From 886b275e529e44a59c54b933453d9bc902973178 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Fri, 4 Jan 2013 12:26:18 -0800 Subject: [PATCH] Properly support ALPHA_8 bitmaps in all drawBitmap() methods Change-Id: I869993c59e0a0d76f369c09acbae711753908f48 --- libs/hwui/OpenGLRenderer.cpp | 168 +++++++++++------- libs/hwui/OpenGLRenderer.h | 6 +- tests/HwAccelerationTest/AndroidManifest.xml | 9 + .../res/drawable-nodpi/spot_mask.png | Bin 0 -> 25505 bytes .../test/hwui/Alpha8BitmapActivity.java | 97 ++++++++++ 5 files changed, 215 insertions(+), 65 deletions(-) create mode 100644 tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png create mode 100644 tests/HwAccelerationTest/src/com/android/test/hwui/Alpha8BitmapActivity.java diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ca9a38e58757e..094e9ab91fa91 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; + + texture->setFilter(GL_NEAREST, true); } else { - filter = FILTER(paint); + texture->setFilter(FILTER(paint), true); } - setupDraw(); - setupDrawWithTexture(true); - if (paint) { - setupDrawAlpha8Color(paint->getColor(), alpha); - } - 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; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index f16558174b17b..3cafed361e66a 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -596,6 +596,11 @@ private: bool swapSrcDst = false, bool ignoreTransform = false, GLuint vbo = 0, bool ignoreScale = false, bool dirty = true); + void 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 = true); + /** * Draws text underline and strike-through if needed. * @@ -700,7 +705,6 @@ private: void setupDrawAA(); void setupDrawVertexShape(); void setupDrawPoint(float pointSize); - void setupDrawColor(int color); void setupDrawColor(int color, int alpha); void setupDrawColor(float r, float g, float b, float a); void setupDrawAlpha8Color(int color, int alpha); diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 9118aea1f575d..1974e0fc9f4e6 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -32,6 +32,15 @@ + + + + + + + diff --git a/tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png b/tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png new file mode 100644 index 0000000000000000000000000000000000000000..89537594e1a663273b598b986ed733f6ae9e867f GIT binary patch literal 25505 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