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

Commit 1df26446 authored by Chris Craik's avatar Chris Craik
Browse files

Rework and clean up DisplayList projection

Move the projection surface to be a property of a DisplayList,
set to true for every background drawable.

Additionally, handle a projecting view background such that it doesn't
try to project onto itself (which is undesirable).

Change-Id: Ic70b17474bd87340e80767f8518f73b233419c7a
parent d5154ec2
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -430,6 +430,17 @@ public class DisplayList {
        }
    }

    /**
     * Sets whether the display list is a projection receiver - that its parent
     * DisplayList should draw any descendent DisplayLists with
     * ProjectBackwards=true directly on top of it. Default value is false.
     */
    public void setProjectionReceiver(boolean shouldRecieve) {
        if (hasNativeDisplayList()) {
            nSetProjectionReceiver(mFinalizer.mNativeDisplayList, shouldRecieve);
        }
    }

    /**
     * Sets the outline, defining the shape that casts a shadow.
     *
@@ -1065,6 +1076,7 @@ public class DisplayList {
    private static native void nSetCaching(long displayList, boolean caching);
    private static native void nSetClipToBounds(long displayList, boolean clipToBounds);
    private static native void nSetProjectBackwards(long displayList, boolean shouldProject);
    private static native void nSetProjectionReceiver(long displayList, boolean shouldRecieve);
    private static native void nSetIsolatedZVolume(long displayList, boolean isolateZVolume);
    private static native void nSetOutline(long displayList, long nativePath);
    private static native void nSetAlpha(long displayList, float alpha);
+1 −7
Original line number Diff line number Diff line
@@ -2335,7 +2335,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     *                               1   PFLAG3_IS_LAID_OUT
     *                              1    PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT
     *                             1     PFLAG3_CALLED_SUPER
     *                            1      PFLAG3_PROJECT_BACKGROUND
     * |-------|-------|-------|-------|
     */
@@ -2371,12 +2370,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     */
    static final int PFLAG3_CALLED_SUPER = 0x10;
    /**
     * Flag indicating that the background of this view will be drawn into a
     * display list and projected onto the closest parent projection surface.
     */
    static final int PFLAG3_PROJECT_BACKGROUND = 0x20;
    /* End of masks for mPrivateFlags3 */
    static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
@@ -15014,6 +15007,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
        // Set up drawable properties that are view-independent.
        displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
        displayList.setProjectBackwards(drawable.isProjected());
        displayList.setProjectionReceiver(true);
        displayList.setClipToBounds(false);
        return displayList;
    }
+8 −1
Original line number Diff line number Diff line
@@ -117,6 +117,12 @@ static void android_view_DisplayList_setProjectBackwards(JNIEnv* env,
    displayList->setProjectBackwards(shouldProject);
}

static void android_view_DisplayList_setProjectionReceiver(JNIEnv* env,
        jobject clazz, jlong displayListPtr, jboolean shouldRecieve) {
    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
    displayList->setProjectionReceiver(shouldRecieve);
}

static void android_view_DisplayList_setOutline(JNIEnv* env,
        jobject clazz, jlong displayListPtr, jlong outlinePathPtr) {
    DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr);
