diff options
author | Chet Haase <chet@google.com> | 2011-05-12 14:57:51 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-05-12 14:57:51 -0700 |
commit | 674b595fa5299d138e068b2b786027d6d6225394 (patch) | |
tree | 9a43e7d0b48025744da3b5e9e5741c1beb45a171 | |
parent | 1f5e3a1af338d23838de059d7b270e89d54efa00 (diff) | |
parent | 858aa93ddb6e69e0503382af63bb681b6728aef1 (diff) | |
download | frameworks_base-674b595fa5299d138e068b2b786027d6d6225394.zip frameworks_base-674b595fa5299d138e068b2b786027d6d6225394.tar.gz frameworks_base-674b595fa5299d138e068b2b786027d6d6225394.tar.bz2 |
Merge "Antialiasing for rectangles"
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 79 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 3 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 9 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java | 124 |
4 files changed, 214 insertions, 1 deletions
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 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int } /** + * 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 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, } 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, diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 271e4b1..ffacbfc 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -285,6 +285,9 @@ private: void drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint); + void drawAARect(float left, float top, float right, float bottom, + int color, SkXfermode::Mode mode); + /** * Draws a textured rectangle with the specified texture. The specified coordinates * are transformed by the current snapshot's transform matrix. diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 6285880..c1aa215 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -93,6 +93,15 @@ </activity> <activity + android:name="ColoredRectsActivity" + android:label="_Rects"> + <intent-filter> + <action android:name="android.intent.action.MAIN" /> + <category android:name="android.intent.category.LAUNCHER" /> + </intent-filter> + </activity> + + <activity android:name="SimplePatchActivity" android:label="_SimplePatch" android:theme="@android:style/Theme.Translucent.NoTitleBar"> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java new file mode 100644 index 0000000..e8cdbc3 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ColoredRectsActivity.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.test.hwui; + +import android.animation.ObjectAnimator; +import android.app.Activity; +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.ColorDrawable; +import android.os.Bundle; +import android.view.View; +import android.widget.FrameLayout; + +@SuppressWarnings({"UnusedDeclaration"}) +public class ColoredRectsActivity extends Activity { + private ObjectAnimator mAnimator; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + getWindow().setBackgroundDrawable(new ColorDrawable(0xff000000)); + FrameLayout frame = new FrameLayout(this); + final RectsView gpuView = new RectsView(this, 0, Color.GREEN); + frame.addView(gpuView); + final RectsView swView = new RectsView(this, 400, Color.RED); + swView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + frame.addView(swView); + final RectsView hwBothView = new RectsView(this, 850, Color.GREEN); + // Don't actually need to render to a hw layer, but it's a good sanity-check that + // we're rendering to/from layers correctly + hwBothView.setLayerType(View.LAYER_TYPE_HARDWARE, null); + frame.addView(hwBothView); + final RectsView swBothView = new RectsView(this, 854, Color.RED); + swBothView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); + frame.addView(swBothView); + setContentView(frame); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + } + + public static class RectsView extends View { + + private float mOffset; + private int mColor; + + public RectsView(Context c, float offset, int color) { + super(c); + mOffset = offset; + mColor = color; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + Paint p = new Paint(); + p.setColor(mColor); + float yOffset = 10; + + for (int i = 0; i < 2; ++i) { + canvas.save(); + canvas.translate(mOffset, yOffset); + canvas.drawRect(0, 0, 20, 10, p); + canvas.drawRect(35, 0, 45, 20, p); + canvas.translate(0, -yOffset); + canvas.scale(2, 2); + canvas.translate(60, yOffset/2); + canvas.drawRect(0, 0, 20, 10, p); + canvas.translate(15, 0); + canvas.drawRect(35, 0, 45, 20, p); + canvas.restore(); + + yOffset += 100; + + canvas.save(); + canvas.save(); + canvas.translate(mOffset + 10, yOffset); + canvas.rotate(45); + canvas.drawRect(0, 0, 20, 10, p); + canvas.restore(); + canvas.save(); + canvas.translate(mOffset + 70, yOffset); + canvas.rotate(5); + canvas.drawRect(0, 0, 20, 10, p); + canvas.restore(); + canvas.save(); + canvas.translate(mOffset + 140, yOffset); + canvas.scale(2, 2); + canvas.rotate(5); + canvas.drawRect(0, 0, 20, 10, p); + canvas.restore(); + canvas.save(); + canvas.translate(mOffset + 210, yOffset); + canvas.scale(2, 2); + canvas.rotate(45); + canvas.drawRect(0, 0, 20, 10, p); + canvas.restore(); + canvas.restore(); + + yOffset += 100; + + p.setAntiAlias(true); + } + } + } +} |