diff options
| author | Romain Guy <romainguy@google.com> | 2010-06-28 17:12:22 -0700 |
|---|---|---|
| committer | Romain Guy <romainguy@google.com> | 2010-06-28 17:12:22 -0700 |
| commit | 026c5e16704e817cac7d9c382914c947e34f87e0 (patch) | |
| tree | 6398f104ab860dd65caf02336ea96fff3c79dadf /libs/hwui/OpenGLRenderer.cpp | |
| parent | 4aef697d58bc142b96953cb2623b06981af2abc9 (diff) | |
| download | frameworks_base-026c5e16704e817cac7d9c382914c947e34f87e0.zip frameworks_base-026c5e16704e817cac7d9c382914c947e34f87e0.tar.gz frameworks_base-026c5e16704e817cac7d9c382914c947e34f87e0.tar.bz2 | |
Implement support for PorterDuff's blending modes.
The blending modes are currently hooked up only when drawing filled rects but the
code is reusable for other primitives. This will allow implementation of saveLayer().
This method is required to support the fade effects used throughout the standard
Android UI.
Change-Id: I396023d123436f16cdafc606e358e4eb80c9df2c
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 107 |
1 files changed, 77 insertions, 30 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index e764778..305c8c5 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -40,34 +40,42 @@ namespace uirenderer { // Globals /////////////////////////////////////////////////////////////////////////////// -const SimpleVertex gDrawColorVertices[] = { +static const SimpleVertex gDrawColorVertices[] = { SV(0.0f, 0.0f), SV(1.0f, 0.0f), SV(0.0f, 1.0f), SV(1.0f, 1.0f) }; -const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); -const GLsizei gDrawColorVertexCount = 4; +static const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex); +static const GLsizei gDrawColorVertexCount = 4; -TextureVertex gDrawTextureVertices[] = { +// This array is never used directly but used as a memcpy source in the +// OpenGLRenderer constructor +static const TextureVertex gDrawTextureVertices[] = { FV(0.0f, 0.0f, 0.0f, 1.0f), FV(1.0f, 0.0f, 1.0f, 1.0f), FV(0.0f, 1.0f, 0.0f, 0.0f), FV(1.0f, 1.0f, 1.0f, 0.0f) }; -const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex); -const GLsizei gDrawTextureVertexCount = 4; - -static inline void resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { - gDrawTextureVertices[0].texture[0] = u1; - gDrawTextureVertices[0].texture[1] = v2; - gDrawTextureVertices[1].texture[0] = u2; - gDrawTextureVertices[1].texture[1] = v2; - gDrawTextureVertices[2].texture[0] = u1; - gDrawTextureVertices[2].texture[1] = v1; - gDrawTextureVertices[3].texture[0] = u2; - gDrawTextureVertices[3].texture[1] = v1; -} +static const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex); +static const GLsizei gDrawTextureVertexCount = 4; + +// In this array, the index of each Blender equals the value of the first +// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode] +static const Blender gBlends[] = { + { SkXfermode::kClear_Mode, GL_ZERO, GL_ZERO }, + { SkXfermode::kSrc_Mode, GL_ONE, GL_ZERO }, + { SkXfermode::kDst_Mode, GL_ZERO, GL_ONE }, + { SkXfermode::kSrcOver_Mode, GL_ONE, GL_ONE_MINUS_SRC_ALPHA }, + { SkXfermode::kDstOver_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE }, + { SkXfermode::kSrcIn_Mode, GL_DST_ALPHA, GL_ZERO }, + { SkXfermode::kDstIn_Mode, GL_ZERO, GL_SRC_ALPHA }, + { SkXfermode::kSrcOut_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ZERO }, + { SkXfermode::kDstOut_Mode, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA }, + { SkXfermode::kSrcATop_Mode, GL_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA }, + { SkXfermode::kDstATop_Mode, GL_ONE_MINUS_DST_ALPHA, GL_SRC_ALPHA }, + { SkXfermode::kXor_Mode, GL_ONE_MINUS_DST_ALPHA, GL_ONE_MINUS_SRC_ALPHA } +}; /////////////////////////////////////////////////////////////////////////////// // Constructors/destructor @@ -78,6 +86,8 @@ OpenGLRenderer::OpenGLRenderer() { mDrawColorShader = new DrawColorProgram; mDrawTextureShader = new DrawTextureProgram; + + memcpy(mDrawTextureVertices, gDrawTextureVertices, sizeof(gDrawTextureVertices)); } OpenGLRenderer::~OpenGLRenderer() { @@ -336,22 +346,43 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom) /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { - // TODO: Set the transfer mode const Rect& clip = mSnapshot->clipRect; - drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color); + drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode); } void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, const SkPaint* p) { - // TODO Support more than just color - // TODO: Set the transfer mode - drawColorRect(left, top, right, bottom, p->getColor()); + SkXfermode::Mode mode; + + const bool isMode = SkXfermode::IsMode(p->getXfermode(), &mode); + if (!isMode) { + // Assume SRC_OVER + mode = SkXfermode::kSrcOver_Mode; + } + + // Skia draws using the color's alpha channel if < 255 + // Otherwise, it uses the paint's alpha + int color = p->getColor(); + if (((color >> 24) & 0xFF) == 255) { + color |= p->getAlpha() << 24; + } + + drawColorRect(left, top, right, bottom, color, mode); } -void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color) { - GLfloat a = ((color >> 24) & 0xFF) / 255.0f; - GLfloat r = ((color >> 16) & 0xFF) / 255.0f; - GLfloat g = ((color >> 8) & 0xFF) / 255.0f; - GLfloat b = ((color ) & 0xFF) / 255.0f; +void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, + int color, SkXfermode::Mode mode) { + const int alpha = (color >> 24) & 0xFF; + const bool blend = alpha < 255 || mode != SkXfermode::kSrcOver_Mode; + + const GLfloat a = alpha / 255.0f; + const GLfloat r = ((color >> 16) & 0xFF) / 255.0f; + const GLfloat g = ((color >> 8) & 0xFF) / 255.0f; + const GLfloat b = ((color ) & 0xFF) / 255.0f; + + if (blend) { + glEnable(GL_BLEND); + glBlendFunc(gBlends[mode].src, gBlends[mode].dst); + } mModelView.loadTranslate(left, top, 0.0f); mModelView.scale(right - left, bottom - top, 1.0f); @@ -368,6 +399,10 @@ void OpenGLRenderer::drawColorRect(float left, float top, float right, float bot glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount); glDisableVertexAttribArray(mDrawColorShader->position); + + if (blend) { + glDisable(GL_BLEND); + } } void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, @@ -379,15 +414,16 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b // TODO Correctly set the blend function, based on texture format and xfermode glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + // For not pre-multiplied sources + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBindTexture(GL_TEXTURE_2D, texture); glActiveTexture(GL_TEXTURE0); glUniform1i(mDrawTextureShader->sampler, 0); - const GLvoid* p = &gDrawTextureVertices[0].position[0]; - const GLvoid* t = &gDrawTextureVertices[0].texture[0]; + const GLvoid* p = &mDrawTextureVertices[0].position[0]; + const GLvoid* t = &mDrawTextureVertices[0].texture[0]; glEnableVertexAttribArray(mDrawTextureShader->position); glVertexAttribPointer(mDrawTextureShader->position, 2, GL_FLOAT, GL_FALSE, @@ -408,5 +444,16 @@ void OpenGLRenderer::drawTextureRect(float left, float top, float right, float b glDisable(GL_BLEND); } +void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) { + mDrawTextureVertices[0].texture[0] = u1; + mDrawTextureVertices[0].texture[1] = v2; + mDrawTextureVertices[1].texture[0] = u2; + mDrawTextureVertices[1].texture[1] = v2; + mDrawTextureVertices[2].texture[0] = u1; + mDrawTextureVertices[2].texture[1] = v1; + mDrawTextureVertices[3].texture[0] = u2; + mDrawTextureVertices[3].texture[1] = v1; +} + }; // namespace uirenderer }; // namespace android |
