summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/OpenGLRenderer.cpp308
-rw-r--r--libs/hwui/OpenGLRenderer.h47
-rw-r--r--libs/hwui/ProgramCache.h39
3 files changed, 251 insertions, 143 deletions
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.