Loading libs/hwui/OpenGLRenderer.cpp +180 −128 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -831,6 +824,156 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, return !mSnapshot->clipRect->isEmpty(); } /////////////////////////////////////////////////////////////////////////////// // 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 /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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); setupDrawModelView(left, top, right, bottom, ignoreTransform); } 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); } 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, Loading libs/hwui/OpenGLRenderer.h +40 −7 Original line number Diff line number Diff line Loading @@ -220,13 +220,6 @@ private: void drawColorRect(float left, float top, float right, float bottom, 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. Loading Loading @@ -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. Loading Loading @@ -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 Loading libs/hwui/ProgramCache.h +31 −8 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -141,6 +135,35 @@ struct ProgramDescription { SkXfermode::Mode framebufferMode; 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 Loading Loading
libs/hwui/OpenGLRenderer.cpp +180 −128 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -831,6 +824,156 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom, return !mSnapshot->clipRect->isEmpty(); } /////////////////////////////////////////////////////////////////////////////// // 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 /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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); Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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); setupDrawModelView(left, top, right, bottom, ignoreTransform); } 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); } 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, Loading
libs/hwui/OpenGLRenderer.h +40 −7 Original line number Diff line number Diff line Loading @@ -220,13 +220,6 @@ private: void drawColorRect(float left, float top, float right, float bottom, 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. Loading Loading @@ -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. Loading Loading @@ -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 Loading
libs/hwui/ProgramCache.h +31 −8 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -141,6 +135,35 @@ struct ProgramDescription { SkXfermode::Mode framebufferMode; 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 Loading