summaryrefslogtreecommitdiff
path: root/libs/hwui/OpenGLRenderer.cpp
diff options
context:
space:
mode:
author Romain Guy <romainguy@google.com> 2013-01-04 15:21:16 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2013-01-04 15:21:36 -0800
commit48f7cfb10622f8675741f36bdf5b1f679e3fe37c (patch)
tree30c94aceb32a956c9af599b9763ec2feafb6230c /libs/hwui/OpenGLRenderer.cpp
parent5c11ef10dbc6734ec028a7112eaaa57920aa184d (diff)
parent886b275e529e44a59c54b933453d9bc902973178 (diff)
Merge "Properly support ALPHA_8 bitmaps in all drawBitmap() methods"
Diffstat (limited to 'libs/hwui/OpenGLRenderer.cpp')
-rw-r--r--libs/hwui/OpenGLRenderer.cpp168
1 files changed, 104 insertions, 64 deletions
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index ca9a38e58757..094e9ab91fa9 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1340,30 +1340,20 @@ void OpenGLRenderer::setupDrawPoint(float pointSize) {
mDescription.pointSize = pointSize;
}
-void OpenGLRenderer::setupDrawColor(int color) {
- setupDrawColor(color, (color >> 24) & 0xFF);
-}
-
void OpenGLRenderer::setupDrawColor(int color, int alpha) {
mColorA = alpha / 255.0f;
- // Second divide of a by 255 is an optimization, allowing us to simply multiply
- // the rgb values by a instead of also dividing by 255
- const float a = mColorA / 255.0f;
- mColorR = a * ((color >> 16) & 0xFF);
- mColorG = a * ((color >> 8) & 0xFF);
- mColorB = a * ((color ) & 0xFF);
+ mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f;
+ mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f;
+ mColorB = mColorA * ((color ) & 0xFF) / 255.0f;
mColorSet = true;
mSetShaderColor = mDescription.setColor(mColorR, mColorG, mColorB, mColorA);
}
void OpenGLRenderer::setupDrawAlpha8Color(int color, int alpha) {
mColorA = alpha / 255.0f;
- // Double-divide of a by 255 is an optimization, allowing us to simply multiply
- // the rgb values by a instead of also dividing by 255
- const float a = mColorA / 255.0f;
- mColorR = a * ((color >> 16) & 0xFF);
- mColorG = a * ((color >> 8) & 0xFF);
- mColorB = a * ((color ) & 0xFF);
+ mColorR = mColorA * ((color >> 16) & 0xFF) / 255.0f;
+ mColorG = mColorA * ((color >> 8) & 0xFF) / 255.0f;
+ mColorB = mColorA * ((color ) & 0xFF) / 255.0f;
mColorSet = true;
mSetShaderColor = mDescription.setAlpha8Color(mColorR, mColorG, mColorB, mColorA);
}
@@ -1625,43 +1615,27 @@ void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, Sk
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
+ int color = paint != NULL ? paint->getColor() : 0;
+
float x = left;
float y = top;
- GLenum filter = GL_LINEAR;
+ texture->setWrap(GL_CLAMP_TO_EDGE, true);
+
bool ignoreTransform = false;
if (mSnapshot->transform->isPureTranslate()) {
x = (int) floorf(left + mSnapshot->transform->getTranslateX() + 0.5f);
y = (int) floorf(top + mSnapshot->transform->getTranslateY() + 0.5f);
ignoreTransform = true;
- filter = GL_NEAREST;
- } else {
- filter = FILTER(paint);
- }
- setupDraw();
- setupDrawWithTexture(true);
- if (paint) {
- setupDrawAlpha8Color(paint->getColor(), alpha);
+ texture->setFilter(GL_NEAREST, true);
+ } else {
+ texture->setFilter(FILTER(paint), true);
}
- setupDrawColorFilter();
- setupDrawShader();
- setupDrawBlending(true, mode);
- setupDrawProgram();
- setupDrawModelView(x, y, x + texture->width, y + texture->height, ignoreTransform);
- setupDrawTexture(texture->id);
- texture->setWrap(GL_CLAMP_TO_EDGE);
- texture->setFilter(filter);
-
- setupDrawPureColorUniforms();
- setupDrawColorFilterUniforms();
- setupDrawShaderUniforms();
- setupDrawMesh(NULL, (GLvoid*) gMeshTextureOffset);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
-
- finishDrawTexture();
+ drawAlpha8TextureMesh(x, y, x + texture->width, y + texture->height, texture->id,
+ paint != NULL, color, alpha, mode, (GLvoid*) NULL,
+ (GLvoid*) gMeshTextureOffset, GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
}
status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint) {
@@ -1704,7 +1678,11 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint*
// to the vertex shader. The save/restore is a bit overkill.
save(SkCanvas::kMatrix_SaveFlag);
concatMatrix(matrix);
- drawTextureRect(0.0f, 0.0f, bitmap->width(), bitmap->height(), texture, paint);
+ if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) {
+ drawAlphaBitmap(texture, 0.0f, 0.0f, paint);
+ } else {
+ drawTextureRect(0.0f, 0.0f, bitmap->width(), bitmap->height(), texture, paint);
+ }
restore();
return DrawGlInfo::kStatusDrew;
@@ -1722,7 +1700,11 @@ status_t OpenGLRenderer::drawBitmapData(SkBitmap* bitmap, float left, float top,
Texture* texture = mCaches.textureCache.getTransient(bitmap);
const AutoTexture autoCleanup(texture);
- drawTextureRect(left, top, right, bottom, texture, paint);
+ if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) {
+ drawAlphaBitmap(texture, left, top, paint);
+ } else {
+ drawTextureRect(left, top, right, bottom, texture, paint);
+ }
return DrawGlInfo::kStatusDrew;
}
@@ -1836,26 +1818,59 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
texture->setWrap(GL_CLAMP_TO_EDGE, true);
- if (CC_LIKELY(mSnapshot->transform->isPureTranslate())) {
- const float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
- const float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
+ float scaleX = (dstRight - dstLeft) / (srcRight - srcLeft);
+ float scaleY = (dstBottom - dstTop) / (srcBottom - srcTop);
- GLenum filter = GL_NEAREST;
- // Enable linear filtering if the source rectangle is scaled
- if (srcRight - srcLeft != dstRight - dstLeft || srcBottom - srcTop != dstBottom - dstTop) {
- filter = FILTER(paint);
- }
+ bool scaled = scaleX != 1.0f || scaleY != 1.0f;
+ // Apply a scale transform on the canvas only when a shader is in use
+ // Skia handles the ratio between the dst and src rects as a scale factor
+ // when a shader is set
+ bool useScaleTransform = mShader && scaled;
+ bool ignoreTransform = false;
- texture->setFilter(filter, true);
- drawTextureMesh(x, y, x + (dstRight - dstLeft), y + (dstBottom - dstTop),
- texture->id, alpha / 255.0f, mode, texture->blend,
- &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
- GL_TRIANGLE_STRIP, gMeshCount, false, true);
+ if (CC_LIKELY(mSnapshot->transform->isPureTranslate() && !useScaleTransform)) {
+ float x = (int) floorf(dstLeft + mSnapshot->transform->getTranslateX() + 0.5f);
+ float y = (int) floorf(dstTop + mSnapshot->transform->getTranslateY() + 0.5f);
+
+ dstRight = x + (dstRight - dstLeft);
+ dstBottom = y + (dstBottom - dstTop);
+
+ dstLeft = x;
+ dstTop = y;
+
+ texture->setFilter(scaled ? FILTER(paint) : GL_NEAREST, true);
+ ignoreTransform = true;
} else {
texture->setFilter(FILTER(paint), true);
- drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom, texture->id, alpha / 255.0f,
- mode, texture->blend, &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
- GL_TRIANGLE_STRIP, gMeshCount);
+ }
+
+ if (CC_UNLIKELY(useScaleTransform)) {
+ save(SkCanvas::kMatrix_SaveFlag);
+ translate(dstLeft, dstTop);
+ scale(scaleX, scaleY);
+
+ dstLeft = 0.0f;
+ dstTop = 0.0f;
+
+ dstRight = srcRight - srcLeft;
+ dstBottom = srcBottom - srcTop;
+ }
+
+ if (CC_UNLIKELY(bitmap->getConfig() == SkBitmap::kA8_Config)) {
+ int color = paint ? paint->getColor() : 0;
+ drawAlpha8TextureMesh(dstLeft, dstTop, dstRight, dstBottom,
+ texture->id, paint != NULL, color, alpha, mode,
+ &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+ GL_TRIANGLE_STRIP, gMeshCount, ignoreTransform);
+ } else {
+ drawTextureMesh(dstLeft, dstTop, dstRight, dstBottom,
+ texture->id, alpha / 255.0f, mode, texture->blend,
+ &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0],
+ GL_TRIANGLE_STRIP, gMeshCount, false, ignoreTransform);
+ }
+
+ if (CC_UNLIKELY(useScaleTransform)) {
+ restore();
}
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
@@ -3094,17 +3109,15 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
setupDrawColorFilter();
setupDrawBlending(blend, mode, swapSrcDst);
setupDrawProgram();
- if (!dirty) {
- setupDrawDirtyRegionsDisabled();
- }
+ if (!dirty) setupDrawDirtyRegionsDisabled();
if (!ignoreScale) {
setupDrawModelView(left, top, right, bottom, ignoreTransform);
} else {
setupDrawModelViewTranslate(left, top, right, bottom, ignoreTransform);
}
+ setupDrawTexture(texture);
setupDrawPureColorUniforms();
setupDrawColorFilterUniforms();
- setupDrawTexture(texture);
setupDrawMesh(vertices, texCoords, vbo);
glDrawArrays(drawMode, 0, elementsCount);
@@ -3112,6 +3125,33 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b
finishDrawTexture();
}
+void OpenGLRenderer::drawAlpha8TextureMesh(float left, float top, float right, float bottom,
+ GLuint texture, bool hasColor, int color, int alpha, SkXfermode::Mode mode,
+ GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount,
+ bool ignoreTransform, bool dirty) {
+
+ setupDraw();
+ setupDrawWithTexture(true);
+ if (hasColor) {
+ setupDrawAlpha8Color(color, alpha);
+ }
+ setupDrawColorFilter();
+ setupDrawShader();
+ setupDrawBlending(true, mode);
+ setupDrawProgram();
+ if (!dirty) setupDrawDirtyRegionsDisabled();
+ setupDrawModelView(left, top, right, bottom, ignoreTransform);
+ setupDrawTexture(texture);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderUniforms();
+ setupDrawMesh(vertices, texCoords);
+
+ glDrawArrays(drawMode, 0, elementsCount);
+
+ finishDrawTexture();
+}
+
void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
ProgramDescription& description, bool swapSrcDst) {
blend = blend || mode != SkXfermode::kSrcOver_Mode;