summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2013-07-30 19:05:20 -0700
committerChris Craik <ccraik@google.com>2013-08-02 11:29:22 -0700
commit5e49b307eb99269db2db257760508b8efd7bb97d (patch)
tree18c9f02b947e99fe8aa5b27074725b11fc6df2ba /libs/hwui
parentcb9accefb19ba6ae6fd449dc9ab62e972b51335c (diff)
downloadframeworks_base-5e49b307eb99269db2db257760508b8efd7bb97d.zip
frameworks_base-5e49b307eb99269db2db257760508b8efd7bb97d.tar.gz
frameworks_base-5e49b307eb99269db2db257760508b8efd7bb97d.tar.bz2
Fix quickReject's handling of AA ramp geometry
By having quickReject round out the window-space geometry bounds, we prevent the AA perimeter (which falls outside the local bounds passed in) from drawing outside the clip. Change-Id: I8ee36be9039a9c47906815ee2f0dbaa5eb910b82
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/DeferredDisplayList.h2
-rw-r--r--libs/hwui/DisplayListOp.h6
-rw-r--r--libs/hwui/OpenGLRenderer.cpp29
-rw-r--r--libs/hwui/OpenGLRenderer.h13
-rw-r--r--libs/hwui/Rect.h14
5 files changed, 52 insertions, 12 deletions
diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h
index 33feb7e..6c5a847 100644
--- a/libs/hwui/DeferredDisplayList.h
+++ b/libs/hwui/DeferredDisplayList.h
@@ -79,7 +79,7 @@ public:
/**
* Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
- * disallowReorder is false, respecting draw order when overlaps occur
+ * disallowReorder is false, respecting draw order when overlaps occur.
*/
void addDrawOp(OpenGLRenderer& renderer, DrawOp* op);
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 5ac2511..255b77f 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -180,7 +180,11 @@ public:
*/
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo) {}
- // returns true if bounds exist
+ /**
+ * Query the conservative, local bounds (unmapped) bounds of the op.
+ *
+ * returns true if bounds exist
+ */
virtual bool getLocalBounds(Rect& localBounds) { return false; }
// TODO: better refine localbounds usage
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index bc00ce8..24cd5cb 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1414,6 +1414,10 @@ bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state, int stateDef
if (!state.mBounds.isEmpty()) {
currentMatrix.mapRect(state.mBounds);
Rect clippedBounds(state.mBounds);
+ // NOTE: if we ever want to use this clipping info to drive whether the scissor
+ // is used, it should more closely duplicate the quickReject logic (in how it uses
+ // snapToPixelBoundaries)
+
if(!clippedBounds.intersect(currentClip)) {
// quick rejected
return true;
@@ -1608,14 +1612,21 @@ const Rect& OpenGLRenderer::getClipBounds() {
}
bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, float bottom,
- bool* clipRequired) {
+ bool snapOut, bool* clipRequired) {
if (mSnapshot->isIgnored() || bottom <= top || right <= left) {
return true;
}
Rect r(left, top, right, bottom);
currentTransform().mapRect(r);
- r.snapToPixelBoundaries();
+
+ if (snapOut) {
+ // snapOut is generally used to account for 1 pixel ramp (in window coordinates)
+ // outside of the provided rect boundaries in tessellated AA geometry
+ r.snapOutToPixelBoundaries();
+ } else {
+ r.snapToPixelBoundaries();
+ }
Rect clipRect(*mSnapshot->clipRect);
clipRect.snapToPixelBoundaries();
@@ -1628,17 +1639,21 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl
bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom,
SkPaint* paint) {
+ // AA geometry will likely have a ramp around it (not accounted for in local bounds). Snap out
+ // the final mapped rect to ensure correct clipping behavior for the ramp.
+ bool snapOut = paint->isAntiAlias();
+
if (paint->getStyle() != SkPaint::kFill_Style) {
float outset = paint->getStrokeWidth() * 0.5f;
- return quickReject(left - outset, top - outset, right + outset, bottom + outset);
+ return quickReject(left - outset, top - outset, right + outset, bottom + outset, snapOut);
} else {
- return quickReject(left, top, right, bottom);
+ return quickReject(left, top, right, bottom, snapOut);
}
}
-bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) {
+bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom, bool snapOut) {
bool clipRequired = false;
- if (quickRejectNoScissor(left, top, right, bottom, &clipRequired)) {
+ if (quickRejectNoScissor(left, top, right, bottom, snapOut, &clipRequired)) {
return true;
}
@@ -3115,7 +3130,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
bool clipRequired = false;
const bool rejected = quickRejectNoScissor(x, y,
- x + layer->layer.getWidth(), y + layer->layer.getHeight(), &clipRequired);
+ x + layer->layer.getWidth(), y + layer->layer.getHeight(), false, &clipRequired);
if (rejected) {
if (transform && !transform->isIdentity()) {
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index eb42540..2f8a2f0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -256,14 +256,15 @@ public:
ANDROID_API const Rect& getClipBounds();
/**
- * Performs a quick reject but adjust the bounds to account for stroke width if necessary
+ * Performs a quick reject but adjust the bounds to account for stroke width if necessary,
+ * and handling snapOut for AA geometry.
*/
bool quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint);
/**
* Returns false and sets scissor based upon bounds if drawing won't be clipped out
*/
- bool quickReject(float left, float top, float right, float bottom);
+ bool quickReject(float left, float top, float right, float bottom, bool snapOut = false);
bool quickReject(const Rect& bounds) {
return quickReject(bounds.left, bounds.top, bounds.right, bounds.bottom);
}
@@ -273,7 +274,7 @@ public:
* clipRequired will be only set if not rejected
*/
ANDROID_API bool quickRejectNoScissor(float left, float top, float right, float bottom,
- bool* clipRequired = NULL);
+ bool snapOut = false, bool* clipRequired = NULL);
bool quickRejectNoScissor(const Rect& bounds, bool* clipRequired = NULL) {
return quickRejectNoScissor(bounds.left, bounds.top, bounds.right, bounds.bottom,
clipRequired);
@@ -340,6 +341,12 @@ public:
SkPaint* filterPaint(SkPaint* paint);
+ /**
+ * Store the current display state (most importantly, the current clip and transform), and
+ * additionally map the state's bounds from local to window coordinates.
+ *
+ * Returns true if quick-rejected
+ */
bool storeDisplayState(DeferredDisplayState& state, int stateDeferFlags);
void restoreDisplayState(const DeferredDisplayState& state, bool skipClipRestore = false);
void setupMergedMultiDraw(const Rect* clipRect);
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 7531769..7605307 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -170,6 +170,20 @@ public:
bottom += delta;
}
+ /**
+ * Similar to snapToPixelBoundaries, but used for AA geometry with a ramp perimeter.
+ *
+ * We inset the data by a fudge factor of slightly over 1/16 (similar to when drawing non-AA
+ * lines) before rounding out so that insignificant amounts of ramp geometry (esp. from rounding
+ * errors) are ignored.
+ */
+ void snapOutToPixelBoundaries() {
+ left = floorf(left + 0.065f);
+ top = floorf(top + 0.065f);
+ right = ceilf(right - 0.065f);
+ bottom = ceilf(bottom - 0.065f);
+ }
+
void snapToPixelBoundaries() {
left = floorf(left + 0.5f);
top = floorf(top + 0.5f);