@@ -392,6 +398,7 @@ static JNINativeMethod gMethods[] = {
    { "nSetClipToBounds",      "(JZ)V",  (void*) android_view_DisplayList_setClipToBounds },
    { "nSetIsolatedZVolume",   "(JZ)V",  (void*) android_view_DisplayList_setIsolatedZVolume },
    { "nSetProjectBackwards",  "(JZ)V",  (void*) android_view_DisplayList_setProjectBackwards },
    { "nSetProjectionReceiver","(JZ)V",  (void*) android_view_DisplayList_setProjectionReceiver },
    { "nSetOutline",           "(JJ)V",  (void*) android_view_DisplayList_setOutline },
    { "nSetAlpha",             "(JF)V",  (void*) android_view_DisplayList_setAlpha },
    { "nSetHasOverlappingRendering", "(JZ)V",
+44 −24
Original line number Diff line number Diff line
@@ -240,6 +240,7 @@ void DisplayList::init() {
    mClipToBounds = true;
    mIsolatedZVolume = true;
    mProjectBackwards = false;
    mProjectionReceiver = false;
    mOutline.rewind();
    mAlpha = 1;
    mHasOverlappingRendering = true;
@@ -524,6 +525,7 @@ void DisplayList::computeOrderingImpl(
        const mat4* transformFromProjectionSurface) {
    m3dNodes.clear();
    mProjectedNodes.clear();
    if (mDisplayListData == NULL || mSize == 0) return;

    // TODO: should avoid this calculation in most cases
    // TODO: just calculate single matrix, down to all leaf composited elements
@@ -553,6 +555,7 @@ void DisplayList::computeOrderingImpl(
        opState->mSkipInOrderDraw = false;
    }

    if (mDisplayListData->children.size() > 0) {
        if (mIsolatedZVolume) {
            // create a new 3d space for descendents by collecting them
            compositedChildrenOf3dRoot = &m3dNodes;
@@ -562,23 +565,36 @@ void DisplayList::computeOrderingImpl(
            transformFrom3dRoot = &localTransformFrom3dRoot;
        }

    if (mDisplayListData != NULL && mDisplayListData->projectionIndex >= 0) {
        // create a new projection surface for descendents by collecting them
        compositedChildrenOfProjectionSurface = &mProjectedNodes;
        transformFromProjectionSurface = &mat4::identity();
        const bool isProjectionReceiver = mDisplayListData->projectionReceiveIndex >= 0;
        bool haveAppliedPropertiesToProjection = false;
        for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
            DrawDisplayListOp* childOp = mDisplayListData->children[i];
            DisplayList* child = childOp->mDisplayList;

            Vector<DrawDisplayListOp*>* projectionChildren = NULL;
            const mat4* projectionTransform = NULL;
            if (isProjectionReceiver && !child->mProjectBackwards) {
                // if receiving projections, collect projecting descendent

                // Note that if a direct descendent is projecting backwards, we pass it's
                // grandparent projection collection, since it shouldn't project onto it's
                // parent, where it will already be drawing.
                projectionChildren = &mProjectedNodes;
                projectionTransform = &mat4::identity();
            } else {
                if (!haveAppliedPropertiesToProjection) {
                    applyViewPropertyTransforms(localTransformFromProjectionSurface);
        transformFromProjectionSurface = &localTransformFromProjectionSurface;
                    haveAppliedPropertiesToProjection = true;
                }

    if (mDisplayListData != NULL && mDisplayListData->children.size() > 0) {
        for (unsigned int i = 0; i < mDisplayListData->children.size(); i++) {
            DrawDisplayListOp* childOp = mDisplayListData->children[i];
            childOp->mDisplayList->computeOrderingImpl(childOp,
                projectionChildren = compositedChildrenOfProjectionSurface;
                projectionTransform = &localTransformFromProjectionSurface;
            }
            child->computeOrderingImpl(childOp,
                    compositedChildrenOf3dRoot, transformFrom3dRoot,
                    compositedChildrenOfProjectionSurface, transformFromProjectionSurface);
                    projectionChildren, projectionTransform);
        }
    }

}

class DeferOperationHandler {
@@ -638,11 +654,11 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren
        return;
    }

    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
    LinearAllocator& alloc = handler.allocator();
    ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight,
            SkRegion::kIntersect_Op); // clip to 3d root bounds for now
    handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds);
    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);

    for (size_t i = 0; i < m3dNodes.size(); i++) {
        const float zValue = m3dNodes[i].key;
@@ -677,18 +693,22 @@ void DisplayList::iterate3dChildren(ChildrenSelectMode mode, OpenGLRenderer& ren

template <class T>
void DisplayList::iterateProjectedChildren(OpenGLRenderer& renderer, T& handler, const int level) {
    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
    LinearAllocator& alloc = handler.allocator();
    ClipRectOp* clipOp = new (alloc) ClipRectOp(0, 0, mWidth, mHeight,
            SkRegion::kReplace_Op); // clip to projection surface root bounds
    handler(clipOp, PROPERTY_SAVECOUNT, mClipToBounds);
    int rootRestoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);

    for (size_t i = 0; i < mProjectedNodes.size(); i++) {
        DrawDisplayListOp* childOp = mProjectedNodes[i];

        // matrix save, concat, and restore can be done safely without allocating operations
        int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag);
        renderer.concatMatrix(childOp->mTransformFromCompositingAncestor);
        childOp->mSkipInOrderDraw = false; // this is horrible, I'm so sorry everyone
        handler(childOp, renderer.getSaveCount() - 1, mClipToBounds);
        childOp->mSkipInOrderDraw = true;
        renderer.restoreToCount(restoreTo);
    }
    handler(new (alloc) RestoreToCountOp(rootRestoreTo), PROPERTY_SAVECOUNT, mClipToBounds);
}
@@ -740,7 +760,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level)

        DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
        const int saveCountOffset = renderer.getSaveCount() - 1;
        const int projectionIndex = mDisplayListData->projectionIndex;
        const int projectionReceiveIndex = mDisplayListData->projectionReceiveIndex;
        for (unsigned int i = 0; i < mDisplayListData->displayListOps.size(); i++) {
            DisplayListOp *op = mDisplayListData->displayListOps[i];

@@ -751,7 +771,7 @@ void DisplayList::iterate(OpenGLRenderer& renderer, T& handler, const int level)
            logBuffer.writeCommand(level, op->name());
            handler(op, saveCountOffset, mClipToBounds);

            if (CC_UNLIKELY(i == projectionIndex && mProjectedNodes.size() > 0)) {
            if (CC_UNLIKELY(i == projectionReceiveIndex && mProjectedNodes.size() > 0)) {
                iterateProjectedChildren(renderer, handler, level);
            }
        }
+11 −3
Original line number Diff line number Diff line
@@ -112,7 +112,7 @@ public:
 */
class DisplayListData : public LightRefBase<DisplayListData> {
public:
    DisplayListData() : projectionIndex(-1) {}
    DisplayListData() : projectionReceiveIndex(-1) {}
    // allocator into which all ops were allocated
    LinearAllocator allocator;

@@ -123,8 +123,7 @@ public:
    Vector<DrawDisplayListOp*> children;

    // index of DisplayListOp restore, after which projected descendents should be drawn
    int projectionIndex;
    Matrix4 projectionTransform;
    int projectionReceiveIndex;
};

/**
@@ -198,6 +197,14 @@ public:
        mProjectBackwards = shouldProject;
    }

    void setProjectionReceiver(bool shouldRecieve) {
        mProjectionReceiver = shouldRecieve;
    }

    bool isProjectionReceiver() {
        return mProjectionReceiver;
    }

    void setOutline(const SkPath* outline) {
        if (!outline) {
            mOutline.reset();
@@ -600,6 +607,7 @@ private:
    bool mClipToBounds;
    bool mIsolatedZVolume;
    bool mProjectBackwards;
    bool mProjectionReceiver;
    SkPath mOutline;
    float mAlpha;
    bool mHasOverlappingRendering;
Loading