summaryrefslogtreecommitdiffstats
path: root/libs/hwui/OpenGLRenderer.cpp
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2010-06-28 17:12:22 -0700
committerRomain Guy <romainguy@google.com>2010-06-28 17:12:22 -0700
commit026c5e16704e817cac7d9c382914c947e34f87e0 (patch)
tree6398f104ab860dd65caf02336ea96fff3c79dadf /libs/hwui/OpenGLRenderer.cpp
parent4aef697d58bc142b96953cb2623b06981af2abc9 (diff)
downloadframeworks_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.cpp107
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