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

Commit 80d49021 authored by Chris Craik's avatar Chris Craik
Browse files

Wrap ViewGroup content in save/restore to protect composited children

bug:15570351

Pos Z composited children are drawn before the primary restore for a
RenderNode. This means that without an additional save/restore (which
wraps the content) they aren't protected from transformations/clips
that happen within the ViewGroup's DisplayList.

Also changes RenderNode to use OpenGLRenderer tag for displaylist
dumping consistency, and simplifies the entry points into RenderNode
drawing, since the distinction between tree root vs tree internal is
no longer important.

Change-Id: I2621eba0592c74d71f85a91a4ab3d0da2d7468d3
parent 6b2df21e
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -1475,19 +1475,19 @@ public:
    virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
            bool useQuickReject) {
        if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
            mDisplayList->deferNodeInParent(deferStruct, level + 1);
            mDisplayList->defer(deferStruct, level + 1);
        }
    }
    virtual void replay(ReplayStateStruct& replayStruct, int saveCount, int level,
            bool useQuickReject) {
        if (mDisplayList && mDisplayList->isRenderable() && !mSkipInOrderDraw) {
            mDisplayList->replayNodeInParent(replayStruct, level + 1);
            mDisplayList->replay(replayStruct, level + 1);
        }
    }

    // NOT USED since replay() is overridden
    virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) {
        return DrawGlInfo::kStatusDone;
        LOG_ALWAYS_FATAL("should not be called, because replay() is overridden");
        return 0;
    }

    virtual void output(int level, uint32_t logFlags) const {
+1 −1
Original line number Diff line number Diff line
@@ -219,7 +219,7 @@ void Layer::defer() {
            dirtyRect.right, dirtyRect.bottom, !isBlend());

    displayList->computeOrdering();
    displayList->deferNodeTree(deferredState);
    displayList->defer(deferredState, 0);

    deferredUpdateScheduled = false;
}
+2 −2
Original line number Diff line number Diff line
@@ -1942,14 +1942,14 @@ status_t OpenGLRenderer::drawDisplayList(RenderNode* displayList, Rect& dirty,
        if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
            status = startFrame();
            ReplayStateStruct replayStruct(*this, dirty, replayFlags);
            displayList->replayNodeTree(replayStruct);
            displayList->replay(replayStruct, 0);
            return status | replayStruct.mDrawGlStatus;
        }

        bool avoidOverdraw = !mCaches.debugOverdraw && !mCountOverdraw; // shh, don't tell devs!
        DeferredDisplayList deferredList(*currentClipRect(), avoidOverdraw);
        DeferStateStruct deferStruct(deferredList, *this, replayFlags);
        displayList->deferNodeTree(deferStruct);
        displayList->defer(deferStruct, 0);

        flushLayers();
        status = startFrame();
+38 −26
Original line number Diff line number Diff line
@@ -15,7 +15,7 @@
 */

#define ATRACE_TAG ATRACE_TAG_VIEW
#define LOG_TAG "RenderNode"
#define LOG_TAG "OpenGLRenderer"

#include "RenderNode.h"

@@ -523,15 +523,7 @@ private:
    const int mLevel;
};

void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) {
    DeferOperationHandler handler(deferStruct, 0);
    if (MathUtils::isPositive(properties().getZ())) {
        issueDrawShadowOperation(Matrix4::identity(), handler);
    }
    issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
}

void RenderNode::deferNodeInParent(DeferStateStruct& deferStruct, const int level) {
void RenderNode::defer(DeferStateStruct& deferStruct, const int level) {
    DeferOperationHandler handler(deferStruct, level);
    issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
}
@@ -561,15 +553,7 @@ private:
    const int mLevel;
};

void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) {
    ReplayOperationHandler handler(replayStruct, 0);
    if (MathUtils::isPositive(properties().getZ())) {
        issueDrawShadowOperation(Matrix4::identity(), handler);
    }
    issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}

void RenderNode::replayNodeInParent(ReplayStateStruct& replayStruct, const int level) {
void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) {
    ReplayOperationHandler handler(replayStruct, level);
    issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
}
@@ -628,6 +612,36 @@ void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T&
    handler(shadowOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
}

