am 10c0aa24: Merge "Implement support for drawBitmapMesh\'s colors array"
# Via Android (Google) Code Review (1) and Romain Guy (1)
* commit '10c0aa246d9b2633c6cb4e5b714abb0031a4f4cd':
Implement support for drawBitmapMesh's colors array
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ec7c65a..06e7116 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -901,9 +901,9 @@
final int count = (meshWidth + 1) * (meshHeight + 1);
checkRange(verts.length, vertOffset, count * 2);
- // TODO: Colors are ignored for now
- colors = null;
- colorOffset = 0;
+ if (colors != null) {
+ checkRange(colors.length, colorOffset, count);
+ }
int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
try {
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 74201d1..88f1d83 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -365,11 +365,12 @@
}
}
-void Caches::bindTexCoordsVertexPointer(bool force, GLvoid* vertices) {
- if (force || vertices != mCurrentTexCoordsPointer) {
+void Caches::bindTexCoordsVertexPointer(bool force, GLvoid* vertices, GLsizei stride) {
+ if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
GLuint slot = currentProgram->texCoords;
- glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, gMeshStride, vertices);
+ glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
mCurrentTexCoordsPointer = vertices;
+ mCurrentTexCoordsStride = stride;
}
}
@@ -390,7 +391,7 @@
}
}
-void Caches::disbaleTexCoordsVertexArray() {
+void Caches::disableTexCoordsVertexArray() {
if (mTexCoordsArrayEnabled) {
glDisableVertexAttribArray(Program::kBindingTexCoords);
mTexCoordsArrayEnabled = false;
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index d70c0e3..0ca2ffd 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -183,7 +183,7 @@
* Binds an attrib to the specified float vertex pointer.
* Assumes a stride of gMeshStride and a size of 2.
*/
- void bindTexCoordsVertexPointer(bool force, GLvoid* vertices);
+ void bindTexCoordsVertexPointer(bool force, GLvoid* vertices, GLsizei stride = gMeshStride);
/**
* Resets the vertex pointers.
@@ -192,7 +192,7 @@
void resetTexCoordsVertexPointer();
void enableTexCoordsVertexArray();
- void disbaleTexCoordsVertexArray();
+ void disableTexCoordsVertexArray();
/**
* Activate the specified texture unit. The texture unit must
@@ -299,6 +299,7 @@
void* mCurrentPositionPointer;
GLsizei mCurrentPositionStride;
void* mCurrentTexCoordsPointer;
+ GLsizei mCurrentTexCoordsStride;
bool mTexCoordsArrayEnabled;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2431e54..f0d25e1 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -317,7 +317,7 @@
mCaches.unbindMeshBuffer();
mCaches.unbindIndicesBuffer();
mCaches.resetVertexPointers();
- mCaches.disbaleTexCoordsVertexArray();
+ mCaches.disableTexCoordsVertexArray();
debugOverdraw(false, false);
}
@@ -1469,12 +1469,18 @@
mDescription.hasAlpha8Texture = isAlpha8;
}
+void OpenGLRenderer::setupDrawWithTextureAndColor(bool isAlpha8) {
+ mDescription.hasTexture = true;
+ mDescription.hasColors = true;
+ mDescription.hasAlpha8Texture = isAlpha8;
+}
+
void OpenGLRenderer::setupDrawWithExternalTexture() {
mDescription.hasExternalTexture = true;
}
void OpenGLRenderer::setupDrawNoTexture() {
- mCaches.disbaleTexCoordsVertexArray();
+ mCaches.disableTexCoordsVertexArray();
}
void OpenGLRenderer::setupDrawAA() {
@@ -1682,6 +1688,23 @@
mCaches.unbindIndicesBuffer();
}
+void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors) {
+ bool force = mCaches.unbindMeshBuffer();
+ GLsizei stride = sizeof(ColorTextureVertex);
+
+ mCaches.bindPositionVertexPointer(force, vertices, stride);
+ if (mCaches.currentProgram->texCoords >= 0) {
+ mCaches.bindTexCoordsVertexPointer(force, texCoords, stride);
+ }
+ int slot = mCaches.currentProgram->getAttrib("colors");
+ if (slot >= 0) {
+ glEnableVertexAttribArray(slot);
+ glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors);
+ }
+
+ mCaches.unbindIndicesBuffer();
+}
+
void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords) {
bool force = mCaches.unbindMeshBuffer();
mCaches.bindPositionVertexPointer(force, vertices);
@@ -1833,9 +1856,16 @@
const uint32_t count = meshWidth * meshHeight * 6;
- // TODO: Support the colors array
- TextureVertex mesh[count];
- TextureVertex* vertex = mesh;
+ ColorTextureVertex mesh[count];
+ ColorTextureVertex* vertex = mesh;
+
+ bool cleanupColors = false;
+ if (!colors) {
+ uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1);
+ colors = new int[colorsCount];
+ memset(colors, 0xff, colorsCount * sizeof(int));
+ cleanupColors = true;
+ }
for (int32_t y = 0; y < meshHeight; y++) {
for (int32_t x = 0; x < meshWidth; x++) {
@@ -1855,13 +1885,13 @@
int dx = i + (meshWidth + 1) * 2 + 2;
int dy = dx + 1;
- TextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2);
- TextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1);
- TextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1);
+ ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
+ ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
+ ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
- TextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2);
- TextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1);
- TextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2);
+ ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
+ ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
+ ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);
left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx])));
top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy])));
@@ -1871,12 +1901,16 @@
}
if (quickReject(left, top, right, bottom)) {
+ if (cleanupColors) delete[] colors;
return DrawGlInfo::kStatusDone;
}
mCaches.activeTexture(0);
Texture* texture = mCaches.textureCache.get(bitmap);
- if (!texture) return DrawGlInfo::kStatusDone;
+ if (!texture) {
+ if (cleanupColors) delete[] colors;
+ return DrawGlInfo::kStatusDone;
+ }
const AutoTexture autoCleanup(texture);
texture->setWrap(GL_CLAMP_TO_EDGE, true);
@@ -1886,13 +1920,35 @@
SkXfermode::Mode mode;
getAlphaAndMode(paint, &alpha, &mode);
+ float a = alpha / 255.0f;
+
if (hasLayer()) {
dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
}
- drawTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f,
- mode, texture->blend, &mesh[0].position[0], &mesh[0].texture[0],
- GL_TRIANGLES, count, false, false, 0, false, false);
+ setupDraw();
+ setupDrawWithTextureAndColor();
+ setupDrawColor(a, a, a, a);
+ setupDrawColorFilter();
+ setupDrawBlending(true, mode, false);
+ setupDrawProgram();
+ setupDrawDirtyRegionsDisabled();
+ setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, false);
+ setupDrawTexture(texture->id);
+ setupDrawPureColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0], &mesh[0].color[0]);
+
+ glDrawArrays(GL_TRIANGLES, 0, count);
+
+ finishDrawTexture();
+
+ int slot = mCaches.currentProgram->getAttrib("colors");
+ if (slot >= 0) {
+ glDisableVertexAttribArray(slot);
+ }
+
+ if (cleanupColors) delete[] colors;
return DrawGlInfo::kStatusDrew;
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0ad81c1..ad80d36 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -777,6 +777,7 @@
* Various methods to setup OpenGL rendering.
*/
void setupDrawWithTexture(bool isAlpha8 = false);
+ void setupDrawWithTextureAndColor(bool isAlpha8 = false);
void setupDrawWithExternalTexture();
void setupDrawNoTexture();
void setupDrawAA();
@@ -811,6 +812,7 @@
void setupDrawTextureTransformUniforms(mat4& transform);
void setupDrawTextGammaUniforms();
void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
+ void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords);
void setupDrawVertices(GLvoid* vertices);
void finishDrawTexture();
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index b1df980..7b67b3c 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -81,6 +81,8 @@
#define PROGRAM_IS_SIMPLE_GRADIENT 41
+#define PROGRAM_HAS_COLORS 42
+
///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////
@@ -120,6 +122,9 @@
bool hasExternalTexture;
bool hasTextureTransform;
+ // Color attribute
+ bool hasColors;
+
// Modulate, this should only be set when setColor() return true
bool modulate;
@@ -164,6 +169,8 @@
hasExternalTexture = false;
hasTextureTransform = false;
+ hasColors = false;
+
isAA = false;
modulate = false;
@@ -259,6 +266,7 @@
if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
+ if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
return key;
}
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index fb00335..74d598d 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -40,6 +40,8 @@
"attribute vec4 position;\n";
const char* gVS_Header_Attributes_TexCoords =
"attribute vec2 texCoords;\n";
+const char* gVS_Header_Attributes_Colors =
+ "attribute vec4 colors;\n";
const char* gVS_Header_Attributes_AAVertexShapeParameters =
"attribute float vtxAlpha;\n";
const char* gVS_Header_Uniforms_TextureTransform =
@@ -65,6 +67,8 @@
"uniform mediump vec2 textureDimension;\n";
const char* gVS_Header_Varyings_HasTexture =
"varying vec2 outTexCoords;\n";
+const char* gVS_Header_Varyings_HasColors =
+ "varying vec4 outColors;\n";
const char* gVS_Header_Varyings_IsAAVertexShape =
"varying float alpha;\n";
const char* gVS_Header_Varyings_HasBitmap =
@@ -94,6 +98,8 @@
"\nvoid main(void) {\n";
const char* gVS_Main_OutTexCoords =
" outTexCoords = texCoords;\n";
+const char* gVS_Main_OutColors =
+ " outColors = colors;\n";
const char* gVS_Main_OutTransformedTexCoords =
" outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
const char* gVS_Main_OutGradient[6] = {
@@ -325,6 +331,8 @@
};
const char* gFS_Main_FragColor =
" gl_FragColor = fragColor;\n";
+const char* gFS_Main_FragColor_HasColors =
+ " gl_FragColor *= outColors;\n";
const char* gFS_Main_FragColor_Blend =
" gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
const char* gFS_Main_FragColor_Blend_Swap =
@@ -459,6 +467,9 @@
if (description.isAA) {
shader.append(gVS_Header_Attributes_AAVertexShapeParameters);
}
+ if (description.hasColors) {
+ shader.append(gVS_Header_Attributes_Colors);
+ }
// Uniforms
shader.append(gVS_Header_Uniforms);
if (description.hasTextureTransform) {
@@ -480,6 +491,9 @@
if (description.isAA) {
shader.append(gVS_Header_Varyings_IsAAVertexShape);
}
+ if (description.hasColors) {
+ shader.append(gVS_Header_Varyings_HasColors);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
}
@@ -499,6 +513,9 @@
if (description.isAA) {
shader.append(gVS_Main_AAVertexShape);
}
+ if (description.hasColors) {
+ shader.append(gVS_Main_OutColors);
+ }
if (description.hasBitmap) {
shader.append(description.isPoint ?
gVS_Main_OutPointBitmapTexCoords :
@@ -549,6 +566,9 @@
if (description.isAA) {
shader.append(gVS_Header_Varyings_IsAAVertexShape);
}
+ if (description.hasColors) {
+ shader.append(gVS_Header_Varyings_HasColors);
+ }
if (description.hasGradient) {
shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
}
@@ -583,7 +603,7 @@
}
// Optimization for common cases
- if (!description.isAA && !blendFramebuffer &&
+ if (!description.isAA && !blendFramebuffer && !description.hasColors &&
description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
bool fast = false;
@@ -729,6 +749,9 @@
shader.append(!description.swapSrcDst ?
gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap);
}
+ if (description.hasColors) {
+ shader.append(gFS_Main_FragColor_HasColors);
+ }
}
// End the shader
shader.append(gFS_Footer);
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index c120428..523120e 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -33,7 +33,7 @@
}; // struct Vertex
/**
- * Simple structure to describe a vertex with a position and a texture.
+ * Simple structure to describe a vertex with a position and texture UV.
*/
struct TextureVertex {
float position[2];
@@ -53,6 +53,24 @@
}; // struct TextureVertex
/**
+ * Simple structure to describe a vertex with a position, texture UV and ARGB color.
+ */
+struct ColorTextureVertex : TextureVertex {
+ float color[4];
+
+ static inline void set(ColorTextureVertex* vertex, float x, float y,
+ float u, float v, int color) {
+ TextureVertex::set(vertex, x, y, u, v);
+
+ const float a = ((color >> 24) & 0xff) / 255.0f;
+ vertex[0].color[0] = a * ((color >> 16) & 0xff) / 255.0f;
+ vertex[0].color[1] = a * ((color >> 8) & 0xff) / 255.0f;
+ vertex[0].color[2] = a * ((color ) & 0xff) / 255.0f;
+ vertex[0].color[3] = a;
+ }
+}; // struct ColorTextureVertex
+
+/**
* Simple structure to describe a vertex with a position and an alpha value.
*/
struct AlphaVertex : Vertex {
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
index 854dd69..69d34a5 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
@@ -54,7 +54,7 @@
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,
};
-
+
mColors = new int[] {
0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000,
0xff0000ff, 0xffff0000, 0xff00ff00, 0xff00ff00,