summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2012-09-06 10:52:13 -0700
committerAndroid (Google) Code Review <android-gerrit@google.com>2012-09-06 10:52:14 -0700
commit378d131e65348d199db36c21ba7156542bbf0045 (patch)
treeb2e41ab4962973acea7fe8a3b9b3f97581ead2be /libs
parent369bb97d02209fa800081fc3b4e8675ea7e75d34 (diff)
parent6ebdc114e0d72137394f02bc8ffe9d7a782a65c4 (diff)
downloadframeworks_base-378d131e65348d199db36c21ba7156542bbf0045.zip
frameworks_base-378d131e65348d199db36c21ba7156542bbf0045.tar.gz
frameworks_base-378d131e65348d199db36c21ba7156542bbf0045.tar.bz2
Merge "Varying-based AA rect drawing" into jb-mr1-dev
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Caches.h1
-rw-r--r--libs/hwui/OpenGLRenderer.cpp87
-rw-r--r--libs/hwui/OpenGLRenderer.h2
-rw-r--r--libs/hwui/Program.h5
-rw-r--r--libs/hwui/ProgramCache.cpp31
5 files changed, 87 insertions, 39 deletions
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index b9a6336..6d27d6e 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -68,6 +68,7 @@ static const GLsizei gVertexStride = sizeof(Vertex);
static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
static const GLsizei gAAVertexStride = sizeof(AAVertex);
static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
+static const GLsizei gVertexAlphaOffset = 2 * sizeof(float);
static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
static const GLsizei gMeshCount = 4;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7abcc63..a1bb6a2 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1141,6 +1141,10 @@ void OpenGLRenderer::setupDrawAALine() {
mDescription.isAA = true;
}
+void OpenGLRenderer::setupDrawAARect() {
+ mDescription.isAARect = true;
+}
+
void OpenGLRenderer::setupDrawPoint(float pointSize) {
mDescription.isPoint = true;
mDescription.pointSize = pointSize;
@@ -1741,9 +1745,9 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const
/**
* This function uses a similar approach to that of AA lines in the drawLines() function.
- * We expand the rectangle by a half pixel in screen space on all sides, and use a fragment
- * shader to compute the translucency of the color, determined by whether a given pixel is
- * within that boundary region and how far into the region it is.
+ * We expand the rectangle by a half pixel in screen space on all sides. However, instead of using
+ * a fragment shader to compute the translucency of the color from its position, we simply use a
+ * varying parameter to define how far a given pixel is into the region.
*/
void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode) {
@@ -1755,10 +1759,8 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
Matrix4 *mat = mSnapshot->transform;
float m00 = mat->data[Matrix4::kScaleX];
float m01 = mat->data[Matrix4::kSkewY];
- float m02 = mat->data[2];
float m10 = mat->data[Matrix4::kSkewX];
float m11 = mat->data[Matrix4::kScaleX];
- float m12 = mat->data[6];
float scaleX = sqrt(m00 * m00 + m01 * m01);
float scaleY = sqrt(m10 * m10 + m11 * m11);
inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
@@ -1768,6 +1770,11 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
float boundarySizeX = .5 * inverseScaleX;
float boundarySizeY = .5 * inverseScaleY;
+ float innerLeft = left + boundarySizeX;
+ float innerRight = right - boundarySizeX;
+ float innerTop = top + boundarySizeY;
+ float innerBottom = bottom - boundarySizeY;
+
// Adjust the rect by the AA boundary padding
left -= boundarySizeX;
right += boundarySizeX;
@@ -1777,7 +1784,7 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
if (!quickReject(left, top, right, bottom)) {
setupDraw();
setupDrawNoTexture();
- setupDrawAALine();
+ setupDrawAARect();
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
setupDrawColorFilter();
setupDrawShader();
@@ -1788,34 +1795,52 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
setupDrawColorFilterUniforms();
setupDrawShaderIdentityUniforms();
- AAVertex rects[4];
- AAVertex* aaVertices = &rects[0];
- void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
- void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
-
- int widthSlot;
- int lengthSlot;
+ AlphaVertex rects[14];
+ AlphaVertex* aVertices = &rects[0];
+ void* alphaCoords = ((GLbyte*) aVertices) + gVertexAlphaOffset;
+
+ bool force = mCaches.unbindMeshBuffer();
+ mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
+ aVertices, gAlphaVertexStride);
+ mCaches.resetTexCoordsVertexPointer();
+ mCaches.unbindIndicesBuffer();
+
+ int alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
+ glEnableVertexAttribArray(alphaSlot);
+ glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
+
+ // draw left
+ AlphaVertex::set(aVertices++, left, bottom, 0);
+ AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
+ AlphaVertex::set(aVertices++, left, top, 0);
+ AlphaVertex::set(aVertices++, innerLeft, innerTop, 1);
+
+ // draw top
+ AlphaVertex::set(aVertices++, right, top, 0);
+ AlphaVertex::set(aVertices++, innerRight, innerTop, 1);
+
+ // draw right
+ AlphaVertex::set(aVertices++, right, bottom, 0);
+ AlphaVertex::set(aVertices++, innerRight, innerBottom, 1);
+
+ // draw bottom
+ AlphaVertex::set(aVertices++, left, bottom, 0);
+ AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
+
+ // draw inner rect (repeating last vertex to create degenerate bridge triangles)
+ // TODO: also consider drawing the inner rect without the blending-forced shader, if
+ // blending is expensive. Note: can't use drawColorRect() since it doesn't use vertex
+ // buffers like below, resulting in slightly different transformed coordinates.
+ AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
+ AlphaVertex::set(aVertices++, innerLeft, innerTop, 1);
+ AlphaVertex::set(aVertices++, innerRight, innerBottom, 1);
+ AlphaVertex::set(aVertices++, innerRight, innerTop, 1);
- float width = right - left;
- float height = bottom - top;
-
- float boundaryWidthProportion = .5 - ((width != 0) ? (2 * boundarySizeX) / width : 0);
- float boundaryHeightProportion = .5 - ((height != 0) ? (2 * boundarySizeY) / height : 0);
- setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
- boundaryWidthProportion, widthSlot, lengthSlot);
-
- int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
- glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
-
- AAVertex::set(aaVertices++, left, bottom, 1, 1);
- AAVertex::set(aaVertices++, left, top, 1, 0);
- AAVertex::set(aaVertices++, right, bottom, 0, 1);
- AAVertex::set(aaVertices++, right, top, 0, 0);
dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
- finishDrawAALine(widthSlot, lengthSlot);
+ glDisableVertexAttribArray(alphaSlot);
}
}
@@ -1870,10 +1895,8 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
Matrix4 *mat = mSnapshot->transform;
float m00 = mat->data[Matrix4::kScaleX];
float m01 = mat->data[Matrix4::kSkewY];
- float m02 = mat->data[2];
float m10 = mat->data[Matrix4::kSkewX];
float m11 = mat->data[Matrix4::kScaleX];
- float m12 = mat->data[6];
float scaleX = sqrtf(m00 * m00 + m01 * m01);
float scaleY = sqrtf(m10 * m10 + m11 * m11);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4c7cf0a..f2b5f0a 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -434,7 +434,6 @@ private:
* @param color The rectangle's ARGB color, defined as a packed 32 bits word
* @param mode The Skia xfermode to use
* @param ignoreTransform True if the current transform should be ignored
- * @param ignoreBlending True if the blending is set by the caller
*/
void drawColorRect(float left, float top, float right, float bottom,
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
@@ -649,6 +648,7 @@ private:
void setupDrawWithExternalTexture();
void setupDrawNoTexture();
void setupDrawAALine();
+ void setupDrawAARect();
void setupDrawPoint(float pointSize);
void setupDrawColor(int color);
void setupDrawColor(int color, int alpha);
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index 1818f82..a3bfaa4 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -81,6 +81,8 @@ namespace uirenderer {
#define PROGRAM_IS_SIMPLE_GRADIENT 41
+#define PROGRAM_IS_AA_RECT_SHIFT 42
+
///////////////////////////////////////////////////////////////////////////////
// Types
///////////////////////////////////////////////////////////////////////////////
@@ -128,6 +130,7 @@ struct ProgramDescription {
bool isBitmapNpot;
bool isAA;
+ bool isAARect;
bool hasGradient;
Gradient gradientType;
@@ -165,6 +168,7 @@ struct ProgramDescription {
hasTextureTransform = false;
isAA = false;
+ isAARect = false;
modulate = false;
@@ -260,6 +264,7 @@ struct ProgramDescription {
if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
+ if (isAARect) key |= programid(0x1) << PROGRAM_IS_AA_RECT_SHIFT;
return key;
}
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index 8a9a2ac..0ed8008 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -43,6 +43,8 @@ const char* gVS_Header_Attributes_TexCoords =
const char* gVS_Header_Attributes_AAParameters =
"attribute float vtxWidth;\n"
"attribute float vtxLength;\n";
+const char* gVS_Header_Attributes_AARectParameters =
+ "attribute float vtxAlpha;\n";
const char* gVS_Header_Uniforms_TextureTransform =
"uniform mat4 mainTextureTransform;\n";
const char* gVS_Header_Uniforms =
@@ -65,6 +67,8 @@ const char* gVS_Header_Varyings_HasTexture =
const char* gVS_Header_Varyings_IsAA =
"varying float widthProportion;\n"
"varying float lengthProportion;\n";
+const char* gVS_Header_Varyings_IsAARect =
+ "varying float alpha;\n";
const char* gVS_Header_Varyings_HasBitmap =
"varying highp vec2 outBitmapTexCoords;\n";
const char* gVS_Header_Varyings_PointHasBitmap =
@@ -112,6 +116,8 @@ const char* gVS_Main_PointSize =
const char* gVS_Main_AA =
" widthProportion = vtxWidth;\n"
" lengthProportion = vtxLength;\n";
+const char* gVS_Main_AARect =
+ " alpha = vtxAlpha;\n";
const char* gVS_Footer =
"}\n\n";
@@ -242,6 +248,8 @@ const char* gFS_Main_ModulateColor_ApplyGamma =
const char* gFS_Main_AccountForAA =
" fragColor *= (1.0 - smoothstep(boundaryWidth, 0.5, abs(0.5 - widthProportion)))\n"
" * (1.0 - smoothstep(boundaryLength, 0.5, abs(0.5 - lengthProportion)));\n";
+const char* gFS_Main_AccountForAARect =
+ " fragColor *= alpha;\n";
const char* gFS_Main_FetchTexture[2] = {
// Don't modulate
@@ -439,7 +447,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Attributes_TexCoords);
}
- if (description.isAA) {
+ if (description.isAARect) {
+ shader.append(gVS_Header_Attributes_AARectParameters);
+ } else if (description.isAA) {
shader.append(gVS_Header_Attributes_AAParameters);
}
// Uniforms
@@ -460,7 +470,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
- if (description.isAA) {
+ if (description.isAARect) {
+ shader.append(gVS_Header_Varyings_IsAARect);
+ } else if (description.isAA) {
shader.append(gVS_Header_Varyings_IsAA);
}
if (description.hasGradient) {
@@ -479,7 +491,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
} else if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Main_OutTexCoords);
}
- if (description.isAA) {
+ if (description.isAARect) {
+ shader.append(gVS_Main_AARect);
+ } else if (description.isAA) {
shader.append(gVS_Main_AA);
}
if (description.hasGradient) {
@@ -521,7 +535,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
if (description.hasTexture || description.hasExternalTexture) {
shader.append(gVS_Header_Varyings_HasTexture);
}
- if (description.isAA) {
+ if (description.isAARect) {
+ shader.append(gVS_Header_Varyings_IsAARect);
+ } else if (description.isAA) {
shader.append(gVS_Header_Varyings_IsAA);
}
if (description.hasGradient) {
@@ -562,7 +578,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
// Optimization for common cases
if (!description.isAA && !blendFramebuffer &&
- description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
+ description.colorOp == ProgramDescription::kColorNone &&
+ !description.isPoint && !description.isAARect) {
bool fast = false;
const bool noShader = !description.hasGradient && !description.hasBitmap;
@@ -654,7 +671,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
shader.append(gFS_Main_FetchColor);
}
}
- if (description.isAA) {
+ if (description.isAARect) {
+ shader.append(gFS_Main_AccountForAARect);
+ } else if (description.isAA) {
shader.append(gFS_Main_AccountForAA);
}
if (description.hasGradient) {