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
This commit is contained in:
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user