Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e49b307 authored by Chris Craik's avatar Chris Craik
Browse files

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
parent cb9accef
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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);

+5 −1
Original line number Diff line number Diff line
@@ -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
+22 −7
Original line number Diff line number Diff line
@@ -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);

    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()) {
+10 −3
Original line number Diff line number Diff line
@@ -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);
+14 −0
Original line number Diff line number Diff line
@@ -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);