Loading libs/hwui/FrameBuilder.cpp +11 −1 Original line number Diff line number Diff line Loading @@ -699,7 +699,17 @@ void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) { void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) { if (CC_UNLIKELY(!op.layer->isRenderable())) return; BakedOpState* bakedState = tryBakeOpState(op); const TextureLayerOp* textureLayerOp = &op; // Now safe to access transform (which was potentially unready at record time) if (!op.layer->getTransform().isIdentity()) { // non-identity transform present, so 'inject it' into op by copying + replacing matrix Matrix4 combinedMatrix(op.localMatrix); combinedMatrix.multiply(op.layer->getTransform()); textureLayerOp = mAllocator.create<TextureLayerOp>(op, combinedMatrix); } BakedOpState* bakedState = tryBakeOpState(*textureLayerOp); if (!bakedState) return; // quick rejected currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer); } Loading libs/hwui/RecordedOp.h +8 −0 Original line number Diff line number Diff line Loading @@ -419,6 +419,14 @@ struct TextureLayerOp : RecordedOp { TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer) : SUPER_PAINTLESS(TextureLayerOp) , layer(layer) {} // Copy an existing TextureLayerOp, replacing the underlying matrix TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix) : RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix, op.localClip, op.paint) , layer(op.layer) { } Layer* layer; }; Loading libs/hwui/RecordingCanvas.cpp +1 −7 Original line number Diff line number Diff line Loading @@ -576,15 +576,9 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) { // Note that the backing layer has *not* yet been updated, so don't trust // its width, height, transform, etc...! Matrix4 totalTransform(*(mState.currentSnapshot()->transform)); if (layerHandle->getTransform()) { Matrix4 layerTransform(*layerHandle->getTransform()); totalTransform.multiply(layerTransform); } addOp(alloc().create_trivial<TextureLayerOp>( Rect(layerHandle->getWidth(), layerHandle->getHeight()), totalTransform, *(mState.currentSnapshot()->transform), getRecordedClip(), layerHandle->backingLayer())); } Loading libs/hwui/tests/common/TestUtils.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( renderthread::RenderThread& renderThread, uint32_t width, uint32_t height, const SkMatrix& transform) { Layer* layer = LayerRenderer::createTextureLayer(renderThread.renderState()); layer->getTransform().load(transform); sp<DeferredLayerUpdater> layerUpdater = new DeferredLayerUpdater(layer); layerUpdater->setSize(width, height); Loading libs/hwui/tests/unit/FrameBuilderTests.cpp +48 −3 Original line number Diff line number Diff line Loading @@ -372,8 +372,8 @@ RENDERTHREAD_TEST(FrameBuilder, textStyle) { EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; } RENDERTHREAD_TEST(FrameBuilder, textureLayer) { class TextureLayerTestRenderer : public TestRendererBase { RENDERTHREAD_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { public: void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { EXPECT_EQ(0, mIndex++); Loading @@ -398,11 +398,56 @@ RENDERTHREAD_TEST(FrameBuilder, textureLayer) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); TextureLayerTestRenderer renderer; TextureLayerClipLocalMatrixTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()); } RENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { public: void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { EXPECT_EQ(0, mIndex++); Matrix4 expected; expected.loadTranslate(35, 45, 0); EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); } }; auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5)); auto node = TestUtils::createNode(0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { canvas.save(SaveFlags::MatrixClip); canvas.translate(30, 40); canvas.drawLayer(layerUpdater.get()); canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); TextureLayerCombineMatricesTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()); } RENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5)); layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected auto node = TestUtils::createNode(0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { canvas.drawLayer(layerUpdater.get()); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); FailRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); } RENDERTHREAD_TEST(FrameBuilder, functor_reject) { class FunctorTestRenderer : public TestRendererBase { public: Loading Loading
libs/hwui/FrameBuilder.cpp +11 −1 Original line number Diff line number Diff line Loading @@ -699,7 +699,17 @@ void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) { void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) { if (CC_UNLIKELY(!op.layer->isRenderable())) return; BakedOpState* bakedState = tryBakeOpState(op); const TextureLayerOp* textureLayerOp = &op; // Now safe to access transform (which was potentially unready at record time) if (!op.layer->getTransform().isIdentity()) { // non-identity transform present, so 'inject it' into op by copying + replacing matrix Matrix4 combinedMatrix(op.localMatrix); combinedMatrix.multiply(op.layer->getTransform()); textureLayerOp = mAllocator.create<TextureLayerOp>(op, combinedMatrix); } BakedOpState* bakedState = tryBakeOpState(*textureLayerOp); if (!bakedState) return; // quick rejected currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer); } Loading
libs/hwui/RecordedOp.h +8 −0 Original line number Diff line number Diff line Loading @@ -419,6 +419,14 @@ struct TextureLayerOp : RecordedOp { TextureLayerOp(BASE_PARAMS_PAINTLESS, Layer* layer) : SUPER_PAINTLESS(TextureLayerOp) , layer(layer) {} // Copy an existing TextureLayerOp, replacing the underlying matrix TextureLayerOp(const TextureLayerOp& op, const Matrix4& replacementMatrix) : RecordedOp(RecordedOpId::TextureLayerOp, op.unmappedBounds, replacementMatrix, op.localClip, op.paint) , layer(op.layer) { } Layer* layer; }; Loading
libs/hwui/RecordingCanvas.cpp +1 −7 Original line number Diff line number Diff line Loading @@ -576,15 +576,9 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) { // Note that the backing layer has *not* yet been updated, so don't trust // its width, height, transform, etc...! Matrix4 totalTransform(*(mState.currentSnapshot()->transform)); if (layerHandle->getTransform()) { Matrix4 layerTransform(*layerHandle->getTransform()); totalTransform.multiply(layerTransform); } addOp(alloc().create_trivial<TextureLayerOp>( Rect(layerHandle->getWidth(), layerHandle->getHeight()), totalTransform, *(mState.currentSnapshot()->transform), getRecordedClip(), layerHandle->backingLayer())); } Loading
libs/hwui/tests/common/TestUtils.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -44,6 +44,7 @@ sp<DeferredLayerUpdater> TestUtils::createTextureLayerUpdater( renderthread::RenderThread& renderThread, uint32_t width, uint32_t height, const SkMatrix& transform) { Layer* layer = LayerRenderer::createTextureLayer(renderThread.renderState()); layer->getTransform().load(transform); sp<DeferredLayerUpdater> layerUpdater = new DeferredLayerUpdater(layer); layerUpdater->setSize(width, height); Loading
libs/hwui/tests/unit/FrameBuilderTests.cpp +48 −3 Original line number Diff line number Diff line Loading @@ -372,8 +372,8 @@ RENDERTHREAD_TEST(FrameBuilder, textStyle) { EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; } RENDERTHREAD_TEST(FrameBuilder, textureLayer) { class TextureLayerTestRenderer : public TestRendererBase { RENDERTHREAD_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { public: void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { EXPECT_EQ(0, mIndex++); Loading @@ -398,11 +398,56 @@ RENDERTHREAD_TEST(FrameBuilder, textureLayer) { }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); TextureLayerTestRenderer renderer; TextureLayerClipLocalMatrixTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()); } RENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { public: void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { EXPECT_EQ(0, mIndex++); Matrix4 expected; expected.loadTranslate(35, 45, 0); EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); } }; auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5)); auto node = TestUtils::createNode(0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { canvas.save(SaveFlags::MatrixClip); canvas.translate(30, 40); canvas.drawLayer(layerUpdater.get()); canvas.restore(); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); TextureLayerCombineMatricesTestRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); EXPECT_EQ(1, renderer.getIndex()); } RENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, SkMatrix::MakeTrans(5, 5)); layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected auto node = TestUtils::createNode(0, 0, 200, 200, [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { canvas.drawLayer(layerUpdater.get()); }); FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); FailRenderer renderer; frameBuilder.replayBakedOps<TestDispatcher>(renderer); } RENDERTHREAD_TEST(FrameBuilder, functor_reject) { class FunctorTestRenderer : public TestRendererBase { public: Loading