Merge "Properly support ALPHA_8 bitmaps in all drawBitmap() methods"
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -32,6 +32,15 @@
|
||||
|
||||
<meta-data android:name="android.graphics.renderThread" android:value="true" />
|
||||
|
||||
<activity
|
||||
android:name="Alpha8BitmapActivity"
|
||||
android:label="_Alpha8Bitmap">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name="MipMapActivity"
|
||||
android:label="_MipMap">
|
||||
|
||||
BIN
tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png
Normal file
BIN
tests/HwAccelerationTest/res/drawable-nodpi/spot_mask.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.test.hwui;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.BitmapShader;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.Shader;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
|
||||
@SuppressWarnings({"UnusedDeclaration"})
|
||||
public class Alpha8BitmapActivity extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(new BitmapsView(this));
|
||||
}
|
||||
|
||||
static class BitmapsView extends View {
|
||||
private Paint mBitmapPaint;
|
||||
private final Bitmap mBitmap1;
|
||||
private final float[] mVertices;
|
||||
|
||||
BitmapsView(Context c) {
|
||||
super(c);
|
||||
|
||||
Bitmap texture = BitmapFactory.decodeResource(c.getResources(), R.drawable.spot_mask);
|
||||
mBitmap1 = Bitmap.createBitmap(texture.getWidth(), texture.getHeight(),
|
||||
Bitmap.Config.ALPHA_8);
|
||||
Canvas canvas = new Canvas(mBitmap1);
|
||||
canvas.drawBitmap(texture, 0.0f, 0.0f, null);
|
||||
|
||||
texture = BitmapFactory.decodeResource(c.getResources(), R.drawable.sunset1);
|
||||
BitmapShader shader = new BitmapShader(texture,
|
||||
Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
|
||||
|
||||
final float width = texture.getWidth() / 3.0f;
|
||||
final float height = texture.getHeight() / 3.0f;
|
||||
|
||||
mVertices = new float[] {
|
||||
0.0f, 0.0f, width, 0.0f, width * 2, 0.0f, width * 3, 0.0f,
|
||||
0.0f, height, width, height, width * 2, height, width * 4, height,
|
||||
0.0f, height * 2, width, height * 2, width * 2, height * 2, width * 3, height * 2,
|
||||
0.0f, height * 4, width, height * 4, width * 2, height * 4, width * 4, height * 4,
|
||||
};
|
||||
|
||||
mBitmapPaint = new Paint();
|
||||
mBitmapPaint.setFilterBitmap(true);
|
||||
mBitmapPaint.setShader(shader);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDraw(Canvas canvas) {
|
||||
super.onDraw(canvas);
|
||||
|
||||
canvas.drawColor(0xffffffff);
|
||||
canvas.drawBitmap(mBitmap1, 0.0f, 0.0f, mBitmapPaint);
|
||||
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.setScale(2.0f, 2.0f);
|
||||
matrix.postTranslate(0.0f, mBitmap1.getHeight());
|
||||
canvas.drawBitmap(mBitmap1, matrix, mBitmapPaint);
|
||||
|
||||
Rect src = new Rect(0, 0, mBitmap1.getWidth() / 2, mBitmap1.getHeight() / 2);
|
||||
Rect dst = new Rect(0, mBitmap1.getHeight() * 3, mBitmap1.getWidth(),
|
||||
mBitmap1.getHeight() * 4);
|
||||
canvas.drawBitmap(mBitmap1, src, dst, mBitmapPaint);
|
||||
|
||||
canvas.translate(0.0f, mBitmap1.getHeight() * 4);
|
||||
canvas.drawBitmapMesh(mBitmap1, 3, 3, mVertices, 0, null, 0, mBitmapPaint);
|
||||
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user