From 70ca14e08ae197547ac412e8a1210e1ebdfb2eb1 Mon Sep 17 00:00:00 2001 From: Romain Guy Date: Mon, 13 Dec 2010 18:24:33 -0800 Subject: Refactor OpenGLRenderer to simplify OpenGL drawing code. This is the first step of the refactoring: - drawColorRect - drawTextureMesh Remaining methods to refactor: - setupTextureAlpha8 - drawPath - setupShadow - drawText - drawLines - composeLayerRegion Change-Id: I0fced6a05b6b6eee10ee7cef0c3fbdaa6cefab20 --- libs/hwui/OpenGLRenderer.cpp | 308 +++++++++++++++++++++++++------------------ libs/hwui/OpenGLRenderer.h | 47 ++++++- libs/hwui/ProgramCache.h | 39 ++++-- 3 files changed, 251 insertions(+), 143 deletions(-) (limited to 'libs') diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 17b9e83..a8fe646 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -723,13 +723,6 @@ void OpenGLRenderer::dirtyLayer(const float left, const float top, #endif } -void OpenGLRenderer::setupDraw() { - clearLayerRegions(); - if (mDirtyClip) { - setScissorFromClip(); - } -} - void OpenGLRenderer::clearLayerRegions() { if (mLayers.size() == 0 || mSnapshot->isIgnored()) return; @@ -832,6 +825,156 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, } /////////////////////////////////////////////////////////////////////////////// +// Drawing commands +/////////////////////////////////////////////////////////////////////////////// + +void OpenGLRenderer::setupDraw() { + clearLayerRegions(); + if (mDirtyClip) { + setScissorFromClip(); + } + mDescription.reset(); + mSetShaderColor = false; + mColorSet = false; + mColorA = mColorR = mColorG = mColorB = 0.0f; + mTextureUnit = 0; + mTrackDirtyRegions = true; +} + +void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { + mDescription.hasTexture = true; + mDescription.hasAlpha8Texture = isAlpha8; +} + +void OpenGLRenderer::setupDrawColor(int color) { + mColorA = ((color >> 24) & 0xFF) / 255.0f; + const float a = mColorA / 255.0f; + mColorR = mColorA * ((color >> 16) & 0xFF); + mColorG = mColorA * ((color >> 8) & 0xFF); + mColorB = mColorA * ((color ) & 0xFF); + mColorSet = true; + mSetShaderColor = mDescription.setColor(mColorR, mColorG, mColorB, mColorA); +} + +void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) { + mColorA = a; + mColorR = r; + mColorG = g; + mColorB = b; + mColorSet = true; + mSetShaderColor = mDescription.setColor(r, g, b, a); +} + +void OpenGLRenderer::setupDrawShader() { + if (mShader) { + mShader->describe(mDescription, mCaches.extensions); + } +} + +void OpenGLRenderer::setupDrawColorFilter() { + if (mColorFilter) { + mColorFilter->describe(mDescription, mCaches.extensions); + } +} + +void OpenGLRenderer::setupDrawBlending(SkXfermode::Mode mode, bool swapSrcDst) { + chooseBlending((mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode, + mDescription, swapSrcDst); +} + +void OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) { + chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode, + mDescription, swapSrcDst); +} + +void OpenGLRenderer::setupDrawProgram() { + useProgram(mCaches.programCache.get(mDescription)); +} + +void OpenGLRenderer::setupDrawDirtyRegionsDisabled() { + mTrackDirtyRegions = false; +} + +void OpenGLRenderer::setupDrawModelViewTranslate(float left, float top, float right, float bottom, + bool ignoreTransform) { + mModelView.loadTranslate(left, top, 0.0f); + if (!ignoreTransform) { + mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); + if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *mSnapshot->transform); + } else { + mCaches.currentProgram->set(mOrthoMatrix, mModelView, mIdentity); + if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom); + } +} + +void OpenGLRenderer::setupDrawModelView(float left, float top, float right, float bottom, + bool ignoreTransform, bool ignoreModelView) { + if (!ignoreModelView) { + mModelView.loadTranslate(left, top, 0.0f); + mModelView.scale(right - left, bottom - top, 1.0f); + if (!ignoreTransform) { + mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); + if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom, *mSnapshot->transform); + } else { + mCaches.currentProgram->set(mOrthoMatrix, mModelView, mIdentity); + if (mTrackDirtyRegions) dirtyLayer(left, top, right, bottom); + } + } else { + mModelView.loadIdentity(); + } +} + +void OpenGLRenderer::setupDrawColorUniforms() { + if (mColorSet && mSetShaderColor) { + mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA); + } +} + +void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) { + if (mShader) { + if (ignoreTransform) { + mModelView.loadInverse(*mSnapshot->transform); + } + mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &mTextureUnit); + } +} + +void OpenGLRenderer::setupDrawColorFilterUniforms() { + if (mColorFilter) { + mColorFilter->setupProgram(mCaches.currentProgram); + } +} + +void OpenGLRenderer::setupDrawSimpleMesh() { + mCaches.bindMeshBuffer(); + glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, + gMeshStride, 0); +} + +void OpenGLRenderer::setupDrawTexture(GLuint texture) { + bindTexture(texture); + glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++); + + mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords"); + glEnableVertexAttribArray(mTexCoordsSlot); +} + +void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) { + if (!vertices) { + mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); + } else { + mCaches.unbindMeshBuffer(); + } + glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, + gMeshStride, vertices); + glVertexAttribPointer(mTexCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); +} + +void OpenGLRenderer::finishDrawTexture() { + glDisableVertexAttribArray(mTexCoordsSlot); +} + +/////////////////////////////////////////////////////////////////////////////// // Drawing /////////////////////////////////////////////////////////////////////////////// @@ -1043,18 +1186,16 @@ void OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) { glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, gMeshStride, vertex); - mModelView.loadIdentity(); - // Build and use the appropriate shader useProgram(mCaches.programCache.get(description)); - mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); + mCaches.currentProgram->set(mOrthoMatrix, mIdentity, *mSnapshot->transform); if (!mShader || (mShader && setColor)) { mCaches.currentProgram->setColor(r, g, b, a); } if (mShader) { - mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit); + mShader->setupProgram(mCaches.currentProgram, mIdentity, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCaches.currentProgram); @@ -1116,6 +1257,7 @@ void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { Rect& clip(*mSnapshot->clipRect); clip.snapToPixelBoundaries(); + drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); } @@ -1512,84 +1654,26 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color, SkXfermode::Mode mode, bool ignoreTransform) { - setupDraw(); - // If a shader is set, preserve only the alpha if (mShader) { color |= 0x00ffffff; } - // Render using pre-multiplied alpha - const int alpha = (color >> 24) & 0xFF; - const GLfloat a = alpha / 255.0f; - const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; - const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; - const GLfloat b = a * ((color ) & 0xFF) / 255.0f; - - setupColorRect(left, top, right, bottom, r, g, b, a, mode, ignoreTransform); + setupDraw(); + setupDrawColor(color); + setupDrawShader(); + setupDrawColorFilter(); + setupDrawBlending(mode); + setupDrawProgram(); + setupDrawModelView(left, top, right, bottom, ignoreTransform); + setupDrawColorUniforms(); + setupDrawShaderUniforms(ignoreTransform); + setupDrawColorFilterUniforms(); + setupDrawSimpleMesh(); - // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); } -void OpenGLRenderer::setupColorRect(float left, float top, float right, float bottom, - float r, float g, float b, float a, SkXfermode::Mode mode, - bool ignoreTransform, bool ignoreMatrix) { - GLuint textureUnit = 0; - - // Describe the required shaders - ProgramDescription description; - const bool setColor = description.setColor(r, g, b, a); - - if (mShader) { - mShader->describe(description, mCaches.extensions); - } - if (mColorFilter) { - mColorFilter->describe(description, mCaches.extensions); - } - - // Setup the blending mode - chooseBlending(a < 1.0f || (mShader && mShader->blend()), mode, description); - - // Build and use the appropriate shader - useProgram(mCaches.programCache.get(description)); - - // Setup attributes - mCaches.bindMeshBuffer(); - glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, - gMeshStride, 0); - - if (!ignoreMatrix) { - // Setup uniforms - mModelView.loadTranslate(left, top, 0.0f); - mModelView.scale(right - left, bottom - top, 1.0f); - if (!ignoreTransform) { - mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); - dirtyLayer(left, top, right, bottom, *mSnapshot->transform); - } else { - mat4 identity; - mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity); - dirtyLayer(left, top, right, bottom); - } - } - if (!mShader || (mShader && setColor)) { - mCaches.currentProgram->setColor(r, g, b, a); - } - - // Setup attributes and uniforms required by the shaders - if (mShader) { - if (ignoreMatrix) { - mModelView.loadIdentity(); - } else if (ignoreTransform) { - mModelView.loadInverse(*mSnapshot->transform); - } - mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &textureUnit); - } - if (mColorFilter) { - mColorFilter->setupProgram(mCaches.currentProgram); - } -} - void OpenGLRenderer::drawTextureRect(float left, float top, float right, float bottom, Texture* texture, SkPaint* paint) { int alpha; @@ -1622,61 +1706,29 @@ void OpenGLRenderer::drawTextureMesh(float left, float top, float right, float b GLuint texture, float alpha, SkXfermode::Mode mode, bool blend, GLvoid* vertices, GLvoid* texCoords, GLenum drawMode, GLsizei elementsCount, bool swapSrcDst, bool ignoreTransform, GLuint vbo, bool ignoreScale, bool dirty) { - setupDraw(); - ProgramDescription description; - description.hasTexture = true; - const bool setColor = description.setColor(alpha, alpha, alpha, alpha); - if (mColorFilter) { - mColorFilter->describe(description, mCaches.extensions); + setupDraw(); + setupDrawWithTexture(); + setupDrawColor(alpha, alpha, alpha, alpha); + setupDrawColorFilter(); + setupDrawBlending(blend, mode, swapSrcDst); + setupDrawProgram(); + if (!dirty) { + setupDrawDirtyRegionsDisabled(); } - - mModelView.loadTranslate(left, top, 0.0f); if (!ignoreScale) { - mModelView.scale(right - left, bottom - top, 1.0f); - } - - chooseBlending(blend || alpha < 1.0f, mode, description, swapSrcDst); - - useProgram(mCaches.programCache.get(description)); - if (!ignoreTransform) { - mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); - if (dirty) dirtyLayer(left, top, right, bottom, *mSnapshot->transform); - } else { - mat4 identity; - mCaches.currentProgram->set(mOrthoMatrix, mModelView, identity); - if (dirty) dirtyLayer(left, top, right, bottom); - } - - // Texture - bindTexture(texture); - glUniform1i(mCaches.currentProgram->getUniform("sampler"), 0); - - // Always premultiplied - if (setColor) { - mCaches.currentProgram->setColor(alpha, alpha, alpha, alpha); - } - - // Mesh - int texCoordsSlot = mCaches.currentProgram->getAttrib("texCoords"); - glEnableVertexAttribArray(texCoordsSlot); - - if (!vertices) { - mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); + setupDrawModelView(left, top, right, bottom, ignoreTransform); } else { - mCaches.unbindMeshBuffer(); - } - glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, - gMeshStride, vertices); - glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, texCoords); - - // Color filter - if (mColorFilter) { - mColorFilter->setupProgram(mCaches.currentProgram); + setupDrawModelViewTranslate(left, top, right, bottom, ignoreTransform); } + setupDrawColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawTexture(texture); + setupDrawMesh(vertices, texCoords, vbo); glDrawArrays(drawMode, 0, elementsCount); - glDisableVertexAttribArray(texCoordsSlot); + + finishDrawTexture(); } void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index e866d1b..82b27b0 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -221,13 +221,6 @@ private: int color, SkXfermode::Mode mode, bool ignoreTransform = false); /** - * Setups shaders to draw a colored rect. - */ - void setupColorRect(float left, float top, float right, float bottom, - float r, float g, float b, float a, SkXfermode::Mode mode, - bool ignoreTransform, bool ignoreMatrix = false); - - /** * Draws a textured rectangle with the specified texture. The specified coordinates * are transformed by the current snapshot's transform matrix. * @@ -431,6 +424,31 @@ private: * Invoked before any drawing operation. This sets required state. */ void setupDraw(); + /** + * Various methods to setup OpenGL rendering. + */ + void setupDrawWithTexture(bool isAlpha8 = false); + void setupDrawColor(int color); + void setupDrawColor(float r, float g, float b, float a); + void setupDrawShader(); + void setupDrawColorFilter(); + void setupDrawBlending(SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode, + bool swapSrcDst = false); + void setupDrawBlending(bool blend = true, SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode, + bool swapSrcDst = false); + void setupDrawProgram(); + void setupDrawDirtyRegionsDisabled(); + void setupDrawModelView(float left, float top, float right, float bottom, + bool ignoreTransform = false, bool ignoreModelView = false); + void setupDrawModelViewTranslate(float left, float top, float right, float bottom, + bool ignoreTransform = false); + void setupDrawColorUniforms(); + void setupDrawShaderUniforms(bool ignoreTransform = false); + void setupDrawColorFilterUniforms(); + void setupDrawSimpleMesh(); + void setupDrawTexture(GLuint texture); + void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo = 0); + void finishDrawTexture(); /** * Should be invoked every time the glScissor is modified. @@ -495,6 +513,21 @@ private: // Indicates whether the clip must be restored bool mDirtyClip; + // The following fields are used to setup drawing + // Used to describe the shaders to generate + ProgramDescription mDescription; + // Color description + bool mColorSet; + float mColorA, mColorR, mColorG, mColorB; + // Indicates that the shader should get a color + bool mSetShaderColor; + // Current texture unit + GLuint mTextureUnit; + // Track dirty regions, true by default + bool mTrackDirtyRegions; + // Texture coordinates slot + int mTexCoordsSlot; + friend class DisplayListRenderer; }; // class OpenGLRenderer diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index fc3e248..3acd18a 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -102,14 +102,8 @@ struct ProgramDescription { kGradientSweep }; - ProgramDescription(): - hasTexture(false), hasAlpha8Texture(false), modulate(false), - hasBitmap(false), isBitmapNpot(false), hasGradient(false), - gradientType(kGradientLinear), - shadersMode(SkXfermode::kClear_Mode), isBitmapFirst(false), - bitmapWrapS(GL_CLAMP_TO_EDGE), bitmapWrapT(GL_CLAMP_TO_EDGE), - colorOp(kColorNone), colorMode(SkXfermode::kClear_Mode), - framebufferMode(SkXfermode::kClear_Mode), swapSrcDst(false) { + ProgramDescription() { + reset(); } // Texturing @@ -142,6 +136,35 @@ struct ProgramDescription { bool swapSrcDst; /** + * Resets this description. All fields are reset back to the default + * values they hold after building a new instance. + */ + void reset() { + hasTexture = false; + hasAlpha8Texture = false; + + modulate = false; + + hasBitmap = false; + isBitmapNpot = false; + + hasGradient = false; + gradientType = kGradientLinear; + + shadersMode = SkXfermode::kClear_Mode; + + isBitmapFirst = false; + bitmapWrapS = GL_CLAMP_TO_EDGE; + bitmapWrapT = GL_CLAMP_TO_EDGE; + + colorOp = kColorNone; + colorMode = SkXfermode::kClear_Mode; + + framebufferMode = SkXfermode::kClear_Mode; + swapSrcDst = false; + } + + /** * Indicates, for a given color, whether color modulation is required in * the fragment shader. When this method returns true, the program should * be provided with a modulation color. -- cgit v1.1