Generate shaders to cover all possible cases.
With this change, all the vertex and fragment shaders used by the GL
renderer are now generated based on a program description supplied
by the caller. This allows the renderer to generate a large number
of shaders without having to write all the possible combinations by
hand. The generated shaders are stored in a program cache.
Change-Id: If54d286e77ae021c724d42090da476df12a18ebb
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 2e44e122..0ed6276 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -45,32 +45,22 @@
#define MB(s) s * 1024 * 1024
// Generates simple and textured vertices
-#define SV(x, y) { { x, y } }
#define FV(x, y, u, v) { { x, y }, { u, v } }
///////////////////////////////////////////////////////////////////////////////
// Globals
///////////////////////////////////////////////////////////////////////////////
-static const SimpleVertex gDrawColorVertices[] = {
- SV(0.0f, 0.0f),
- SV(1.0f, 0.0f),
- SV(0.0f, 1.0f),
- SV(1.0f, 1.0f)
-};
-static const GLsizei gDrawColorVertexStride = sizeof(SimpleVertex);
-static const GLsizei gDrawColorVertexCount = 4;
-
// This array is never used directly but used as a memcpy source in the
// OpenGLRenderer constructor
-static const TextureVertex gDrawTextureVertices[] = {
+static const TextureVertex gMeshVertices[] = {
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;
+static const GLsizei gMeshStride = sizeof(TextureVertex);
+static const GLsizei gMeshCount = 4;
// In this array, the index of each Blender equals the value of the first
// entry. For instance, gBlends[1] == gBlends[SkXfermode::kSrc_Mode]
@@ -143,7 +133,18 @@
mLastTexture = 0;
- memcpy(mDrawTextureVertices, gDrawTextureVertices, sizeof(gDrawTextureVertices));
+ memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
+
+ ProgramDescription d;
+ mProgramCache.get(d);
+ d.hasTexture = true;
+ mProgramCache.get(d);
+ d.hasAlpha8Texture = true;
+ d.hasGradient = true;
+ d.hasBitmap = true;
+ d.shadersMode = SkXfermode::kDstOut_Mode;
+ d.colorOp = ProgramDescription::kColorMatrix;
+ mProgramCache.get(d);
}
OpenGLRenderer::~OpenGLRenderer() {
@@ -650,9 +651,13 @@
mModelView.scale(right - left, bottom - top, 1.0f);
if (!useProgram(mDrawColorProgram)) {
- const GLvoid* p = &gDrawColorVertices[0].position[0];
+ const GLvoid* vertices = &mMeshVertices[0].position[0];
+ const GLvoid* texCoords = &mMeshVertices[0].texture[0];
+
glVertexAttribPointer(mDrawColorProgram->position, 2, GL_FLOAT, GL_FALSE,
- gDrawColorVertexStride, p);
+ gMeshStride, vertices);
+ glVertexAttribPointer(mDrawColorProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
+ gMeshStride, texCoords);
}
if (!ignoreTransform) {
@@ -664,7 +669,7 @@
glUniform4f(mDrawColorProgram->color, r, g, b, a);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawColorVertexCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}
void OpenGLRenderer::drawLinearGradientShader(float left, float top, float right, float bottom,
@@ -717,9 +722,9 @@
&screenSpace.data[0]);
glVertexAttribPointer(mDrawLinearGradientProgram->position, 2, GL_FLOAT, GL_FALSE,
- gDrawTextureVertexStride, &mDrawTextureVertices[0].position[0]);
+ gMeshStride, &mMeshVertices[0].position[0]);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
}
void OpenGLRenderer::drawBitmapShader(float left, float top, float right, float bottom,
@@ -757,7 +762,7 @@
resetDrawTextureTexCoords(u1, v1, u2, v2);
drawTextureMesh(left, top, right, bottom, texture->id, alpha, mode, texture->blend,
- &mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
+ &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
}
@@ -769,13 +774,13 @@
getAlphaAndMode(paint, &alpha, &mode);
drawTextureMesh(left, top, right, bottom, texture->id, alpha / 255.0f, mode, texture->blend,
- &mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
+ &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
}
void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom,
GLuint texture, float alpha, SkXfermode::Mode mode, bool blend) {
drawTextureMesh(left, top, right, bottom, texture, alpha, mode, blend,
- &mDrawTextureVertices[0].position[0], &mDrawTextureVertices[0].texture[0], NULL);
+ &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0], NULL);
}
void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float bottom,
@@ -794,12 +799,12 @@
glUniform4f(mDrawTextureProgram->color, alpha, alpha, alpha, alpha);
glVertexAttribPointer(mDrawTextureProgram->position, 2, GL_FLOAT, GL_FALSE,
- gDrawTextureVertexStride, vertices);
+ gMeshStride, vertices);
glVertexAttribPointer(mDrawTextureProgram->texCoords, 2, GL_FLOAT, GL_FALSE,
- gDrawTextureVertexStride, texCoords);
+ gMeshStride, texCoords);
if (!indices) {
- glDrawArrays(GL_TRIANGLE_STRIP, 0, gDrawTextureVertexCount);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount);
} else {
glDrawElements(GL_TRIANGLES, elementsCount, GL_UNSIGNED_SHORT, indices);
}
@@ -842,7 +847,7 @@
}
void OpenGLRenderer::resetDrawTextureTexCoords(float u1, float v1, float u2, float v2) {
- TextureVertex* v = &mDrawTextureVertices[0];
+ TextureVertex* v = &mMeshVertices[0];
TextureVertex::setUV(v++, u1, v1);
TextureVertex::setUV(v++, u2, v1);
TextureVertex::setUV(v++, u1, v2);