Antialiasing for rectangles
Change-Id: I7ca6931606541ddd504bd5db7f8dc04b9cde8cd9
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 80a7bed..5a86fe3 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1458,6 +1458,79 @@
}
/**
+ * 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.
+ */
+void OpenGLRenderer::drawAARect(float left, float top, float right, float bottom,
+ int color, SkXfermode::Mode mode)
+{
+ float inverseScaleX = 1.0f;
+ float inverseScaleY = 1.0f;
+ // The quad that we use needs to account for scaling.
+ if (!mSnapshot->transform->isPureTranslate()) {
+ 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;
+ inverseScaleY = (scaleY != 0) ? (inverseScaleY / scaleY) : 0;
+ }
+
+ setupDraw();
+ setupDrawAALine();
+ setupDrawColor(color);
+ setupDrawColorFilter();
+ setupDrawShader();
+ setupDrawBlending(true, mode);
+ setupDrawProgram();
+ setupDrawModelViewIdentity(true);
+ setupDrawColorUniforms();
+ setupDrawColorFilterUniforms();
+ setupDrawShaderIdentityUniforms();
+
+ AAVertex rects[4];
+ AAVertex* aaVertices = &rects[0];
+ void* widthCoords = ((GLbyte*) aaVertices) + gVertexAAWidthOffset;
+ void* lengthCoords = ((GLbyte*) aaVertices) + gVertexAALengthOffset;
+
+ float boundarySizeX = .5 * inverseScaleX;
+ float boundarySizeY = .5 * inverseScaleY;
+
+ // Adjust the rect by the AA boundary padding
+ left -= boundarySizeX;
+ right += boundarySizeX;
+ top -= boundarySizeY;
+ bottom += boundarySizeY;
+
+ float width = right - left;
+ float height = bottom - top;
+
+ float boundaryWidthProportion = (width != 0) ? (2 * boundarySizeX) / width : 0;
+ float boundaryHeightProportion = (height != 0) ? (2 * boundarySizeY) / height : 0;
+ setupDrawAALine((void*) aaVertices, widthCoords, lengthCoords, boundaryWidthProportion);
+ int boundaryLengthSlot = mCaches.currentProgram->getUniform("boundaryLength");
+ int inverseBoundaryLengthSlot = mCaches.currentProgram->getUniform("inverseBoundaryLength");
+ glUniform1f(boundaryLengthSlot, boundaryHeightProportion);
+ glUniform1f(inverseBoundaryLengthSlot, (1 / boundaryHeightProportion));
+
+ if (!quickReject(left, top, right, bottom)) {
+ 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);
+ }
+}
+
+/**
* We draw lines as quads (tristrips). Using GL_LINES can be difficult because the rasterization
* rules for those lines produces some unexpected results, and may vary between hardware devices.
* The basics of lines-as-quads is easy; we simply find the normal to the line and position the
@@ -1848,7 +1921,11 @@
}
int color = p->getColor();
- drawColorRect(left, top, right, bottom, color, mode);
+ if (p->isAntiAlias()) {
+ drawAARect(left, top, right, bottom, color, mode);
+ } else {
+ drawColorRect(left, top, right, bottom, color, mode);
+ }
}
void OpenGLRenderer::drawText(const char* text, int bytesCount, int count,