template <class T>
int RenderNode::issueOperationsOfNegZChildren(
        const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
        OpenGLRenderer& renderer, T& handler) {
    if (zTranslatedNodes.isEmpty()) return -1;

    // create a save around the body of the ViewGroup's draw method, so that
    // matrix/clip methods don't affect composited children
    int shadowSaveCount = renderer.getSaveCount();
    handler(new (handler.allocator()) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
            PROPERTY_SAVECOUNT, properties().getClipToBounds());

    issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
    return shadowSaveCount;
}

template <class T>
void RenderNode::issueOperationsOfPosZChildren(int shadowRestoreTo,
        const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
        OpenGLRenderer& renderer, T& handler) {
    if (zTranslatedNodes.isEmpty()) return;

    LOG_ALWAYS_FATAL_IF(shadowRestoreTo < 0, "invalid save to restore to");
    handler(new (handler.allocator()) RestoreToCountOp(shadowRestoreTo),
            PROPERTY_SAVECOUNT, properties().getClipToBounds());
    renderer.setOverrideLayerAlpha(1.0f);

    issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
}

#define SHADOW_DELTA 0.1f

template <class T>
@@ -701,8 +715,6 @@ template <class T>
void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
    DISPLAY_LIST_LOGD("%*s%d projected children:", (handler.level() + 1) * 2, "", mProjectedNodes.size());
    const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
    bool maskProjecteesWithPath = projectionReceiverOutline != NULL
            && !projectionReceiverOutline->isRect(NULL);
    int restoreTo = renderer.getSaveCount();

    // If the projection reciever has an outline, we mask each of the projected rendernodes to it
@@ -723,7 +735,7 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T&
            SaveLayerOp* op = new (alloc) SaveLayerOp(
                    outlineBounds.left(), outlineBounds.top(),
                    outlineBounds.right(), outlineBounds.bottom(),
                    255, SkCanvas::kARGB_ClipLayer_SaveFlag);
                    255, SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag | SkCanvas::kARGB_ClipLayer_SaveFlag);
            op->setMask(projectionReceiverOutline);
            handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());

@@ -812,7 +824,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
            buildZSortedChildList(zTranslatedNodes);

            // for 3d root, draw children with negative z values
            issueOperationsOf3dChildren(zTranslatedNodes, kNegativeZChildren, renderer, handler);
            int shadowRestoreTo = issueOperationsOfNegZChildren(zTranslatedNodes, renderer, handler);

            DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
            const int saveCountOffset = renderer.getSaveCount() - 1;
@@ -832,7 +844,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
            }

            // for 3d root, draw children with positive z values
            issueOperationsOf3dChildren(zTranslatedNodes, kPositiveZChildren, renderer, handler);
            issueOperationsOfPosZChildren(shadowRestoreTo, zTranslatedNodes, renderer, handler);
        }
    }

+10 −5
Original line number Diff line number Diff line
@@ -113,11 +113,8 @@ public:

    void computeOrdering();

    void deferNodeTree(DeferStateStruct& deferStruct);
    void deferNodeInParent(DeferStateStruct& deferStruct, const int level);

    void replayNodeTree(ReplayStateStruct& replayStruct);
    void replayNodeInParent(ReplayStateStruct& replayStruct, const int level);
    void defer(DeferStateStruct& deferStruct, const int level);
    void replay(ReplayStateStruct& replayStruct, const int level);

    ANDROID_API void output(uint32_t level = 1);
    ANDROID_API int getDebugSize();
@@ -225,6 +222,14 @@ private:
    template<class T>
    inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler);

    template <class T>
    inline int issueOperationsOfNegZChildren(
            const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
            OpenGLRenderer& renderer, T& handler);
    template <class T>
    inline void issueOperationsOfPosZChildren(int shadowRestoreTo,
            const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
            OpenGLRenderer& renderer, T& handler);
    template <class T>
    inline void issueOperationsOf3dChildren(const Vector<ZDrawDisplayListOpPair>& zTranslatedNodes,
            ChildrenSelectMode mode, OpenGLRenderer& renderer, T& handler);