Skip to content

Commit 6ebdc11

Browse files
committed
Varying-based AA rect drawing
Instead of calculating opacity from relative position in the shader, use a shader varying to do this computation for us. bug:5045101 Also adds a test to HwAccelerationTest to show incorrect antialiasing in scaled drawAARect / boundarySize calculation. Change-Id: Icdc41acb01dc10ce354834f8389a5aed2f439162
1 parent 176d105 commit 6ebdc11

File tree

6 files changed

+93
-39
lines changed

6 files changed

+93
-39
lines changed

libs/hwui/Caches.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ static const GLsizei gVertexStride = sizeof(Vertex);
6767
static const GLsizei gAlphaVertexStride = sizeof(AlphaVertex);
6868
static const GLsizei gAAVertexStride = sizeof(AAVertex);
6969
static const GLsizei gMeshTextureOffset = 2 * sizeof(float);
70+
static const GLsizei gVertexAlphaOffset = 2 * sizeof(float);
7071
static const GLsizei gVertexAAWidthOffset = 2 * sizeof(float);
7172
static const GLsizei gVertexAALengthOffset = 3 * sizeof(float);
7273
static const GLsizei gMeshCount = 4;

libs/hwui/OpenGLRenderer.cpp

Lines changed: 55 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,6 +1145,10 @@ void OpenGLRenderer::setupDrawAALine() {
11451145
mDescription.isAA = true;
11461146
}
11471147

