Loading libs/hwui/FrameBuilder.cpp +39 −1 Original line number Original line Diff line number Diff line Loading @@ -878,11 +878,49 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) { restoreForLayer(); 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 // 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 // uses state from the associated beginLayerOp, since it has all the state needed for drawing LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>( LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>( beginLayerOp.unmappedBounds, beginLayerOp.unmappedBounds, beginLayerOp.localMatrix, localMatrix, beginLayerOp.localClip, beginLayerOp.localClip, beginLayerOp.paint, beginLayerOp.paint, &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer)); &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer)); Loading libs/hwui/OpDumper.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -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 uirenderer } // namespace android } // namespace android libs/hwui/OpDumper.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ struct RecordedOp; class OpDumper { class OpDumper { public: public: static void dump(const RecordedOp& op, std::ostream& output, int level = 0); static void dump(const RecordedOp& op, std::ostream& output, int level = 0); static const char* opName(const RecordedOp& op); }; }; }; // namespace uirenderer }; // namespace uirenderer Loading libs/hwui/tests/unit/FrameBuilderTests.cpp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -2025,6 +2025,7 @@ struct SaveLayerAlphaData { uint32_t layerHeight = 0; uint32_t layerHeight = 0; Rect rectClippedBounds; Rect rectClippedBounds; Matrix4 rectMatrix; Matrix4 rectMatrix; Matrix4 drawLayerMatrix; }; }; /** /** * Constructs a view to hit the temporary layer alpha property implementation: * Constructs a view to hit the temporary layer alpha property implementation: Loading Loading @@ -2060,6 +2061,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, } } void onLayerOp(const LayerOp& op, const BakedOpState& state) override { void onLayerOp(const LayerOp& op, const BakedOpState& state) override { EXPECT_EQ(3, mIndex++); EXPECT_EQ(3, mIndex++); mOutData->drawLayerMatrix = state.computedState.transform; } } void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { EXPECT_EQ(4, mIndex++); EXPECT_EQ(4, mIndex++); Loading Loading @@ -2108,6 +2110,9 @@ RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { expected.loadTranslate(0, -2000, 0); expected.loadTranslate(0, -2000, 0); EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) << "expect content to be translated as part of being clipped"; << "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) { RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { Loading Loading
libs/hwui/FrameBuilder.cpp +39 −1 Original line number Original line Diff line number Diff line Loading @@ -878,11 +878,49 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) { restoreForLayer(); 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 // 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 // uses state from the associated beginLayerOp, since it has all the state needed for drawing LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>( LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>( beginLayerOp.unmappedBounds, beginLayerOp.unmappedBounds, beginLayerOp.localMatrix, localMatrix, beginLayerOp.localClip, beginLayerOp.localClip, beginLayerOp.paint, beginLayerOp.paint, &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer)); &(mLayerBuilders[finishedLayerIndex]->offscreenBuffer)); Loading
libs/hwui/OpDumper.cpp +4 −0 Original line number Original line Diff line number Diff line Loading @@ -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 uirenderer } // namespace android } // namespace android
libs/hwui/OpDumper.h +1 −0 Original line number Original line Diff line number Diff line Loading @@ -26,6 +26,7 @@ struct RecordedOp; class OpDumper { class OpDumper { public: public: static void dump(const RecordedOp& op, std::ostream& output, int level = 0); static void dump(const RecordedOp& op, std::ostream& output, int level = 0); static const char* opName(const RecordedOp& op); }; }; }; // namespace uirenderer }; // namespace uirenderer Loading
libs/hwui/tests/unit/FrameBuilderTests.cpp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -2025,6 +2025,7 @@ struct SaveLayerAlphaData { uint32_t layerHeight = 0; uint32_t layerHeight = 0; Rect rectClippedBounds; Rect rectClippedBounds; Matrix4 rectMatrix; Matrix4 rectMatrix; Matrix4 drawLayerMatrix; }; }; /** /** * Constructs a view to hit the temporary layer alpha property implementation: * Constructs a view to hit the temporary layer alpha property implementation: Loading Loading @@ -2060,6 +2061,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, } } void onLayerOp(const LayerOp& op, const BakedOpState& state) override { void onLayerOp(const LayerOp& op, const BakedOpState& state) override { EXPECT_EQ(3, mIndex++); EXPECT_EQ(3, mIndex++); mOutData->drawLayerMatrix = state.computedState.transform; } } void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { EXPECT_EQ(4, mIndex++); EXPECT_EQ(4, mIndex++); Loading Loading @@ -2108,6 +2110,9 @@ RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { expected.loadTranslate(0, -2000, 0); expected.loadTranslate(0, -2000, 0); EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) << "expect content to be translated as part of being clipped"; << "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) { RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { Loading