FrameBuilderTests.cpp revision 6c67f1d04591f44bccb476d715a005ad5bbdf840
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 25ea1724be4d3b6039818f91fc087e1216c1463d5Chris Craik * Copyright (C) 2016 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <gtest/gtest.h> 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <BakedOpState.h> 20d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include <DeferredLayerUpdater.h> 21f158b49c888f722194afe5a80539a2b020c130bcChris Craik#include <FrameBuilder.h> 228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik#include <LayerUpdateQueue.h> 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordedOp.h> 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordingCanvas.h> 258160f20b0aca8c6595d4b385d673f59b6bcd16a4Chris Craik#include <tests/common/TestUtils.h> 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <unordered_map> 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 326e068c0182f6f85bccb855a647510724d1c65a13Chris Craikconst FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 336e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 355854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 365854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 42d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 455854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 475854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 48d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 4974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 50a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 51a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik virtual void recycleTemporaryLayer(OffscreenBuffer*) { 5374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 5474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 5598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 56a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 57a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 58a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 59a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 60a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 6198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 62e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 635854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 66a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 67a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 68a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 697cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 777cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 875854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 915854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 955854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 966fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 977cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 9815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1057cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1095854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1113a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simple) { 112d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 113d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 115d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 116d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 117d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 118d3daa3198e2212c985c634821682d5819346b653Chris Craik } 119d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 120d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 121d3daa3198e2212c985c634821682d5819346b653Chris Craik } 122d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 123d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 124d3daa3198e2212c985c634821682d5819346b653Chris Craik } 125e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 126d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 127d3daa3198e2212c985c634821682d5819346b653Chris Craik } 128d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 129d3daa3198e2212c985c634821682d5819346b653Chris Craik 13006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 200, 1318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 132aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25)); 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 134aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 10, 10, nullptr); 135b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 1369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 1379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleTestRenderer renderer; 141f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1425854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end 1436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 1446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1453a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleStroke) { 146386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik class SimpleStrokeTestRenderer : public TestRendererBase { 147386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik public: 148386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik void onPointsOp(const PointsOp& op, const BakedOpState& state) override { 149386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(0, mIndex++); 150386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // even though initial bounds are empty... 151386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_TRUE(op.unmappedBounds.isEmpty()) 152386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "initial bounds should be empty, since they're unstroked"; 153386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(Rect(45, 45, 55, 55), state.computedState.clippedBounds) 154386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "final bounds should account for stroke"; 155386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 156386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }; 157386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 15806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 200, 159386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 160386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPaint strokedPaint; 161386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik strokedPaint.setStrokeWidth(10); 162386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik canvas.drawPoint(50, 50, strokedPaint); 163386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }); 1649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 1659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 168386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 169f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 170386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 171386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 172386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 1733a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleRejection) { 17406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 176eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 1776c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); // intersection should be empty 1786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 1806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 1819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 1829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 186f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1893a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleBatching) { 190a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 191d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 192d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 193d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 194a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 195d3daa3198e2212c985c634821682d5819346b653Chris Craik } 196d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 197a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 198d3daa3198e2212c985c634821682d5819346b653Chris Craik } 199d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 200d3daa3198e2212c985c634821682d5819346b653Chris Craik 20106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 2028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 203aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv 204aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10, 205aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv kAlpha_8_SkColorType)); // Disable merging by using alpha 8 bitmap 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 209eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 210a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 213aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 5, 0, nullptr); 214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 2179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 2189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 220b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2215854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 222f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 223a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 22415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 225a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 226a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 2279cd1bbe5c9e14472e631d8cc10005613925f34afChris CraikRENDERTHREAD_TEST(FrameBuilder, deferRenderNode_translateClip) { 2289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik class DeferRenderNodeTranslateClipTestRenderer : public TestRendererBase { 2299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public: 2309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(0, mIndex++); 2329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(5, 10, 55, 60), state.computedState.clippedBounds); 2339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom, 2349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik state.computedState.clipSideFlags); 2359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }; 2379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 23806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 2409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 2419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }); 2429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(5, 10, Rect(50, 50), // translate + clip node 2469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik *TestUtils::getSyncedNode(node)); 2479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik DeferRenderNodeTranslateClipTestRenderer renderer; 2499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(1, renderer.getIndex()); 2519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik} 2529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2539cd1bbe5c9e14472e631d8cc10005613925f34afChris CraikRENDERTHREAD_TEST(FrameBuilder, deferRenderNodeScene) { 2549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik class DeferRenderNodeSceneTestRenderer : public TestRendererBase { 2559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public: 2569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik const Rect& clippedBounds = state.computedState.clippedBounds; 2589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik Matrix4 expected; 2599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik switch (mIndex++) { 2609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 0: 2619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // background - left side 2629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(600, 100, 700, 500), clippedBounds); 2639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(100, 100, 0); 2649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 1: 2669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // background - top side 2679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(100, 400, 600, 500), clippedBounds); 2689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(100, 100, 0); 2699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 2: 2719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // content 2729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(100, 100, 700, 500), clippedBounds); 2739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(-50, -50, 0); 2749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 3: 2769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // overlay 2779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(0, 0, 800, 200), clippedBounds); 2789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik default: 2809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik ADD_FAILURE() << "Too many rects observed"; 2819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(expected, state.computedState.transform); 2839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }; 2859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik std::vector<sp<RenderNode>> nodes; 2879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik SkPaint transparentPaint; 2889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik transparentPaint.setAlpha(128); 2899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // backdrop 29106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev nodes.push_back(TestUtils::createNode<RecordingCanvas>(100, 100, 700, 500, // 600x400 2929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 2939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 600, 400, transparentPaint); 2949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 2959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // content 2979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik Rect contentDrawBounds(150, 150, 650, 450); // 500x300 29806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600, 2999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 3009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 800, 600, transparentPaint); 3019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // overlay 30406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600, 3059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 3069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 800, 200, transparentPaint); 3079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik for (auto& node : nodes) { 3109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik TestUtils::syncHierarchyPropertiesAndDisplayList(node); 3119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 3129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600, 3149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 3159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds); 3169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik DeferRenderNodeSceneTestRenderer renderer; 3189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(4, renderer.getIndex()); 3209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik} 3219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3226246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, empty_noFbo0) { 3236246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyNoFbo0TestRenderer : public TestRendererBase { 3246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 3256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 3266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 3276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 3296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 3306246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 3326246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // Use layer update constructor, so no work is enqueued for Fbo0 3349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik LayerUpdateQueue emptyLayerUpdateQueue; 3359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(emptyLayerUpdateQueue, sLightGeometry, Caches::getInstance()); 3366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyNoFbo0TestRenderer renderer; 3376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 3396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, empty_withFbo0) { 3416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyWithFbo0TestRenderer : public TestRendererBase { 3426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 3436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 3446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 3456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 3476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 3486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 35006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 3516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 3526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // no drawn content 3536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 3546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // Draw, but pass node without draw content, so no work is done for primary frame 3569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 3579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 3589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 3599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyWithFbo0TestRenderer renderer; 3616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced," 3636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik " but fbo0 update lifecycle should still be observed"; 3646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 3656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 36680d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikRENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_rects) { 36780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawRectsTestRenderer : public TestRendererBase { 36880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 36980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 37080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(mIndex++, 0) << "Should be one rect"; 37180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds) 37280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Last rect should occlude others."; 37380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 37480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 37506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 37680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 37780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 37880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 37980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 38080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 38180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 38280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // Damage (and therefore clip) is same as last draw, subset of renderable area. 38380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // This means last op occludes other contents, and they'll be rejected to avoid overdraw. 3849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200, 3859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 3869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 38780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 38880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(3u, node->getDisplayList()->getOps().size()) 38980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 39080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 39180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawRectsTestRenderer renderer; 39280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 39380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op"; 39480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 39580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 39680d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikRENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_bitmaps) { 397aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv static sk_sp<Bitmap> opaqueBitmap(TestUtils::createBitmap(50, 50, 398aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv SkColorType::kRGB_565_SkColorType)); 399aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv static sk_sp<Bitmap> transpBitmap(TestUtils::createBitmap(50, 50, 400aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv SkColorType::kAlpha_8_SkColorType)); 40180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase { 40280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 40380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 40480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik switch(mIndex++) { 40580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 0: 406ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv EXPECT_EQ(opaqueBitmap.get(), op.bitmap); 40780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 40880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 1: 409ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv EXPECT_EQ(transpBitmap.get(), op.bitmap); 41080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 41180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik default: 41280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik ADD_FAILURE() << "Only two ops expected."; 41380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 41480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 41580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 41680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 41706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 50, 50, 41880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 41980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 42080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 421aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*transpBitmap, 0, 0, nullptr); 42280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 42380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // only the below draws should remain, since they're 424aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*opaqueBitmap, 0, 0, nullptr); 425aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*transpBitmap, 0, 0, nullptr); 42680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 4279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50, 4289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 43080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 43180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(5u, node->getDisplayList()->getOps().size()) 43280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 43380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 43480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawBitmapsTestRenderer renderer; 43580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 436a82ffc549bd6dbf8cfc6f4d646d0f458dca54014sergeyv EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops"; 43780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 43880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 4393a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clippedMerging) { 44093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 44193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 44293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 44393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 44493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 44593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 44693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 44793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 44893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 44993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 45093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 45106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 45206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 453aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20)); 45493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 45593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 4566c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace); 457aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 0, 40, nullptr); 45893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 45993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 4606c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace); 461aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 40, 0, nullptr); 46293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 46393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 4646c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace); 465aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 80, 40, nullptr); 46693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 46793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 4686c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace); 469aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 40, 70, nullptr); 47093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 47193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 4729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 4739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 4759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 47693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 477f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 47893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 47993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 48093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 481f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris CraikRENDERTHREAD_TEST(FrameBuilder, regionClipStopsMerge) { 482f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik class RegionClipStopsMergeTestRenderer : public TestRendererBase { 483f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik public: 484f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; } 485f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik }; 486f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 487f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 488f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik SkPath path; 489f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik path.addCircle(200, 200, 200, SkPath::kCW_Direction); 490f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik canvas.save(SaveFlags::MatrixClip); 4916c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipPath(&path, SkClipOp::kIntersect); 492f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik SkPaint paint; 493f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 494f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik paint.setAntiAlias(true); 495f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik paint.setTextSize(50); 496f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 497f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200); 498f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik canvas.restore(); 499f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik }); 500f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik 501f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 502f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik sLightGeometry, Caches::getInstance()); 503f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 504f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik 505f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik RegionClipStopsMergeTestRenderer renderer; 506f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 507f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik EXPECT_EQ(2, renderer.getIndex()); 508f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik} 509f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik 5103a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textMerging) { 511d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 512d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 513d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 514d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 515d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 516d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 517d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 518d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 519d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 520d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 521d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 52206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 52306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 524d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 525d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 526d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 527d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 528dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 529dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 530d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 5319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 5329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 535d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 536f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 537d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 538d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 539d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 5403a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStrikethrough) { 541a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 542a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 543a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 544a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 545a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 546a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 54715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 54815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 54915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 55015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 551a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 552a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 55306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 2000, 5548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 555a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 556a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 557a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 558a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setStrikeThruText(true); 55942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 560a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 561dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 562a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 563a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 5649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 5659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000, 5669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 569a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 570f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 571a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 572d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 573b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 574b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 5757c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = { 5767c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; 5777c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5783a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStyle) { 5797c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik class TextStyleTestRenderer : public TestRendererBase { 5807c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik public: 5817c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 5827c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, mIndex); 5837c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(3u, opList.count); 5847c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik mIndex += opList.count; 5857c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5867c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik int index = 0; 5877c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 5887c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto state = opList.states[index++]; 5897c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(style, state->op->paint->getStyle()) 5907c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Remainder of validation relies upon stable merged order"; 5917c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, state->computedState.clipSideFlags) 5927c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Clipped bounds validation requires unclipped ops"; 5937c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 5947c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5957c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect fill = opList.states[0]->computedState.clippedBounds; 5967c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect stroke = opList.states[1]->computedState.clippedBounds; 5977c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) 5987c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Stroke+Fill should be same as stroke"; 5997c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 6007c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_TRUE(stroke.contains(fill)); 6017c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_FALSE(fill.contains(stroke)); 6027c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 60379abbf22d4f672208327546661e694d837f564a9Derek Sollenberger // outset by half the stroke width 6047c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect outsetFill(fill); 60579abbf22d4f672208327546661e694d837f564a9Derek Sollenberger outsetFill.outset(5); 6067c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, outsetFill); 6077c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 6087c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }; 60906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 61006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 6117c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint paint; 6127c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 6137c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setAntiAlias(true); 6147c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextSize(50); 6157c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStrokeWidth(10); 6167c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 6177c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // draw 3 copies of the same text overlapping, each with a different style. 6187c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // They'll get merged, but with 6197c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 6207c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStyle(style); 621dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 6227c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 6237c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }); 6249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 6259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6277c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TextStyleTestRenderer renderer; 6287c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 6297c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; 6307c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik} 6317c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 632aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { 633aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { 634d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 635d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 636d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 637e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 638d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 639d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 640d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 641d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 642d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 643d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 644d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 645d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 646d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 647243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik SkMatrix::MakeTrans(5, 5)); 648d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 64906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 650d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 651eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 6526c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect); 653d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 654d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 655d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 6569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 6579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 6589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 661aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerClipLocalMatrixTestRenderer renderer; 662f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 663d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 664d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 665d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 666aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { 667aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { 668aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik public: 669aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 670aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(0, mIndex++); 671aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 672aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik Matrix4 expected; 673aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik expected.loadTranslate(35, 45, 0); 674aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 675aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik } 676aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }; 677aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 678aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 679aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 680aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 68106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 682aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 683aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.save(SaveFlags::MatrixClip); 684aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.translate(30, 40); 685aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 686aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.restore(); 687aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 688aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 6899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 6909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 693aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerCombineMatricesTestRenderer renderer; 694aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 695aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(1, renderer.getIndex()); 696aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 697aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 698aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { 699aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 700aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 701aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected 702aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 70306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 704aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 705aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 706aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 7079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 7089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 7109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 7119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 712aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FailRenderer renderer; 713aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 714aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 715aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 7163a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, functor_reject) { 717223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 718223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 719223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 720223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 721223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 722223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 723223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 724223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 725223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 72606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto scrolledFunctorView = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 1000000, 727223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 728223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 729cd1c3eba69d044b551cededad75474038f919890John Reck canvas.callDrawGLFunction(&noopFunctor, nullptr); 730223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 731223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 7329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7333a5811b50157e7ba50854caf957e806aee794d39Chris Craik sLightGeometry, Caches::getInstance()); 7349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(scrolledFunctorView)); 7359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 736223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 737223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 738223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 739223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 740223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 741a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikRENDERTHREAD_TEST(FrameBuilder, deferColorOp_unbounded) { 742a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik class ColorTestRenderer : public TestRendererBase { 743a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik public: 744a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 745a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(0, mIndex++); 746a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds) 747a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik << "Color op should be expanded to bounds of surrounding"; 748a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik } 749a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }; 750a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 75106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(0, 0, 10, 10, 752a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 753a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik props.setClipToBounds(false); 754260ab726486317496bc12a57d599ea96dcde3284Mike Reed canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 755a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }); 756a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 7579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 758a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik sLightGeometry, Caches::getInstance()); 7599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(unclippedColorView)); 7609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 761a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik ColorTestRenderer renderer; 762a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 763a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected"; 764a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 765a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 766a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikTEST(FrameBuilder, renderNode) { 767d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 768d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 769d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 770d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 771d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 7725430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 773d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 774d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 775d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 776d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 777d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 778d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 779d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 780d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 781d3daa3198e2212c985c634821682d5819346b653Chris Craik } 782d3daa3198e2212c985c634821682d5819346b653Chris Craik } 783d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 784d3daa3198e2212c985c634821682d5819346b653Chris Craik 78506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 7868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 787b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 788b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 789b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 790b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 791b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 79206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 793d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 794ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 795ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 796ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 797ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 798eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 799ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 800d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 801ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 802b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 803b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 8049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 8059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 8079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8085854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 809f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 810223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 811b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 812b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 8133a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clipped) { 814d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 815d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 816d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 817d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 818d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 819e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 820d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 821d3daa3198e2212c985c634821682d5819346b653Chris Craik } 822d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 823d3daa3198e2212c985c634821682d5819346b653Chris Craik 82406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 8258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 826aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(200, 200)); 827aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 0, 0, nullptr); 828ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 829ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 8309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // clip to small area, should see in receiver 8319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200, 8329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 8349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8355854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 836f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 837ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 838ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 8393a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) { 840d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 841d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 842d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 843d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 844d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 845d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 846d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 847d3daa3198e2212c985c634821682d5819346b653Chris Craik } 848d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 849d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 850d3daa3198e2212c985c634821682d5819346b653Chris Craik } 851d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 852d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 853d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 8545430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 855e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 856d3daa3198e2212c985c634821682d5819346b653Chris Craik 857d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 858d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 859d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 860d3daa3198e2212c985c634821682d5819346b653Chris Craik } 861d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 862d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 863d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 864e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 865d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 866d3daa3198e2212c985c634821682d5819346b653Chris Craik } 86774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 86874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 86974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(nullptr, offscreenBuffer); 87074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 871d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 872d3daa3198e2212c985c634821682d5819346b653Chris Craik 87306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 8748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 875eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 8766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 8776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 8786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 8799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 8819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 8839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 885f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 88674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, renderer.getIndex()); 887b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 8886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8893a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) { 890d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 891d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 892d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 893d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 894d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 895d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 896d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 897d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 898d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 899d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 900d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 901d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 902d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 903d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 904d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 905d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 906d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 907d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 908d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 909d3daa3198e2212c985c634821682d5819346b653Chris Craik } 910d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 911d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 912d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 913d3daa3198e2212c985c634821682d5819346b653Chris Craik } 91498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 915d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 916d3daa3198e2212c985c634821682d5819346b653Chris Craik } 917e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 918d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 919d3daa3198e2212c985c634821682d5819346b653Chris Craik } 920d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 921d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 922d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 9235430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 924d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 9255430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 926d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 927d3daa3198e2212c985c634821682d5819346b653Chris Craik } 928d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 929d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 930d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 931d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 9325430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 933d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 934d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 9355430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 936d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 937d3daa3198e2212c985c634821682d5819346b653Chris Craik } 93874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 93974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik const int index = mIndex++; 94074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik // order isn't important, but we need to see both 94174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik if (index == 10) { 94274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer); 94374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else if (index == 11) { 94474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer); 94574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else { ADD_FAILURE(); } 94674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 947d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 948d3daa3198e2212c985c634821682d5819346b653Chris Craik 94906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 800, 800, 9508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 951eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 9526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 9536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 954eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 9556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 9566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 9576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 9586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9596fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 9606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 9626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800, 9649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 9659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 9669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 9675854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 968f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 96974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, renderer.getIndex()); 9706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 9716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9723a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) { 97306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 9748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 975eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 9766c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); 977eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 9786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 9806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 9816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 9859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 9869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 9879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 9889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 9896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 9916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 992f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 993b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 9946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9953a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) { 996b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 997b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 998b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 999b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 1000b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 10017435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 1002b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1003b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1004b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1005b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 1006b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 1007260ab726486317496bc12a57d599ea96dcde3284Mike Reed ASSERT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint)); 1008b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1009b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1010b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 1011b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 1012b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 1013b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 1014b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1015b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1016b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1017b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 1018b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 10197435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 1020b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1021b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1022b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1023b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 102406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1025b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1026eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 1027b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 1028b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1029b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 10309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 10319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 10329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 10339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 10349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1035b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 1036f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1037b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 1038b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1039b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1040d5a90114128f4d3d528f1a0e93651496c968f940Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_round) { 1041d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik class SaveLayerUnclippedRoundTestRenderer : public TestRendererBase { 1042d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik public: 1043d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1044d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(0, mIndex++); 1045d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds) 1046d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik << "Bounds rect should round out"; 1047d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik } 1048d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {} 1049d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override {} 1050d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1051d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(1, mIndex++); 1052d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds) 1053d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik << "Bounds rect should round out"; 1054d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik } 1055d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik }; 1056d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 105706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1058d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1059d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out 1060d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 128, (SaveFlags::Flags)(0)); 1061d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 1062d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik canvas.restore(); 1063d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik }); 1064d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 1065d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 1066d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik sLightGeometry, Caches::getInstance()); 1067d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1068d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 1069d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik SaveLayerUnclippedRoundTestRenderer renderer; 1070d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1071d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(2, renderer.getIndex()); 1072d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik} 1073d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 10743a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 1075b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 1076b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1077b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1078b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1079b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 1080b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 1081b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 1082b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 1083b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 1084b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 1085b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 1086b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 1087b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 1088b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 1089b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 1090b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1091b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1092b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1093b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 1094b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 1095b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 1096b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 1097b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 1098b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 1099b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1100b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1101b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1102b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1103b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1104b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1105b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 1106b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1107b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1108b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 110906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1110b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1111b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1112eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 1113b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 1114eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 1115eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 1116eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 1117eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 1118b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 1119b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 1120b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 11219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 11229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 11239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 11249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 11259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1126b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 1127f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1128b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 1129b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 1130b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1131b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 11323a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_clearClip) { 11334876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 11344876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 11354876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 11364876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 11374876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11384876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 11394876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 11404876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 1141260ab726486317496bc12a57d599ea96dcde3284Mike Reed EXPECT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint)); 11424876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 11434876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 11444876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 11454876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 11464876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 11474876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11484876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 11494876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 11504876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11514876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 11524876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 11534876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11544876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 11554876de16e34622634266d09522c9153c78c7c2fbChris Craik 115606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 11574876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 11584876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 11594876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 11604876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 11614876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 11624876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 11634876de16e34622634266d09522c9153c78c7c2fbChris Craik 11644876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 11659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 11669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 11679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 11689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 11694876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 11704876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11714876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 11724876de16e34622634266d09522c9153c78c7c2fbChris Craik} 11734876de16e34622634266d09522c9153c78c7c2fbChris Craik 11743a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_reject) { 117506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 11764876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 11774876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 11784876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 11794876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 11804876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 11814876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 11824876de16e34622634266d09522c9153c78c7c2fbChris Craik 11834876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 11849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, 11859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 11869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 11879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 11884876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 11894876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11904876de16e34622634266d09522c9153c78c7c2fbChris Craik} 11914876de16e34622634266d09522c9153c78c7c2fbChris Craik 1192b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 1193b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 1194b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 1195b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 11963a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) { 1197b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 1198b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1199b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1200b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 1201b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 1202b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1203b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1204b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1205b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 1206b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1207b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1208b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1209b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 1210b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1211b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1212b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 1213b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 1214b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 1215b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 1216b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 1217b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1218b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1219b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1220b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 1221b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1222b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 1223b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1224b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1225b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1226b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 1227b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1228b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1229b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 123074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1231b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1232b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 1233b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 1234b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 123574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 123674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, mIndex++); 123774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer); 123874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1239b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1240b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 124106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 600, 600, // 500x500 triggers clipping 1242b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1243eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 1244eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 1245eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 1246b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 1247b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1248b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1249b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1250b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 12519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 12529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600, 12539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 12549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 12559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1256b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 1257f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 125874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, renderer.getIndex()); 1259b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1260b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1261f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 1262d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 1263d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 126498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1265d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 126698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 126798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 126898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 1269d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1270d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1271d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 12720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1273d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 1274d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 1275d3daa3198e2212c985c634821682d5819346b653Chris Craik 1276e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 1277d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 1278d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1279d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1280d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 1281d3daa3198e2212c985c634821682d5819346b653Chris Craik } 128298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1283d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 1284d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1285d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1286d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 1287d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1288e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1289d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 1290d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1291d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 12920b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 129306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 129416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 129516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 12960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 12970b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 12980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 129916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 130098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 13010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 130298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 130398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 130498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 13050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(node); 13070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 130998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 13100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 13110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 13139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 13149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 13159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 13169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 13170b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 1318f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 13190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 13200b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13210b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 132298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 13230b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 13240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1325f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 1326d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 1327d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 1328d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 1329d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 1330d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 1331d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 1332d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 1333d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1334d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1335d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 1336d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 1337d3daa3198e2212c985c634821682d5819346b653Chris Craik } 133898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1339d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1340d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 1341d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 134298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 134398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 1344d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 1345d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 134698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 134798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 1348d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1349d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1350d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1351d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1352d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 1353d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 1354d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 1355d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 1356d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 1357d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1358d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1359d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1360d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1361d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1362d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 1363d3daa3198e2212c985c634821682d5819346b653Chris Craik } 136498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1365d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 1366d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1367d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 136898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 1369d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1370d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 137198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 137298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 1373d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 1374d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1375d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 137698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 137798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 1378d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1379d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1380e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1381d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 1382d3daa3198e2212c985c634821682d5819346b653Chris Craik } 138374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 138474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, mIndex++); 138574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1386d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1387d3daa3198e2212c985c634821682d5819346b653Chris Craik 138806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150, 138916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 139016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 13910b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 13920b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 13930b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 139416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 139598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 139698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 13970b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 139906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 140016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 140116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 14020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 14030b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 14040b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 14050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1406eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 14070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 14080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 140916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 141098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 141198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 14120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 14140b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 141598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 14160b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 14170b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 14180b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 14209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 14219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 14229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 14239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 14240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1425f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 142674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(14, renderer.getIndex()); 14270b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 14290b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 14300b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 14310b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 14320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14346246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, buildLayer) { 14356246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class BuildLayerTestRenderer : public TestRendererBase { 14366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 14376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 14386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 14396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 14406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 14416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 14426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 14446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 14456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 14476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Transform should be reset within layer"; 14486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 14506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Damage rect should be used to clip layer content"; 14516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endLayer() override { 14536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, mIndex++); 14546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 14566246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 14576246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14586246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 14596246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 14606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 14626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 146306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 14646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 14656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik props.mutateLayerProperties().setType(LayerType::RenderLayer); 1466260ab726486317496bc12a57d599ea96dcde3284Mike Reed canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 14676246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 14686246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 14696246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14706246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // create RenderNode's layer here in same way prepareTree would 14716246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 14726246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = &layer; 14736246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik TestUtils::syncHierarchyPropertiesAndDisplayList(node); 14756246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14766246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // only enqueue partial damage 14776246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 14786246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 14796246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14806246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // Draw, but pass empty node list, so no work is done for primary frame 14819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(layerUpdateQueue, sLightGeometry, Caches::getInstance()); 14826246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik BuildLayerTestRenderer renderer; 14836246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 14846246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(3, renderer.getIndex()); 14856246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14866246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // clean up layer pointer, so we can safely destruct RenderNode 14876246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = nullptr; 14886246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 14896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 1490db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace { 1491db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 149206152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) { 1493161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1494814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik // order put in blue channel, transparent so overlapped content doesn't get rejected 1495814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder)); 1496161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1497161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 149806152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) { 149906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 15008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1501161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1502161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1503161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1504161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1505161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1506161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1507db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 1508db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, 1509db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::function<void(RenderProperties& props, RecordingCanvas& canvas)> setup) { 1510db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 1511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [expectedDrawOrder, setup](RenderProperties& props, RecordingCanvas& canvas) { 1512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedRect(&canvas, expectedDrawOrder); 1513db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (setup) { 1514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev setup(props, canvas); 1515d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); 1517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 1519db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 1520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievclass ZReorderTestRenderer : public TestRendererBase { 1521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievpublic: 1522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onRectOp(const RectOp& op, const BakedOpState& state) override { 1523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 1526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}; 1527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 1528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} // end anonymous namespace 1529d3daa3198e2212c985c634821682d5819346b653Chris Craik 1530db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievRENDERTHREAD_TEST(FrameBuilder, zReorder) { 153106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 15328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1533347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev canvas.insertReorderBarrier(true); 1534347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev canvas.insertReorderBarrier(false); 1535161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1536161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1537161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1538161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1539161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1540161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1541161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1542161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1543161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1544161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1545161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1546161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 154788e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op 154888e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedRect(&canvas, 11); 154988e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedNode(&canvas, 10, -1.0f); 155088e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(false); 155188e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); //test with two empty reorder sections 155288e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); 155388e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(false); 155488e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedRect(&canvas, 12); 1555161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 15569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 15579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 15589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 15599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1560161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1561f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 156288e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev EXPECT_EQ(13, renderer.getIndex()); 1563161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1564161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 15653a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionReorder) { 15668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 15678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 15688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 15698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 15708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 15718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 15728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 15738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 15748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 15758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 15768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 15778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 15788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1579678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 15808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 15818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 15828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 15838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1584678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1585678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1586678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1587678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 15888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 15898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 15908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 15918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 15928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1593678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 15948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 15958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 15968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 15978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1598678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 15998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 16008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 16018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 16028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 16038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 16048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 16058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 16068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 16078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 16088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 16098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 161006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 16118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 16128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 16138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 16148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 16158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 16168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 16178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 16188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 16198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 16208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 16218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 162206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto projectingRipple = TestUtils::createNode<RecordingCanvas>(50, 0, 100, 50, 16238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 16248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 16258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 16268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 16278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 16288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 16298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 163006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(0, 50, 100, 100, 16318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 16328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 16338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 16348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 16358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 16368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 163706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 16388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1639678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1640678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1641678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1642eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 16438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 16448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 16458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 16468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 16478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 16488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 16499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 16509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 16519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 16529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 16538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1654f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 16558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 16568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 16578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1658678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1659678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1660678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1661678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1662678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1663678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1664678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1665678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1666678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1667678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1668678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1669678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1670678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1671678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1672678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1673678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1674678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1675678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1676678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1677678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1678678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1679678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1680678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1681678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1682678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1683678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1684678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1685678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1686678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1687678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1688678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1689678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1690678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 169106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1692678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1693678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1694678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1695678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1696678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1697678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1698678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1699678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1700678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 170106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1702678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1703678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1704678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1705678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1706678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 170706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(100, 100, 300, 300, 1708678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1709678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1710678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1711678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1712678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 171306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1714678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1715678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1716678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1717678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1718678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1719678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1720678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1721678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1722678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1723678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1724678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1725678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1726678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1727678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1728678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1729678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1730678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 17319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 17329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1733678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1734678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 17359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 17369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 17379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 17389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 17399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 17409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1741678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1742678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1743678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1744678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1745678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1746678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1747678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1748678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1749a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1750a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1751a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1752a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1753a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1754a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1755a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1756a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1757a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1758a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1759a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1760a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1761a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1762a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1763a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1764a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1765a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 176606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1767a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1768a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1769a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1770a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 177106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1772a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1773a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1774a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1775a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1776a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1777a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1778a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1779a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1780a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 178106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1782a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1783a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 17846c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect); 1785a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1786a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1787a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1788a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 178906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1790a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1791a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1792a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1793a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1794a748c08241e43fc68c7c34767d819aef5183936eChris Craik 17959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 17969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 17979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 17989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1799a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1800a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1801a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1802a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1803a748c08241e43fc68c7c34767d819aef5183936eChris Craik 180498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 180598787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 180606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev return TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 18078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 180816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 180916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 181098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 181198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 181298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 181398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 181498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 181598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 18166e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1817d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1818d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1819d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1820d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 182198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 18226e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 18236e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 182498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 182598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 182698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 18276e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1828d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1829d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1830d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1831d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1832d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1833161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 183406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 18358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 183698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 183798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1838d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 183998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 18409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 18419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 18429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 18439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 184498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1845f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 184698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 184798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 184898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 18496e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 185098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 185198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 185298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 185398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 185498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 185598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 185698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 185798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 18586e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 18596e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 186098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 186198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 186298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 186398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 186498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 186598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 186698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 186798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 186898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 186998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 187074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 187174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, mIndex++); 187274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 187398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 187498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 187506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 18768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 187798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 187898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1879eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1880d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 188198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 188298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 188398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1884d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1885d3daa3198e2212c985c634821682d5819346b653Chris Craik 18869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 18873a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 18889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 18899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 189098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1891f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 189274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(6, renderer.getIndex()); 189398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1894d3daa3198e2212c985c634821682d5819346b653Chris Craik 1895f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 189698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 189798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 189898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 189998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 190098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 190198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 190298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 19036e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 19046e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 19056e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 190698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 190798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 190898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 190998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 191098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 191198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 191298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 191398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 191498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 191598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 191698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1917d3daa3198e2212c985c634821682d5819346b653Chris Craik 191806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(50, 60, 150, 160, 191916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 192016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 192198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1922eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 192398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 192498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 192598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 192616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 192798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 192898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 192998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 193098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 193198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 193298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 193398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 193498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 193598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 19369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 193798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 193898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 19399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 19409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 19413a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance()); 19429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 19439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 19449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 194598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1946f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 194798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 194898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 194998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 195098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1951d3daa3198e2212c985c634821682d5819346b653Chris Craik} 195276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 19533a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowLayering) { 195498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 195598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 195698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 195798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 195898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 195998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 196098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 196198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 196298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 196398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 196498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 196506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 19668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 196798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 196898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 196998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 197098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 19719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 19723a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 19739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 19749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 197598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1976f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 197798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 197898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 197998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1980d645640180c25c2711e99aa82ec629155f8e91baChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowClipping) { 1981d645640180c25c2711e99aa82ec629155f8e91baChris Craik class ShadowClippingTestRenderer : public TestRendererBase { 1982d645640180c25c2711e99aa82ec629155f8e91baChris Craik public: 1983d645640180c25c2711e99aa82ec629155f8e91baChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1984d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(0, mIndex++); 1985d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipState->rect) 1986d645640180c25c2711e99aa82ec629155f8e91baChris Craik << "Shadow must respect pre-barrier canvas clip value."; 1987d645640180c25c2711e99aa82ec629155f8e91baChris Craik } 1988d645640180c25c2711e99aa82ec629155f8e91baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1989d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(1, mIndex++); 1990d645640180c25c2711e99aa82ec629155f8e91baChris Craik } 1991d645640180c25c2711e99aa82ec629155f8e91baChris Craik }; 199206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 1993d645640180c25c2711e99aa82ec629155f8e91baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1994d645640180c25c2711e99aa82ec629155f8e91baChris Craik // Apply a clip before the reorder barrier/shadow casting child is drawn. 1995d645640180c25c2711e99aa82ec629155f8e91baChris Craik // This clip must be applied to the shadow cast by the child. 19966c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect); 1997d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.insertReorderBarrier(true); 1998d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1999d645640180c25c2711e99aa82ec629155f8e91baChris Craik }); 2000d645640180c25c2711e99aa82ec629155f8e91baChris Craik 20019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2002d645640180c25c2711e99aa82ec629155f8e91baChris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 20039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 20049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2005d645640180c25c2711e99aa82ec629155f8e91baChris Craik ShadowClippingTestRenderer renderer; 2006d645640180c25c2711e99aa82ec629155f8e91baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2007d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(2, renderer.getIndex()); 2008d645640180c25c2711e99aa82ec629155f8e91baChris Craik} 2009d645640180c25c2711e99aa82ec629155f8e91baChris Craik 201016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 201176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 2012d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 2013d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 2014d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh explicit PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 2015d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 2016d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2017d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 2018d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 2019d3daa3198e2212c985c634821682d5819346b653Chris Craik } 2020d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 2021d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 2022d3daa3198e2212c985c634821682d5819346b653Chris Craik 202306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 202416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 202516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 202676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 202776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 202876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 202916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 203076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, 20329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 20339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 20349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 203576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 2036f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 203776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 203876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 203976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20403a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 204176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 204276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 204376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 204476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 204576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 204676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 204776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 204876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20493a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropClipping) { 205076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 205176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 205276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 205376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 205476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 205576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 205676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 205776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 205876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20593a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropRevealClip) { 206076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 206176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 206276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 206376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 206476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 206576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 206676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 206776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 206876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 206976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20703a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOutlineClip) { 207176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 207276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 207376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 207476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 207576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 207676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 207776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 207876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 207976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 208076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 208176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20823a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropTransform) { 208376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 208476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 208576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 208676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 208776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 208876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 208976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 209076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 209176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 209276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 209376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 209476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 209576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 209676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 209776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 209876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 209976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 210076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 210176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 210276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 210376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 210476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 210576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 210676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 210776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 210876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 210976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 211076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 211176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 211276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 211376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 2114161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 21158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 21168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 21178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 21188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 21198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 2120c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck Matrix4 drawLayerMatrix; 21218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 21228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 21238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 21248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 21258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 21268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 21278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 21288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 21298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 21308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 21318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 21328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 213316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 21348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 21358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 2136d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 21378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 21388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 21408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 21418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 21428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 21438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 21448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 21458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 21468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 21478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 21498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 21508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 21518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 21528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 21538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 21548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 21558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 2156c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck mOutData->drawLayerMatrix = state.computedState.transform; 21578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 215874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 215974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 216074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 21618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 21628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 21638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 21648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 21668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 216706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000, 216816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 21698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 21708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 21718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 217216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 217316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 217416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 217516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 217616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 21778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 21789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height 21799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 21809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 21819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 21829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 21838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 2185f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 21868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 218874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 21898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 21908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21913a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 21928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 21938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 21948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 21958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 21968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 21978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 21988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 21995430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 22008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 22018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 22028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 22038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 22048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 2205c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck expected.loadTranslate(10, 0, 0); 2206c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix) 2207c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck << "expect drawLayer to be translated as part of being clipped"; 22088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 22103a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 22118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 22128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 22138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 22148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 22158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 22168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 22178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 22188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 22198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 22208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 22218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 22228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 22238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 22248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 22255430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 22268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 22278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 22293a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 22308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 22318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 22328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 22338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 22348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 22358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 22368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 22378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 22388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 22395430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 22408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 22418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 224304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris CraikRENDERTHREAD_TEST(FrameBuilder, clip_replace) { 224404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik class ClipReplaceTestRenderer : public TestRendererBase { 224504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik public: 224604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 224704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(0, mIndex++); 224804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_TRUE(op.localClip->intersectWithRoot); 224904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect) 225004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik << "Expect resolved clip to be intersection of viewport clip and clip op"; 225104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 225204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }; 225306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30, 225404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 22556c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace); 2256260ab726486317496bc12a57d599ea96dcde3284Mike Reed canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 225704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }); 225804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 22599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50, 22609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 22619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 22629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 226304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik ClipReplaceTestRenderer renderer; 226404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 226504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(1, renderer.getIndex()); 226604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 226704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 2268db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderProjectedInMiddle) { 2269db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B 2270db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2271db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2272db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2273db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2274db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2275db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2276db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2277db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2278db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { 2279db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2280db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2281db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2282db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2283db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2284db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2285db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2286db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2287db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2288db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2289db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2290db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2291db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2292db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2293db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2294db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2295db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2296db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2297db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2298db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderProjectLast) { 2299db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on E 2300db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2301db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2302db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2303db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C E 2304db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2305db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2306db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2307db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2308db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2309db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2310db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2311db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 2 2312db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2313db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2314db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2315db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2316db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 3 2317db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2318db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeE 2319db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2320db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2321db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2322db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2323db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2324db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2325db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2326db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2327db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, renderer.getIndex()); 2328db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2329db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2330db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderNoReceivable) { 2331db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected without receiver 2332db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2333db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2334db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2335db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2336db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2337db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2338db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2339db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2340db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2341db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2342db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { 2343db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //not having a projection receiver is an undefined behavior 2344db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2345db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2346db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2347db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2348db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2349db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2350db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2351db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2352db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2353db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2354db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2355db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2356db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, renderer.getIndex()); 2357db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2358db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2359db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderParentReceivable) { 2360db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on C 2361db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2362db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2363db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2364db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2365db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2366db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2367db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2368db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2369db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2370db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2371db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2372db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2373db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2374db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2375db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2376db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2377db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2378db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2379db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2380db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2381db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2382db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2383db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2384db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2385db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2386db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2387db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2388db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderSameNodeReceivable) { 2389db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2390db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2391db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2392db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2393db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { 2394db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //having a node that is projected on itself is an undefined/unexpected behavior 2395db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2396db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2397db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2398db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2399db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2400db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2401db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2402db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2403db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2404db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2405db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2406db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2407db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2408db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, renderer.getIndex()); 2409db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2410db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2411db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderProjectedSibling) { 2412db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a 2413db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical 2414db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling 2415db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B. R is not expected to be drawn (see Sibling2 outcome below), 2416db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev but for some reason it is drawn. 2417db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2418db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /|\ 2419db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2420db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C R 2421db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2422db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2423db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2424db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { 2425db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2426db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2427db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2428db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2429db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2430db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2431db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2432db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2433db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2434db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2435db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2436db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2437db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2438db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2439db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2440db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2441db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2442db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2443db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2444db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderProjectedSibling2) { 2445db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed. 2446db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2447db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2448db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G 2449db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /|\ 2450db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2451db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C R 2452db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2453db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2454db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2455db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2456db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2457db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2458db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2459db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2460db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2461db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2462db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2463db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2464db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2465db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2466db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2467db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2468db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2469db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2470db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2471db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2472db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2473db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2474db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2475db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2476db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2477db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderGrandparentReceivable) { 2478db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B 2479db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2480db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2481db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B 2482db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2483db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev C 2484db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2485db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2486db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2487db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2488db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2489db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { 2490db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2491db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2492db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2493db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2494db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2495db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2496db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2497db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2498db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2499db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2500db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2501db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2502db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2503db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2504db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2505db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2506db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2507db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2508db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2509db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderTwoReceivables) { 2510db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, R is backward projected 2511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2513db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2515db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G R 2516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2519db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2529db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2530db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2531db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2532db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2533db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2534db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2535db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2536db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2537db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2538db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2539db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, renderer.getIndex()); 2540db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2541db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2542db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) { 2543db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, G is backward projected 2544db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2545db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2546db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2548db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G R 2549db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2550db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2551db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2552db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2553db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2554db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2555db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2556db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2557db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2558db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2559db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2560db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2561db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2562db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2563db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2564db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2565db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2566db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2567db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2568db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2569db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2570db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2571db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2572db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, renderer.getIndex()); 2573db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2574db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2575db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan IlievTEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) { 2576db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, R is backward projected 2577db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2578db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2579db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2580db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2581db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G D 2582db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2583db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2584db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2585db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2586db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2587db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2588db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2589db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2590db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2591db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2592db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2593db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2594db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { //D 2595db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2596db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2597db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2598db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2599db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeD 2600db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2601db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2602db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2603db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2604db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2605db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2606db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2607db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2608db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2609db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(5, renderer.getIndex()); 2610db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2611db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 26126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 26136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 2614