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

Commit c9bb1a38 authored by John Reck's avatar John Reck
Browse files

Fix a translate issue with saveLayer

Bug: 28667141

saveLayer clips the layer to the size it needs to
be and will translate content if necessary, but
the drawLayerOp that results from that was not
translated to handle the shifted draw content.

This fixes that

Change-Id: I3c9ffd5d0282fa1b958bced94c25e9744281e9be
parent 2a4001ee
Loading
Loading
Loading
Loading
+39 −1
Original line number Diff line number Diff line
@@ -878,11 +878,49 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {

    restoreForLayer();

    // saveLayer will clip & translate the draw contents, so we need
    // to translate the drawLayer by how much the contents was translated
    // TODO: Unify this with beginLayerOp so we don't have to calculate this
    // twice
    uint32_t layerWidth = (uint32_t) beginLayerOp.unmappedBounds.getWidth();
    uint32_t layerHeight = (uint32_t) beginLayerOp.unmappedBounds.getHeight();

    auto previous = mCanvasState.currentSnapshot();
    Vector3 lightCenter = previous->getRelativeLightCenter();

    // Combine all transforms used to present saveLayer content:
    // parent content transform * canvas transform * bounds offset
    Matrix4 contentTransform(*(previous->transform));
    contentTransform.multiply(beginLayerOp.localMatrix);
    contentTransform.translate(beginLayerOp.unmappedBounds.left,
            beginLayerOp.unmappedBounds.top);

    Matrix4 inverseContentTransform;
    inverseContentTransform.loadInverse(contentTransform);

    // map the light center into layer-relative space
    inverseContentTransform.mapPoint3d(lightCenter);

    // Clip bounds of temporary layer to parent's clip rect, so:
    Rect saveLayerBounds(layerWidth, layerHeight);
    //     1) transform Rect(width, height) into parent's space
    //        note: left/top offsets put in contentTransform above
    contentTransform.mapRect(saveLayerBounds);
    //     2) intersect with parent's clip
    saveLayerBounds.doIntersect(previous->getRenderTargetClip());
    //     3) and transform back
    inverseContentTransform.mapRect(saveLayerBounds);
    saveLayerBounds.doIntersect(Rect(layerWidth, layerHeight));
    saveLayerBounds.roundOut();

    Matrix4 localMatrix(beginLayerOp.localMatrix);
    localMatrix.translate(saveLayerBounds.left, saveLayerBounds.top);

    // record the draw operation into the previous layer's list of draw commands
    // uses state from the associated beginLayerOp, since it has all the state needed for drawing
    LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(
            beginLayerOp.unmappedBounds,
            beginLayerOp.localMatrix,
            localMatrix,
            beginLayerOp.localClip,
            beginLayerOp.paint,
            &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer));
+4 −0
Original line number Diff line number Diff line
@@ -45,5 +45,9 @@ void OpDumper::dump(const RecordedOp& op, std::ostream& output, int level) {
    }
}

const char* OpDumper::opName(const RecordedOp& op) {
    return sOpNameLut[op.opId];
}

} // namespace uirenderer
} // namespace android
+1 −0
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ struct RecordedOp;
class OpDumper {
public:
    static void dump(const RecordedOp& op, std::ostream& output, int level = 0);
    static const char* opName(const RecordedOp& op);
};

}; // namespace uirenderer
+5 −0
Original line number Diff line number Diff line
@@ -2025,6 +2025,7 @@ struct SaveLayerAlphaData {
    uint32_t layerHeight = 0;
    Rect rectClippedBounds;
    Matrix4 rectMatrix;
    Matrix4 drawLayerMatrix;
};
/**
 * Constructs a view to hit the temporary layer alpha property implementation:
@@ -2060,6 +2061,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
        }
        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
            EXPECT_EQ(3, mIndex++);
            mOutData->drawLayerMatrix = state.computedState.transform;
        }
        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
            EXPECT_EQ(4, mIndex++);
@@ -2108,6 +2110,9 @@ RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
    expected.loadTranslate(0, -2000, 0);
    EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
            << "expect content to be translated as part of being clipped";
    expected.loadTranslate(10, 0, 0);
    EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
                << "expect drawLayer to be translated as part of being clipped";
}

RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {