diff options
author | Chris Craik <ccraik@google.com> | 2013-07-30 19:05:20 -0700 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2013-08-02 11:29:22 -0700 |
commit | 5e49b307eb99269db2db257760508b8efd7bb97d (patch) | |
tree | 18c9f02b947e99fe8aa5b27074725b11fc6df2ba /libs/hwui | |
parent | cb9accefb19ba6ae6fd449dc9ab62e972b51335c (diff) | |
download | frameworks_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.h | 2 | ||||
-rw-r--r-- | libs/hwui/DisplayListOp.h | 6 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 29 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 13 | ||||
-rw-r--r-- | libs/hwui/Rect.h | 14 |
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); |