summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2010-07-09 13:25:56 -0700
committerRomain Guy <romainguy@google.com>2010-07-09 13:25:56 -0700
commit82ba814ca0dea659be2cc6523bc0137679d961ce (patch)
tree93d2375615c7c67ccda0506376eef2079366fa5b /libs/hwui
parent020057bd534a41080af8edbe6c6565d478ef256c (diff)
downloadframeworks_base-82ba814ca0dea659be2cc6523bc0137679d961ce.zip
frameworks_base-82ba814ca0dea659be2cc6523bc0137679d961ce.tar.gz
frameworks_base-82ba814ca0dea659be2cc6523bc0137679d961ce.tar.bz2
Optimize blending state changes.
Change-Id: I7c22a8aecccb8b5abfcf7243f049a4ef3cf3979a
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/OpenGLRenderer.cpp96
-rw-r--r--libs/hwui/OpenGLRenderer.h46
-rw-r--r--libs/hwui/Vertex.h5
3 files changed, 97 insertions, 50 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 34da572..4423b7e 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -95,6 +95,7 @@ static const Blender gBlends[] = {
///////////////////////////////////////////////////////////////////////////////
OpenGLRenderer::OpenGLRenderer():
+ mBlend(false), mLastSrcMode(GL_ZERO), mLastDstMode(GL_ZERO),
mTextureCache(MB(DEFAULT_TEXTURE_CACHE_SIZE)),
mLayerCache(MB(DEFAULT_LAYER_CACHE_SIZE)),
mPatchCache(DEFAULT_PATCH_CACHE_SIZE) {
@@ -242,7 +243,7 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
const Rect& rect = layer->layer;
drawTextureRect(rect.left, rect.top, rect.right, rect.bottom,
- layer->texture, layer->alpha, layer->mode, layer->blend, true);
+ layer->texture, layer->alpha, layer->mode, layer->blend);
LayerSize size(rect.getWidth(), rect.getHeight());
// Failing to add the layer to the cache should happen only if the
@@ -421,13 +422,7 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
const Texture* texture = mTextureCache.get(bitmap);
-
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
- drawTextureRect(left, top, left + texture->width, top + texture->height, texture->id,
- alpha / 255.0f, mode, texture->blend, true);
+ drawTextureRect(left, top, left + texture->width, top + texture->height, texture, paint);
}
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) {
@@ -436,13 +431,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const
transform.mapRect(r);
const Texture* texture = mTextureCache.get(bitmap);
-
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
- drawTextureRect(r.left, r.top, r.right, r.bottom, texture->id,
- alpha / 255.0f, mode, texture->blend, true);
+ drawTextureRect(r.left, r.top, r.right, r.bottom, texture, paint);
}
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
@@ -451,10 +440,6 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
const SkPaint* paint) {
const Texture* texture = mTextureCache.get(bitmap);
- int alpha;
- SkXfermode::Mode mode;
- getAlphaAndMode(paint, &alpha, &mode);
-
const float width = texture->width;
const float height = texture->height;
@@ -465,8 +450,7 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
resetDrawTextureTexCoords(u1, v1, u2, v2);
- drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture->id,
- alpha / 255.0f, mode, texture->blend, true);
+ drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture, paint);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -606,17 +590,12 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom,
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);
- }
+ chooseBlending(alpha < 255, mode, true);
mModelView.loadTranslate(left, top, 0.0f);
mModelView.scale(right - left, bottom - top, 1.0f);
@@ -633,10 +612,17 @@ 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,
+ const Texture* texture, const SkPaint* paint, bool isPremultiplied) {
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend,
+ isPremultiplied, &mDrawTextureVertices[0].position[0],
+ &mDrawTextureVertices[0].texture[0], NULL);
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
@@ -653,15 +639,7 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
- if (blend || alpha < 1.0f || mode != SkXfermode::kSrcOver_Mode) {
- GLenum sourceMode = gBlends[mode].src;
- if (!isPremultiplied && sourceMode == GL_ONE) {
- sourceMode = GL_SRC_ALPHA;
- }
-
- glEnable(GL_BLEND);
- glBlendFunc(sourceMode, gBlends[mode].dst);
- }
+ chooseBlending(blend || alpha < 1.0f, mode, isPremultiplied);
glBindTexture(GL_TEXTURE_2D, texture);
@@ -690,18 +668,40 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
glDisableVertexAttribArray(mDrawTextureShader->texCoords);
glBindTexture(GL_TEXTURE_2D, 0);
- glDisable(GL_BLEND);
+}
+
+void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied) {
+ // In theory we should not blend if the mode is Src, but it's rare enough
+ // that it's not worth it
+ blend = blend || mode != SkXfermode::kSrcOver_Mode;
+ if (blend) {
+ if (!mBlend) {
+ glEnable(GL_BLEND);
+ }
+
+ GLenum sourceMode = gBlends[mode].src;
+ GLenum destMode = gBlends[mode].dst;
+ if (!isPremultiplied && sourceMode == GL_ONE) {
+ sourceMode = GL_SRC_ALPHA;
+ }
+
+ if (sourceMode != mLastSrcMode || destMode != mLastDstMode) {
+ glBlendFunc(sourceMode, destMode);
+ mLastSrcMode = sourceMode;
+ mLastDstMode = destMode;
+ }
+ } else if (mBlend) {
+ glDisable(GL_BLEND);
+ }
+ mBlend = blend;
}
void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
- mDrawTextureVertices[0].texture[0] = u1;
- mDrawTextureVertices[0].texture[1] = v1;
- mDrawTextureVertices[1].texture[0] = u2;
- mDrawTextureVertices[1].texture[1] = v1;
- mDrawTextureVertices[2].texture[0] = u1;
- mDrawTextureVertices[2].texture[1] = v2;
- mDrawTextureVertices[3].texture[0] = u2;
- mDrawTextureVertices[3].texture[1] = v2;
+ TextureVertex* v = &mDrawTextureVertices[0];
+ TextureVertex::setUV(v++, u1, v1);
+ TextureVertex::setUV(v++, u2, v1);
+ TextureVertex::setUV(v++, u1, v2);
+ TextureVertex::setUV(v++, u2, v2);
}
void OpenGLRenderer::getAlphaAndMode(const SkPaint* paint, int* alpha, SkXfermode::Mode* mode) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index b46e9d3..6527cae 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -179,10 +179,40 @@ private:
* @param isPremultiplied Indicates whether the texture has premultiplied alpha
*/
void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
- float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = false);
+ float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = true);
/**
- * TODO: documentation
+ * Draws a textured rectangle with the specified texture. The specified coordinates
+ * are transformed by the current snapshot's transform matrix.
+ *
+ * @param left The left coordinate of the rectangle
+ * @param top The top coordinate of the rectangle
+ * @param right The right coordinate of the rectangle
+ * @param bottom The bottom coordinate of the rectangle
+ * @param texture The texture to use
+ * @param paint The paint containing the alpha, blending mode, etc.
+ * @param isPremultiplied Indicates whether the texture has premultiplied alpha
+ */
+ void drawTextureRect(float left, float top, float right, float bottom, const Texture* texture,
+ const SkPaint* paint, bool isPremultiplied = true);
+
+ /**
+ * Draws a textured mesh with the specified texture. If the indices are omitted, the
+ * mesh is drawn as a simple quad.
+ *
+ * @param left The left coordinate of the rectangle
+ * @param top The top coordinate of the rectangle
+ * @param right The right coordinate of the rectangle
+ * @param bottom The bottom coordinate of the rectangle
+ * @param texture The texture name to map onto the rectangle
+ * @param alpha An additional translucency parameter, between 0.0f and 1.0f
+ * @param mode The blending mode
+ * @param blend True if the texture contains an alpha channel
+ * @param isPremultiplied Indicates whether the texture has premultiplied alpha
+ * @param vertices The vertices that define the mesh
+ * @param texCoords The texture coordinates of each vertex
+ * @param indices The indices of the vertices, can be NULL
+ * @param elementsCount The number of elements in the mesh, required by indices
*/
void drawTextureMesh(float left, float top, float right, float bottom, GLuint texture,
float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied,
@@ -217,6 +247,12 @@ private:
inline void generateVertices(TextureVertex* vertex, float y, float v, const int32_t xDivs[],
uint32_t xCount, float xStretch, float xStretchTex, float width, float widthTex);
+ /**
+ * Enable or disable blending as necessary. This function sets the appropriate
+ * blend function based on the specified xfermode.
+ */
+ inline void chooseBlending(bool blend, SkXfermode::Mode mode, bool isPremultiplied);
+
// Dimensions of the drawing surface
int mWidth, mHeight;
@@ -240,6 +276,12 @@ private:
// Used to draw textured quads
TextureVertex mDrawTextureVertices[4];
+ // Last known blend state
+ bool mBlend;
+ GLenum mLastSrcMode;
+ GLenum mLastDstMode;
+
+ // Various caches
TextureCache mTextureCache;
LayerCache mLayerCache;
PatchCache mPatchCache;
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index 208d2a8..ffd0633 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -41,6 +41,11 @@ struct TextureVertex {
vertex[0].texture[0] = u;
vertex[0].texture[1] = v;
}
+
+ static inline void setUV(TextureVertex* vertex, float u, float v) {
+ vertex[0].texture[0] = u;
+ vertex[0].texture[1] = v;
+ }
}; // struct TextureVertex
}; // namespace uirenderer