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

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

Fix ripples projecting to scrolled view

bug:16873774

1) Fix projectionReceiveIndex, which could in some cases point at
translate/restore ops.

2) Use background translateX / translateY for projected RenderNodes.
This makes them match background position, and thus properly account
for scroll.

Change-Id: Idbd5700858fd67c5abea0270a1012952fe09ac22
parent c28aceb1
Loading
Loading
Loading
Loading
+8 −8
Original line number Diff line number Diff line
@@ -176,15 +176,15 @@ bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
    // dirty is an out parameter and should not be recorded,
    // it matters only when replaying the display list
    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
    int opIndex = addDrawOp(op);
    mDisplayListData->addChild(op);

    if (renderNode->stagingProperties().isProjectionReceiver()) {
        // use staging property, since recording on UI thread
        mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
        mDisplayListData->projectionReceiveIndex = opIndex;
    }

    DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
    addDrawOp(op);
    mDisplayListData->addChild(op);
    return DrawGlInfo::kStatusDone;
}

@@ -447,11 +447,11 @@ void DisplayListRenderer::insertTranslate() {
    }
}

void DisplayListRenderer::addStateOp(StateOp* op) {
    addOpInternal(op);
int DisplayListRenderer::addStateOp(StateOp* op) {
    return addOpInternal(op);
}

void DisplayListRenderer::addDrawOp(DrawOp* op) {
int DisplayListRenderer::addDrawOp(DrawOp* op) {
    Rect localBounds;
    if (op->getLocalBounds(localBounds)) {
        bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
@@ -460,7 +460,7 @@ void DisplayListRenderer::addDrawOp(DrawOp* op) {
    }

    mDisplayListData->hasDrawOps = true;
    addOpInternal(op);
    return addOpInternal(op);
}

}; // namespace uirenderer
+6 −4
Original line number Diff line number Diff line
@@ -158,12 +158,14 @@ private:
    void insertTranslate();

    LinearAllocator& alloc() { return mDisplayListData->allocator; }
    void addStateOp(StateOp* op);
    void addDrawOp(DrawOp* op);
    void addOpInternal(DisplayListOp* op) {

    // Each method returns final index of op
    int addStateOp(StateOp* op);
    int addDrawOp(DrawOp* op);
    int addOpInternal(DisplayListOp* op) {
        insertRestoreToCount();
        insertTranslate();
        mDisplayListData->displayListOps.add(op);
        return mDisplayListData->displayListOps.add(op);
    }

    template<class T>
+12 −3
Original line number Diff line number Diff line
@@ -741,15 +741,24 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T&
    const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
    int restoreTo = renderer.getSaveCount();

    LinearAllocator& alloc = handler.allocator();
    handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
            PROPERTY_SAVECOUNT, properties().getClipToBounds());

    // Transform renderer to match background we're projecting onto
    // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
    const DisplayListOp* op =
            (mDisplayListData->displayListOps[mDisplayListData->projectionReceiveIndex]);
    const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
    const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties();
    renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());

    // If the projection reciever has an outline, we mask each of the projected rendernodes to it
    // Either with clipRect, or special saveLayer masking
    LinearAllocator& alloc = handler.allocator();
    if (projectionReceiverOutline != NULL) {
        const SkRect& outlineBounds = projectionReceiverOutline->getBounds();
        if (projectionReceiverOutline->isRect(NULL)) {
            // mask to the rect outline simply with clipRect
            handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
                    PROPERTY_SAVECOUNT, properties().getClipToBounds());
            ClipRectOp* clipOp = new (alloc) ClipRectOp(
                    outlineBounds.left(), outlineBounds.top(),
                    outlineBounds.right(), outlineBounds.bottom(), SkRegion::kIntersect_Op);