Add implementation for drawBitmap().
Change-Id: Iada9325f3c5642b61c2e0c4cd80bcfbc92cb491e
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index d8023859..3010f29 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -54,10 +54,10 @@
// 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)
+ FV(0.0f, 0.0f, 0.0f, 0.0f),
+ FV(1.0f, 0.0f, 1.0f, 0.0f),
+ FV(0.0f, 1.0f, 0.0f, 1.0f),
+ FV(1.0f, 1.0f, 1.0f, 1.0f)
};
static const GLsizei gDrawTextureVertexStride = sizeof(TextureVertex);
static const GLsizei gDrawTextureVertexCount = 4;
@@ -208,7 +208,7 @@
resetDrawTextureTexCoords(u1, v1, u2, v1);
drawTextureRect(layer.left, layer.top, layer.right, layer.bottom,
- current->texture, current->alpha, current->mode, true);
+ current->texture, current->alpha, current->mode, true, true);
resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f);
@@ -378,8 +378,33 @@
// Drawing
///////////////////////////////////////////////////////////////////////////////
-void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
- LOGD("Drawing bitmap!");
+void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
+ Texture* texture = mTextureCache.get(bitmap);
+
+ SkXfermode::Mode mode;
+ int alpha;
+
+ if (paint) {
+ const bool isMode = SkXfermode::IsMode(paint->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 = paint->getColor();
+ alpha = (color >> 24) & 0xFF;
+ if (alpha == 255) {
+ alpha = paint->getAlpha();
+ }
+ } else {
+ mode = SkXfermode::kSrcOver_Mode;
+ alpha = 255;
+ }
+
+ drawTextureRect(left, top, left + texture->width, top + texture->height, texture->id,
+ alpha / 255.0f, mode, texture->blend, true);
}
void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) {
@@ -443,23 +468,26 @@
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
- GLuint texture, float alpha, SkXfermode::Mode mode, bool isPremultiplied) {
+ GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied) {
mModelView.loadTranslate(left, top, 0.0f);
mModelView.scale(right - left, bottom - top, 1.0f);
mDrawTextureShader->use(&mOrthoMatrix[0], &mModelView.data[0], &mSnapshot->transform.data[0]);
- GLenum sourceMode = gBlends[mode].src;
- if (!isPremultiplied && sourceMode == GL_ONE) {
- sourceMode = GL_SRC_ALPHA;
+ 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);
}
- // TODO: Try to disable blending when the texture is opaque and alpha == 1.0f
- glEnable(GL_BLEND);
- glBlendFunc(sourceMode, gBlends[mode].dst);
-
glBindTexture(GL_TEXTURE_2D, texture);
+ // TODO handle tiling and filtering here
+
glActiveTexture(GL_TEXTURE0);
glUniform1i(mDrawTextureShader->sampler, 0);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index e5cc98c..965188f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -102,7 +102,7 @@
bool quickReject(float left, float top, float right, float bottom);
bool clipRect(float left, float top, float right, float bottom);
- void drawBitmap(const SkBitmap* bitmap, float left, float top, const SkPaint* paint);
+ void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
void drawColor(int color, SkXfermode::Mode mode);
void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
@@ -183,10 +183,11 @@
* @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
*/
void drawTextureRect(float left, float top, float right, float bottom, GLuint texture,
- float alpha, SkXfermode::Mode mode, bool isPremultiplied = false);
+ float alpha, SkXfermode::Mode mode, bool blend, bool isPremultiplied = false);
/**
* Resets the texture coordinates stored in mDrawTextureVertices. Setting the values
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index c3b1463..4e16507 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -41,7 +41,7 @@
Texture* texture = mCache.get(bitmap);
if (!texture) {
texture = new Texture;
- generateTexture(bitmap, texture);
+ generateTexture(bitmap, texture, false);
mCache.put(bitmap, texture);
} else if (bitmap->getGenerationID() != texture->generation) {
generateTexture(bitmap, texture, true);
@@ -58,7 +58,14 @@
}
void TextureCache::generateTexture(SkBitmap* bitmap, Texture* texture, bool regenerate) {
+ SkAutoLockPixels alp(*bitmap);
+ if (!bitmap->readyToDraw()) {
+ LOGE("Cannot generate texture from bitmap");
+ return;
+ }
+
if (!regenerate) {
+ texture->generation = bitmap->getGenerationID();
texture->width = bitmap->width();
texture->height = bitmap->height();
@@ -66,25 +73,28 @@
}
glBindTexture(GL_TEXTURE_2D, texture->id);
+ glPixelStorei(GL_UNPACK_ALIGNMENT, bitmap->bytesPerPixel());
+
+ switch (bitmap->getConfig()) {
+ case SkBitmap::kRGB_565_Config:
+ texture->blend = false;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, bitmap->rowBytesAsPixels(), texture->height, 0,
+ GL_RGB, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
+ break;
+ case SkBitmap::kARGB_8888_Config:
+ texture->blend = true;
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, bitmap->rowBytesAsPixels(), texture->height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
+ break;
+ default:
+ break;
+ }
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- switch (bitmap->getConfig()) {
- case SkBitmap::kRGB_565_Config:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB565, texture->width, texture->height,
- 0, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, bitmap->getPixels());
- break;
- case SkBitmap::kARGB_8888_Config:
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture->width, texture->height,
- 0, GL_RGBA, GL_UNSIGNED_BYTE, bitmap->getPixels());
- break;
- default:
- break;
- }
-
glBindTexture(GL_TEXTURE_2D, 0);
}