1148+
void OpenGLRenderer::setupDrawAARect() {
1149+
mDescription.isAARect = true;
1150+
}
1151+
11481152
void OpenGLRenderer::setupDrawPoint(float pointSize) {
11491153
mDescription.isPoint = true;
11501154
mDescription.pointSize = pointSize;
@@ -1745,9 +1749,9 @@ status_t OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const
17451749

17461750
/**
17471751
* This function uses a similar approach to that of AA lines in the drawLines() function.
1748-
* We expand the rectangle by a half pixel in screen space on all sides, and use a fragment
1749-
* shader to compute the translucency of the color, determined by whether a given pixel is
1750-
* within that boundary region and how far into the region it is.
1752+
* We expand the rectangle by a half pixel in screen space on all sides. However, instead of using
1753+
* a fragment shader to compute the translucency of the color from its position, we simply use a
1754+
* varying parameter to define how far a given pixel is into the region.
17511755
*/
17521756
void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom,
17531757
int color, SkXfermode::Mode mode) {
@@ -1759,10 +1763,8 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
17591763
Matrix4 *mat = mSnapshot->transform;
17601764
float m00 = mat->data[Matrix4::kScaleX];
17611765
float m01 = mat->data[Matrix4::kSkewY];
1762-
float m02 = mat->data[2];
17631766
float m10 = mat->data[Matrix4::kSkewX];
17641767
float m11 = mat->data[Matrix4::kScaleX];
1765-
float m12 = mat->data[6];
17661768
float scaleX = sqrt(m00 * m00 + m01 * m01);
17671769
float scaleY = sqrt(m10 * m10 + m11 * m11);
17681770
inverseScaleX = (scaleX != 0) ? (inverseScaleX / scaleX) : 0;
@@ -1772,6 +1774,11 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
17721774
float boundarySizeX = .5 * inverseScaleX;
17731775
float boundarySizeY = .5 * inverseScaleY;
17741776

1777+
float innerLeft = left + boundarySizeX;
1778+
float innerRight = right - boundarySizeX;
1779+
float innerTop = top + boundarySizeY;
1780+
float innerBottom = bottom - boundarySizeY;
1781+
17751782
// Adjust the rect by the AA boundary padding
17761783
left -= boundarySizeX;
17771784
right += boundarySizeX;
@@ -1781,7 +1788,7 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
17811788
if (!quickReject(left, top, right, bottom)) {
17821789
setupDraw();
17831790
setupDrawNoTexture();
1784-
setupDrawAALine();
1791+
setupDrawAARect();
17851792
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
17861793
setupDrawColorFilter();
17871794
setupDrawShader();
@@ -1792,34 +1799,52 @@ void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom
17921799
setupDrawColorFilterUniforms();
17931800
setupDrawShaderIdentityUniforms();
17941801

1795-
AAVertex rects[4];
1796-
AAVertex* aaVertices = &rects[0];
1797-
void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
1798-
void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
1799-
1800-
int widthSlot;
1801-
int lengthSlot;
1802+
AlphaVertex rects[14];
1803+
AlphaVertex* aVertices = &rects[0];
1804+
void* alphaCoords = ((GLbyte*) aVertices) + gVertexAlphaOffset;
1805+
1806+
bool force = mCaches.unbindMeshBuffer();
1807+
mCaches.bindPositionVertexPointer(force, mCaches.currentProgram->position,
1808+
aVertices, gAlphaVertexStride);
1809+
mCaches.resetTexCoordsVertexPointer();
1810+
mCaches.unbindIndicesBuffer();
1811+
1812+
int alphaSlot = mCaches.currentProgram->getAttrib("vtxAlpha");
1813+
glEnableVertexAttribArray(alphaSlot);
1814+
glVertexAttribPointer(alphaSlot, 1, GL_FLOAT, GL_FALSE, gAlphaVertexStride, alphaCoords);
1815+
1816+
// draw left
1817+
AlphaVertex::set(aVertices++, left, bottom, 0);
1818+
AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
1819+
AlphaVertex::set(aVertices++, left, top, 0);
1820+
AlphaVertex::set(aVertices++, innerLeft, innerTop, 1);
1821+
1822+
// draw top
1823+
AlphaVertex::set(aVertices++, right, top, 0);
1824+
AlphaVertex::set(aVertices++, innerRight, innerTop, 1);
1825+
1826+
// draw right
1827+
AlphaVertex::set(aVertices++, right, bottom, 0);
1828+
AlphaVertex::set(aVertices++, innerRight, innerBottom, 1);
1829+
1830+
// draw bottom
1831+
AlphaVertex::set(aVertices++, left, bottom, 0);
1832+
AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
1833+
1834+
// draw inner rect (repeating last vertex to create degenerate bridge triangles)
1835+
// TODO: also consider drawing the inner rect without the blending-forced shader, if
1836+
// blending is expensive. Note: can't use drawColorRect() since it doesn't use vertex
1837+
// buffers like below, resulting in slightly different transformed coordinates.
1838+
AlphaVertex::set(aVertices++, innerLeft, innerBottom, 1);
1839+
AlphaVertex::set(aVertices++, innerLeft, innerTop, 1);
1840+
AlphaVertex::set(aVertices++, innerRight, innerBottom, 1);
1841+
AlphaVertex::set(aVertices++, innerRight, innerTop, 1);
18021842

1803-
float width = right - left;
1804-
float height = bottom - top;
1805-
1806-
float boundaryWidthProportion = .5 - ((width != 0) ? (2 * boundarySizeX) / width : 0);
1807-
float boundaryHeightProportion = .5 - ((height != 0) ? (2 * boundarySizeY) / height : 0);
1808-
setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords,
1809-
boundaryWidthProportion, widthSlot, lengthSlot);
1810-
1811-
int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
1812-
glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
1813-
1814-
AAVertex::set(aaVertices++, left, bottom, 1, 1);
1815-
AAVertex::set(aaVertices++, left, top, 1, 0);
1816-
AAVertex::set(aaVertices++, right, bottom, 0, 1);
1817-
AAVertex::set(aaVertices++, right, top, 0, 0);
18181843
dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
18191844

1820-
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1845+
glDrawArrays(GL_TRIANGLE_STRIP, 0, 14);
18211846

1822-
finishDrawAALine(widthSlot, lengthSlot);
1847+
glDisableVertexAttribArray(alphaSlot);
18231848
}
18241849
}
18251850

