From 39284b763a09688468ed3799ebd2ebb76ea5dfd5 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Wed, 26 Sep 2012 16:39:40 -0700 Subject: [PATCH] Make gradients beautiful again Bug #7239634 This change passes two matrices to the vertex shader instead of one. We used to compute the final MVP matrix on the CPU to minimize the number of operations in the vertex shaders. Shader compilers are however smart enough to perform this optimization for us. Since we need the MV matrix to properly compute gradients dithering, this change splits the MVP matrix into two. This has the advantage of removing one matrix multiplication per drawing operation on the CPU. The SGX 540 shader compiler produces the same number of instructions in both cases. There is no penalty hit with having two matrices instead of one. We also send so few vertices per frame that it does not matter very much. Change-Id: I17d47ac4772615418e0e1885b97493d31435a936 --- libs/hwui/Program.cpp | 9 ++++++--- libs/hwui/Program.h | 5 +++++ libs/hwui/ProgramCache.cpp | 15 ++++++++------- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp index 5b1b57d3a6649..f0b5553a79a74 100644 --- a/libs/hwui/Program.cpp +++ b/libs/hwui/Program.cpp @@ -81,6 +81,7 @@ Program::Program(const ProgramDescription& description, const char* vertex, cons if (mInitialized) { transform = addUniform("transform"); + projection = addUniform("projection"); } } @@ -152,18 +153,20 @@ GLuint Program::buildShader(const char* source, GLenum type) { void Program::set(const mat4& projectionMatrix, const mat4& modelViewMatrix, const mat4& transformMatrix, bool offset) { - mat4 t(projectionMatrix); + mat4 p(projectionMatrix); if (offset) { // offset screenspace xy by an amount that compensates for typical precision // issues in GPU hardware that tends to paint hor/vert lines in pixels shifted // up and to the left. // This offset value is based on an assumption that some hardware may use as // little as 12.4 precision, so we offset by slightly more than 1/16. - t.translate(.375, .375, 0); + p.translate(.375, .375, 0); } - t.multiply(transformMatrix); + + mat4 t(transformMatrix); t.multiply(modelViewMatrix); + glUniformMatrix4fv(projection, 1, GL_FALSE, &p.data[0]); glUniformMatrix4fv(transform, 1, GL_FALSE, &t.data[0]); } diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index b1cb446902651..7e3aacf90260a 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -374,6 +374,11 @@ public: */ int transform; + /** + * Name of the projection uniform. + */ + int projection; + protected: /** * Adds an attribute with the specified name. diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 7bc2b376b43b9..f536adeff3742 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -48,6 +48,7 @@ const char* gVS_Header_Attributes_AAVertexShapeParameters = const char* gVS_Header_Uniforms_TextureTransform = "uniform mat4 mainTextureTransform;\n"; const char* gVS_Header_Uniforms = + "uniform mat4 projection;\n" \ "uniform mat4 transform;\n"; const char* gVS_Header_Uniforms_IsPoint = "uniform mediump float pointSize;\n"; @@ -104,28 +105,28 @@ const char* gVS_Main_OutTransformedTexCoords = const char* gVS_Main_OutGradient[6] = { // Linear " linear = vec2((screenSpace * position).x, 0.5);\n" - " ditherTexCoords = (gl_Position * ditherSize).xy;\n", + " ditherTexCoords = (transform * position).xy * ditherSize;\n", " linear = (screenSpace * position).x;\n" - " ditherTexCoords = (gl_Position * ditherSize).xy;\n", + " ditherTexCoords = (transform * position).xy * ditherSize;\n", // Circular " circular = (screenSpace * position).xy;\n" - " ditherTexCoords = (gl_Position * ditherSize).xy;\n", + " ditherTexCoords = (transform * position).xy * ditherSize;\n", " circular = (screenSpace * position).xy;\n" - " ditherTexCoords = (gl_Position * ditherSize).xy;\n", + " ditherTexCoords = (transform * position).xy * ditherSize;\n", // Sweep " sweep = (screenSpace * position).xy;\n" - " ditherTexCoords = (gl_Position * ditherSize).xy;\n", + " ditherTexCoords = (transform * position).xy * ditherSize;\n", " sweep = (screenSpace * position).xy;\n" - " ditherTexCoords = (gl_Position * ditherSize).xy;\n", + " ditherTexCoords = (transform * position).xy * ditherSize;\n", }; const char* gVS_Main_OutBitmapTexCoords = " outBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; const char* gVS_Main_OutPointBitmapTexCoords = " outPointBitmapTexCoords = (textureTransform * position).xy * textureDimension;\n"; const char* gVS_Main_Position = - " gl_Position = transform * position;\n"; + " gl_Position = projection * transform * position;\n"; const char* gVS_Main_PointSize = " gl_PointSize = pointSize;\n"; const char* gVS_Main_AALine =