Merge "Implement support for drawBitmapMesh's colors array"

This commit is contained in:
Romain Guy
2013-02-14 18:49:34 +00:00
committed by Android (Google) Code Review
9 changed files with 136 additions and 27 deletions

View File

@ -901,9 +901,9 @@ class GLES20Canvas extends HardwareCanvas {
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 {

View File

@ -365,11 +365,12 @@ void Caches::bindPositionVertexPointer(bool force, GLvoid* vertices, GLsizei str
}
}
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::enableTexCoordsVertexArray() {
}
}
void Caches::disbaleTexCoordsVertexArray() {
void Caches::disableTexCoordsVertexArray() {
if (mTexCoordsArrayEnabled) {
glDisableVertexAttribArray(Program::kBindingTexCoords);
mTexCoordsArrayEnabled = false;

View File

@ -183,7 +183,7 @@ public:
* 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 @@ public:
void resetTexCoordsVertexPointer();
void enableTexCoordsVertexArray();
void disbaleTexCoordsVertexArray();
void disableTexCoordsVertexArray();
/**
* Activate the specified texture unit. The texture unit must
@ -299,6 +299,7 @@ private:
void* mCurrentPositionPointer;
GLsizei mCurrentPositionStride;
void* mCurrentTexCoordsPointer;
GLsizei mCurrentTexCoordsStride;
bool mTexCoordsArrayEnabled;

View File

@ -317,7 +317,7 @@ void OpenGLRenderer::interrupt() {
mCaches.unbindMeshBuffer();
mCaches.unbindIndicesBuffer();
mCaches.resetVertexPointers();
mCaches.disbaleTexCoordsVertexArray();
mCaches.disableTexCoordsVertexArray();
debugOverdraw(false, false);
}
@ -1469,12 +1469,18 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) {
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 @@ void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint v
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 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
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 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
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 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
}
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 @@ status_t OpenGLRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int mes
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;
}

View File

@ -777,6 +777,7 @@ private:
* 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 @@ private:
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();

View File

@ -81,6 +81,8 @@ namespace uirenderer {
#define PROGRAM_IS_SIMPLE_GRADIENT 41
#define PROGRAM_HAS_COLORS 42
///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////
@ -120,6 +122,9 @@ struct ProgramDescription {
bool hasExternalTexture;
bool hasTextureTransform;
// Color attribute
bool hasColors;
// Modulate, this should only be set when setColor() return true
bool modulate;
@ -164,6 +169,8 @@ struct ProgramDescription {
hasExternalTexture = false;
hasTextureTransform = false;
hasColors = false;
isAA = false;
modulate = false;
@ -259,6 +266,7 @@ struct ProgramDescription {
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;
}

View File

@ -40,6 +40,8 @@ const char* gVS_Header_Attributes =
"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 @@ const char* gVS_Header_Uniforms_HasBitmap =
"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 @@ const char* gVS_Main =
"\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_BitmapShader_Modulate[6] = {
};
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 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
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 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
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 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
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 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
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 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
}
// 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 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
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);

View File

@ -33,7 +33,7 @@ struct Vertex {
}; // 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];
@ -52,6 +52,24 @@ struct TextureVertex {
}
}; // 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.
*/

View File

@ -54,7 +54,7 @@ public class BitmapMeshActivity extends Activity {
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,