@@ -1874,10 +1899,8 @@ status_t OpenGLRenderer::drawLines(float* points, int count, SkPaint* paint) {
18741899
Matrix4 *mat = mSnapshot->transform;
18751900
float m00 = mat->data[Matrix4::kScaleX];
18761901
float m01 = mat->data[Matrix4::kSkewY];
1877-
float m02 = mat->data[2];
18781902
float m10 = mat->data[Matrix4::kSkewX];
18791903
float m11 = mat->data[Matrix4::kScaleX];
1880-
float m12 = mat->data[6];
18811904

18821905
float scaleX = sqrtf(m00 * m00 + m01 * m01);
18831906
float scaleY = sqrtf(m10 * m10 + m11 * m11);

libs/hwui/OpenGLRenderer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,6 @@ class OpenGLRenderer {
440440
* @param color The rectangle's ARGB color, defined as a packed 32 bits word
441441
* @param mode The Skia xfermode to use
442442
* @param ignoreTransform True if the current transform should be ignored
443-
* @param ignoreBlending True if the blending is set by the caller
444443
*/
445444
void drawColorRect(float left, float top, float right, float bottom,
446445
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
@@ -655,6 +654,7 @@ class OpenGLRenderer {
655654
void setupDrawWithExternalTexture();
656655
void setupDrawNoTexture();
657656
void setupDrawAALine();
657+
void setupDrawAARect();
658658
void setupDrawPoint(float pointSize);
659659
void setupDrawColor(int color);
660660
void setupDrawColor(int color, int alpha);

libs/hwui/Program.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ namespace uirenderer {
8181

8282
#define PROGRAM_IS_SIMPLE_GRADIENT 41
8383

84+
#define PROGRAM_IS_AA_RECT_SHIFT 42
85+
8486
///////////////////////////////////////////////////////////////////////////////
8587
// Types
8688
///////////////////////////////////////////////////////////////////////////////
@@ -128,6 +130,7 @@ struct ProgramDescription {
128130
bool isBitmapNpot;
129131

130132
bool isAA;
133+
bool isAARect;
131134

132135
bool hasGradient;
133136
Gradient gradientType;
@@ -165,6 +168,7 @@ struct ProgramDescription {
165168
hasTextureTransform = false;
166169

167170
isAA = false;
171+
isAARect = false;
168172

169173
modulate = false;
170174

@@ -260,6 +264,7 @@ struct ProgramDescription {
260264
if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
261265
if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
262266
if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
267+
if (isAARect) key |= programid(0x1) << PROGRAM_IS_AA_RECT_SHIFT;
263268
return key;
264269
}
265270

libs/hwui/ProgramCache.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ const char* gVS_Header_Attributes_TexCoords =
4343
const char* gVS_Header_Attributes_AAParameters =
4444
"attribute float vtxWidth;\n"
4545
"attribute float vtxLength;\n";
46+
const char* gVS_Header_Attributes_AARectParameters =
47+
"attribute float vtxAlpha;\n";
4648
const char* gVS_Header_Uniforms_TextureTransform =
4749
"uniform mat4 mainTextureTransform;\n";
4850
const char* gVS_Header_Uniforms =
@@ -65,6 +67,8 @@ const char* gVS_Header_Varyings_HasTexture =
6567
const char* gVS_Header_Varyings_IsAA =
6668
"varying float widthProportion;\n"
6769
"varying float lengthProportion;\n";
70+
const char* gVS_Header_Varyings_IsAARect =
71+
"varying float alpha;\n";
6872
const char* gVS_Header_Varyings_HasBitmap =
6973
"varying highp vec2 outBitmapTexCoords;\n";
7074
const char* gVS_Header_Varyings_PointHasBitmap =
@@ -112,6 +116,8 @@ const char* gVS_Main_PointSize =
112116
const char* gVS_Main_AA =
113117
" widthProportion = vtxWidth;\n"
114118
" lengthProportion = vtxLength;\n";
119+
const char* gVS_Main_AARect =
120+
" alpha = vtxAlpha;\n";
115121
const char* gVS_Footer =
116122
"}\n\n";
117123

@@ -242,6 +248,8 @@ const char* gFS_Main_ModulateColor_ApplyGamma =
242248
const char* gFS_Main_AccountForAA =
243249
" fragColor *= (1.0 - smoothstep(boundaryWidth, 0.5, abs(0.5 - widthProportion)))\n"
244250
" * (1.0 - smoothstep(boundaryLength, 0.5, abs(0.5 - lengthProportion)));\n";
251+
const char* gFS_Main_AccountForAARect =
252+
" fragColor *= alpha;\n";
245253

246254
const char* gFS_Main_FetchTexture[2] = {
247255
// Don't modulate
@@ -439,7 +447,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
439447
if (description.hasTexture || description.hasExternalTexture) {
440448
shader.append(gVS_Header_Attributes_TexCoords);
441449
}
442-
if (description.isAA) {
450+
if (description.isAARect) {
451+
shader.append(gVS_Header_Attributes_AARectParameters);
452+
} else if (description.isAA) {
443453
shader.append(gVS_Header_Attributes_AAParameters);
444454
}
445455
// Uniforms
@@ -460,7 +470,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
460470
if (description.hasTexture || description.hasExternalTexture) {
461471
shader.append(gVS_Header_Varyings_HasTexture);
462472
}
463-
if (description.isAA) {
473+
if (description.isAARect) {
474+
shader.append(gVS_Header_Varyings_IsAARect);
475+
} else if (description.isAA) {
464476
shader.append(gVS_Header_Varyings_IsAA);
465477
}
466478
if (description.hasGradient) {
@@ -479,7 +491,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description
479491
} else if (description.hasTexture || description.hasExternalTexture) {
480492
shader.append(gVS_Main_OutTexCoords);
481493
}
482-
if (description.isAA) {
494+
if (description.isAARect) {
495+
shader.append(gVS_Main_AARect);
496+
} else if (description.isAA) {
483497
shader.append(gVS_Main_AA);
484498
}
485499
if (description.hasGradient) {
@@ -521,7 +535,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
521535
if (description.hasTexture || description.hasExternalTexture) {
522536
shader.append(gVS_Header_Varyings_HasTexture);
523537
}
524-
if (description.isAA) {
538+
if (description.isAARect) {
539+
shader.append(gVS_Header_Varyings_IsAARect);
540+
} else if (description.isAA) {
525541
shader.append(gVS_Header_Varyings_IsAA);
526542
}
527543
if (description.hasGradient) {
@@ -562,7 +578,8 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
562578

563579
// Optimization for common cases
564580
if (!description.isAA && !blendFramebuffer &&
565-
description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
581+
description.colorOp == ProgramDescription::kColorNone &&
582+
!description.isPoint && !description.isAARect) {
566583
bool fast = false;
567584

568585
const bool noShader = !description.hasGradient && !description.hasBitmap;
@@ -654,7 +671,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti
654671
shader.append(gFS_Main_FetchColor);
655672
}
656673
}
657-
if (description.isAA) {
674+
if (description.isAARect) {
675+
shader.append(gFS_Main_AccountForAARect);
676+
} else if (description.isAA) {
658677
shader.append(gFS_Main_AccountForAA);
659678
}
660679
if (description.hasGradient) {

tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,12 @@ protected void onDraw(Canvas canvas) {
113113
canvas.rotate(45);
114114
canvas.drawRect(0, 0, 20, 10, p);
115115
canvas.restore();
116+
canvas.save();
117+
canvas.translate(mOffset + 280, yOffset);
118+
canvas.scale(0.5f, 8);
119+
canvas.rotate(0.5f);
120+
canvas.drawRect(0, 0, 80, 5, p);
121+
canvas.restore();
116122
canvas.restore();
117123

118124
yOffset += 100;

0 commit comments

Comments
 (0)