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

Commit b98a016c authored by Chris Craik's avatar Chris Craik
Browse files

Fix clipping and stencil layer issues

bug:8235699

Ensure rectangle clipping operations disable deferring when necessary
(i.e., when the op might create a non-rect region), including in
DisplayList::setViewProperties

Additionally, makes clipping with a kUnion always use a region, for
consistency with software rendering

Change-Id: I6730f1a80250bcf3f91cd4afde646d470a12dbc2
parent 2b3a47b9
Loading
Loading
Loading
Loading
+12 −7
Original line number Diff line number Diff line
@@ -356,7 +356,9 @@ void DisplayList::outputViewProperties(uint32_t level) {
    }
}

void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
status_t DisplayList::setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
        int32_t flags, uint32_t level, DeferredDisplayList* deferredList) {
    status_t status = DrawGlInfo::kStatusDone;
#if DEBUG_DISPLAYLIST
    outputViewProperties(level);
#endif
@@ -377,6 +379,9 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
        }
    }
    if (mAlpha < 1 && !mCaching) {
        // flush since we'll either enter a Layer, or set alpha, both not supported in deferral
        status |= deferredList->flush(renderer, dirty, flags, level);

        if (!mHasOverlappingRendering) {
            renderer.setAlpha(mAlpha);
        } else {
@@ -392,9 +397,14 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
        }
    }
    if (mClipChildren && !mCaching) {
        if (CC_UNLIKELY(!renderer.hasRectToRectTransform())) {
            // flush, since clip will likely be a region
            status |= deferredList->flush(renderer, dirty, flags, level);
        }
        renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
                SkRegion::kIntersect_Op);
    }
    return status;
}

status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level,
@@ -414,12 +424,7 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
    DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);

    if (mAlpha < 1 && !mCaching && CC_LIKELY(deferredList)) {
        // flush before a saveLayerAlpha/setAlpha
        // TODO: make this cleaner
        drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
    }
    setViewProperties(renderer, level);
    drawGlStatus |= setViewProperties(renderer, dirty, flags, level, deferredList);

    if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
        DISPLAY_LIST_LOGD("%*sRestoreToCount %d", level * 2, "", restoreTo);
+2 −1
Original line number Diff line number Diff line
@@ -75,7 +75,8 @@ public:
        kReplayFlag_ClipChildren = 0x1
    };

    void setViewProperties(OpenGLRenderer& renderer, uint32_t level);
    status_t setViewProperties(OpenGLRenderer& renderer, Rect& dirty,
            int32_t flags, uint32_t level, DeferredDisplayList* deferredList);
    void outputViewProperties(uint32_t level);

    ANDROID_API size_t getSize();
+15 −6
Original line number Diff line number Diff line
@@ -100,7 +100,7 @@ public:
    virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
            uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList* deferredList) {
        status_t status = DrawGlInfo::kStatusDone;
        if (deferredList && requiresDrawOpFlush()) {
        if (deferredList && requiresDrawOpFlush(renderer)) {
            // will be setting renderer state that affects ops in deferredList, so flush list first
            status |= deferredList->flush(renderer, dirty, flags, level);
        }
@@ -114,7 +114,7 @@ public:
     * Returns true if it affects renderer drawing state in such a way to break deferral
     * see OpenGLRenderer::disallowDeferral()
     */
    virtual bool requiresDrawOpFlush() { return false; }
    virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return false; }
};

class DrawOp : public DisplayListOp {
@@ -272,7 +272,7 @@ public:
    }

    virtual const char* name() { return "SaveLayer"; }
    virtual bool requiresDrawOpFlush() { return true; }
    virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }

private:
    Rect mArea;
@@ -294,7 +294,7 @@ public:
    }

    virtual const char* name() { return "SaveLayerAlpha"; }
    virtual bool requiresDrawOpFlush() { return true; }
    virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }

private:
    Rect mArea;
@@ -434,7 +434,16 @@ public:

    virtual const char* name() { return "ClipRect"; }

    virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) {
        // TODO: currently, we flush when we *might* cause a clip region to exist. Ideally, we
        // should only flush when a non-rectangular clip would result
        return !renderer.hasRectToRectTransform() || !hasRectToRectOp();
    }

private:
    inline bool hasRectToRectOp() {
        return mOp == SkRegion::kIntersect_Op || mOp == SkRegion::kReplace_Op;
    }
    Rect mArea;
    SkRegion::Op mOp;
};
@@ -455,7 +464,7 @@ public:
    }

    virtual const char* name() { return "ClipPath"; }
    virtual bool requiresDrawOpFlush() { return true; }
    virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }

private:
    SkPath* mPath;
@@ -478,7 +487,7 @@ public:
    }

    virtual const char* name() { return "ClipRegion"; }
    virtual bool requiresDrawOpFlush() { return true; }
    virtual bool requiresDrawOpFlush(OpenGLRenderer& renderer) { return true; }

private:
    SkRegion* mRegion;
+8 −2
Original line number Diff line number Diff line
@@ -1284,6 +1284,10 @@ void OpenGLRenderer::setMatrix(SkMatrix* matrix) {
    }
}

bool OpenGLRenderer::hasRectToRectTransform() {
    return CC_LIKELY(mSnapshot->transform->rectToRect());
}

void OpenGLRenderer::getMatrix(SkMatrix* matrix) {
    mSnapshot->transform->copyTo(*matrix);
}
@@ -1505,8 +1509,10 @@ void OpenGLRenderer::setupDraw(bool clear) {
    if (clear) clearLayerRegions();
    // Make sure setScissor & setStencil happen at the beginning of
    // this method
    if (mDirtyClip && mCaches.scissorEnabled) {
    if (mDirtyClip) {
        if (mCaches.scissorEnabled) {
            setScissorFromClip();
        }
        setStencilFromClip();
    }
    mDescription.reset();
+1 −0
Original line number Diff line number Diff line
@@ -198,6 +198,7 @@ public:
    virtual void scale(float sx, float sy);
    virtual void skew(float sx, float sy);

    bool hasRectToRectTransform();
    ANDROID_API void getMatrix(SkMatrix* matrix);
    virtual void setMatrix(SkMatrix* matrix);
    virtual void concatMatrix(SkMatrix* matrix);
Loading