FrameBuilderTests.cpp revision aafb01d8ade0def3f51b74ae3bbc610c4ab33044
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 328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikconst LayerUpdateQueue sEmptyLayerUpdateQueue; 336e068c0182f6f85bccb855a647510724d1c65a13Chris Craikconst FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 346e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 44d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 475854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 495854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 50d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 51a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer creation not expected in this test"; 52a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 53a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 55a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 56a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 57a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 58a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 59a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 6098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 61e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 625854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 65a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 66a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 67a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 687cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 6915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 767cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 885854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 935854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 967cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 9715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 9815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1047cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1085854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1103a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simple) { 111d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 112d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 114d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 115d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 116d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 117d3daa3198e2212c985c634821682d5819346b653Chris Craik } 118d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 119d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 120d3daa3198e2212c985c634821682d5819346b653Chris Craik } 121d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 122d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 123d3daa3198e2212c985c634821682d5819346b653Chris Craik } 124e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 125d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 126d3daa3198e2212c985c634821682d5819346b653Chris Craik } 127d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 128d3daa3198e2212c985c634821682d5819346b653Chris Craik 1298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 1308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 131ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(25, 25); 132b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 10, 10, nullptr); 134b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 135f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1363a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 1375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleTestRenderer renderer; 138f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end 1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 1416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1423a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleStroke) { 143386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik class SimpleStrokeTestRenderer : public TestRendererBase { 144386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik public: 145386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik void onPointsOp(const PointsOp& op, const BakedOpState& state) override { 146386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(0, mIndex++); 147386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // even though initial bounds are empty... 148386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_TRUE(op.unmappedBounds.isEmpty()) 149386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "initial bounds should be empty, since they're unstroked"; 150386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(Rect(45, 45, 55, 55), state.computedState.clippedBounds) 151386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "final bounds should account for stroke"; 152386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 153386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }; 154386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 155386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 156386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 157386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPaint strokedPaint; 158386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik strokedPaint.setStrokeWidth(10); 159386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik canvas.drawPoint(50, 50, strokedPaint); 160386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }); 161f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1623a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 163386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 164f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 165386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 166386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 167386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 1683a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleRejection) { 1698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 171eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 1726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty 1736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 1756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 176f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 1773a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 180f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1833a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleBatching) { 184a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 185d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 186d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 187d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 188a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 189d3daa3198e2212c985c634821682d5819346b653Chris Craik } 190d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 191a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 192d3daa3198e2212c985c634821682d5819346b653Chris Craik } 193d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 194d3daa3198e2212c985c634821682d5819346b653Chris Craik 1958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 19715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(10, 10, 19815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik kAlpha_8_SkColorType); // Disable merging by using alpha 8 bitmap 199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 202eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 203a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 5, 0, nullptr); 207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 211f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 2123a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 2135854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 214f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 215a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 21615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 217a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 218a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 2193a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clippedMerging) { 22093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 22193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 22293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 22393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 22493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 22593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 22693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 22793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 22893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 22993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 23093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 23193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik auto node = TestUtils::createNode(0, 0, 100, 100, 23293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik [](RenderProperties& props, TestCanvas& canvas) { 23393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik SkBitmap bitmap = TestUtils::createSkBitmap(20, 20); 23493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 23593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 23693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op); 23793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 0, 40, nullptr); 23893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 23993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 24093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op); 24193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 0, nullptr); 24293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 24393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 24493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op); 24593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 80, 40, nullptr); 24693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 24793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 24893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op); 24993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 70, nullptr); 25093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 25193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 252f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 2533a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 25493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 255f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 25693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 25793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 25893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 2593a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textMerging) { 260d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 261d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 262d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 263d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 264d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 265d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 266d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 267d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 268d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 269d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 270d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 271d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 272d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik [](RenderProperties& props, TestCanvas& canvas) { 273d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 274d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 275d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 276d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 277dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 278dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 279d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 280f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 2813a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 282d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 283f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 284d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 285d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 286d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 2873a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStrikethrough) { 288a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 289a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 290a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 291a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 292a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 293a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 29415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 29515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 29615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 29715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 298a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 299a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 3008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 2000, 3018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 302a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 303a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 304a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 305a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setStrikeThruText(true); 30642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 307a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 308dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 309a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 310a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 311f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, 3123a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 313a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 314f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 315a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 316d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 318b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 3197c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = { 3207c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; 3217c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3223a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStyle) { 3237c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik class TextStyleTestRenderer : public TestRendererBase { 3247c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik public: 3257c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 3267c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, mIndex); 3277c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(3u, opList.count); 3287c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik mIndex += opList.count; 3297c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3307c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik int index = 0; 3317c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 3327c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto state = opList.states[index++]; 3337c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(style, state->op->paint->getStyle()) 3347c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Remainder of validation relies upon stable merged order"; 3357c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, state->computedState.clipSideFlags) 3367c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Clipped bounds validation requires unclipped ops"; 3377c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 3387c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3397c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect fill = opList.states[0]->computedState.clippedBounds; 3407c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect stroke = opList.states[1]->computedState.clippedBounds; 3417c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) 3427c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Stroke+Fill should be same as stroke"; 3437c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3447c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_TRUE(stroke.contains(fill)); 3457c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_FALSE(fill.contains(stroke)); 3467c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 34779abbf22d4f672208327546661e694d837f564a9Derek Sollenberger // outset by half the stroke width 3487c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect outsetFill(fill); 34979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger outsetFill.outset(5); 3507c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, outsetFill); 3517c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 3527c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }; 3537c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 3547c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik [](RenderProperties& props, TestCanvas& canvas) { 3557c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint paint; 3567c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 3577c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setAntiAlias(true); 3587c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextSize(50); 3597c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStrokeWidth(10); 3607c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3617c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // draw 3 copies of the same text overlapping, each with a different style. 3627c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // They'll get merged, but with 3637c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 3647c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStyle(style); 365dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 3667c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 3677c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }); 3687c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 3693a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 3707c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TextStyleTestRenderer renderer; 3717c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3727c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; 3737c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik} 3747c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 375aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { 376aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { 377d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 378d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 379d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 380e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 381d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 382d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 383d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 384d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 385d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 386d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 387d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 388d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 389d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 390243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik SkMatrix::MakeTrans(5, 5)); 391d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 392d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 393d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 394eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 395d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 396d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 397d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 398d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 399f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4003a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 401aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerClipLocalMatrixTestRenderer renderer; 402f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 403d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 404d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 405d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 406aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { 407aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { 408aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik public: 409aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 410aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(0, mIndex++); 411aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 412aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik Matrix4 expected; 413aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik expected.loadTranslate(35, 45, 0); 414aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 415aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik } 416aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }; 417aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 418aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 419aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 420aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 421aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 422aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 423aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.save(SaveFlags::MatrixClip); 424aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.translate(30, 40); 425aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 426aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.restore(); 427aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 428aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 429aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 430aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 431aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerCombineMatricesTestRenderer renderer; 432aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 433aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(1, renderer.getIndex()); 434aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 435aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 436aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { 437aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 438aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 439aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected 440aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 441aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 442aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 443aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 444aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 445aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 446aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 447aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FailRenderer renderer; 448aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 449aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 450aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 4513a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, functor_reject) { 452223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 453223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 454223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 455223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 456223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 457223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 458223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 459223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 460223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 461223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000, 462223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 463223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 464223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.callDrawGLFunction(&noopFunctor); 465223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 466223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 467223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4683a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(scrolledFunctorView), 4693a5811b50157e7ba50854caf957e806aee794d39Chris Craik sLightGeometry, Caches::getInstance()); 470223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 471223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 472223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 473223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 474223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 475a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikRENDERTHREAD_TEST(FrameBuilder, deferColorOp_unbounded) { 476a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik class ColorTestRenderer : public TestRendererBase { 477a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik public: 478a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 479a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(0, mIndex++); 480a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds) 481a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik << "Color op should be expanded to bounds of surrounding"; 482a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik } 483a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }; 484a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 485a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik auto unclippedColorView = TestUtils::createNode(0, 0, 10, 10, 486a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 487a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik props.setClipToBounds(false); 488a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 489a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }); 490a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 491a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 492a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik TestUtils::createSyncedNodeList(unclippedColorView), 493a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik sLightGeometry, Caches::getInstance()); 494a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik ColorTestRenderer renderer; 495a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 496a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected"; 497a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 498a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 499a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikTEST(FrameBuilder, renderNode) { 500d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 501d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 502d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 503d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 504d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 5055430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 506d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 507d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 508d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 509d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 510d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 511d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 512d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 513d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 514d3daa3198e2212c985c634821682d5819346b653Chris Craik } 515d3daa3198e2212c985c634821682d5819346b653Chris Craik } 516d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 517d3daa3198e2212c985c634821682d5819346b653Chris Craik 5188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 5198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 520b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 521b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 522b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 523b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 524b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 5258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 526d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 527ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 528ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 529ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 530ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 531eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 532ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 533d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 534ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 535b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 536b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 537f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5383a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 5395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 540f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 541223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 542b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 543b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 5443a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clipped) { 545d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 546d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 547d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 548d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 549d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 550e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 551d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 552d3daa3198e2212c985c634821682d5819346b653Chris Craik } 553d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 554d3daa3198e2212c985c634821682d5819346b653Chris Craik 5558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 5568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 557ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 558ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 559ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 560ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 561f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, 5620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver 5633a5811b50157e7ba50854caf957e806aee794d39Chris Craik 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 5645854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 565f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 566ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 567ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 5683a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) { 569d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 570d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 571d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 572d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 573d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 574d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 575d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 576d3daa3198e2212c985c634821682d5819346b653Chris Craik } 577d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 578d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 579d3daa3198e2212c985c634821682d5819346b653Chris Craik } 580d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 581d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 582d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 5835430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 584e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 585d3daa3198e2212c985c634821682d5819346b653Chris Craik 586d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 587d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 588d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 589d3daa3198e2212c985c634821682d5819346b653Chris Craik } 590d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 591d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 592d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 593e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 594d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 595d3daa3198e2212c985c634821682d5819346b653Chris Craik } 596d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 597d3daa3198e2212c985c634821682d5819346b653Chris Craik 5988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 5998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 600eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 6016fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 6026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 604f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6053a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 6065854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 607f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 6085854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); 609b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 6106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6113a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) { 612d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 613d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 614d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 615d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 616d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 617d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 618d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 619d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 620d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 621d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 622d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 623d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 624d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 625d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 626d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 627d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 628d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 629d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 630d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 631d3daa3198e2212c985c634821682d5819346b653Chris Craik } 632d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 633d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 634d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 635d3daa3198e2212c985c634821682d5819346b653Chris Craik } 63698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 637d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 638d3daa3198e2212c985c634821682d5819346b653Chris Craik } 639e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 640d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 641d3daa3198e2212c985c634821682d5819346b653Chris Craik } 642d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 643d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 644d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 6455430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 646d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 6475430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 648d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 649d3daa3198e2212c985c634821682d5819346b653Chris Craik } 650d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 651d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 652d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 653d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 6545430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 655d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 656d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 6575430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 658d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 659d3daa3198e2212c985c634821682d5819346b653Chris Craik } 660d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 661d3daa3198e2212c985c634821682d5819346b653Chris Craik 6628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 6638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 664eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 6656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 6666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 667eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 6686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 6696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 6706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 6716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 6736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 6756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 676f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, 6773a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 6785854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 679f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 6805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(10, renderer.getIndex()); 6816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 6826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6833a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) { 6848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 6858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 686eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 6876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 688eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 6896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6906fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 6916fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 6926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6936fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 696f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6973a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 6986fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6995854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 7006fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 701f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 702b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 7036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 7043a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) { 705b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 706b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 707b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 708b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 709b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 7107435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 711b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 712b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 713b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 714b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 715b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 716b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 717b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 718b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 719b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 720b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 721b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 722b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 723b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 724b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 725b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 726b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 727b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 7287435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 729b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 730b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 731b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 732b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 733b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 734b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 735eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 736b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 737b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 738b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 739f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 7403a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 741b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 742f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 743b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 744b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 745b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 7463a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 747b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 748b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 749b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 750b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 751b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 752b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 753b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 754b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 755b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 756b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 757b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 758b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 759b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 760b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 761b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 762b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 763b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 764b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 765b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 766b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 767b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 768b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 769b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 770b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 771b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 772b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 773b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 774b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 775b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 776b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 777b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 778b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 779b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 780b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 781b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 782b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 783b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 784eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 785b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 786eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 787eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 788eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 789eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 790b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 791b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 792b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 793f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 7943a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 795b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 796f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 797b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 798b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 799b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 800b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 8013a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_clearClip) { 8024876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 8034876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 8044876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 8054876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 8064876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8074876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 8084876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 8094876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 8104876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 8114876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 8124876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 8134876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 8144876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 8154876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 8164876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8174876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 8184876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 8194876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8204876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 8214876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 8224876de16e34622634266d09522c9153c78c7c2fbChris Craik } 8234876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 8244876de16e34622634266d09522c9153c78c7c2fbChris Craik 8254876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 8264876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 8274876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 8284876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 8294876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 8304876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 8314876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 8324876de16e34622634266d09522c9153c78c7c2fbChris Craik 8334876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 8344876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 8353a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 8364876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 8374876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 8384876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 8394876de16e34622634266d09522c9153c78c7c2fbChris Craik} 8404876de16e34622634266d09522c9153c78c7c2fbChris Craik 8413a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_reject) { 8424876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 8434876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 8444876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 8454876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 8464876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 8474876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 8484876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 8494876de16e34622634266d09522c9153c78c7c2fbChris Craik 8504876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 8514876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 8523a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 8534876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 8544876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 8554876de16e34622634266d09522c9153c78c7c2fbChris Craik} 8564876de16e34622634266d09522c9153c78c7c2fbChris Craik 857b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 858b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 859b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 860b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 8613a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) { 862b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 863b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 864b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 865b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 866b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 867b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 868b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 869b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 870b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 871b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 872b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 873b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 874b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 875b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 876b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 877b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 878b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 879b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 880b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 881b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 882b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 883b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 884b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 885b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 886b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 887b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 888b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 889b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 890b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 891b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 892b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 893b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 894b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 895b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 896b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 897b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 898b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 899b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 900b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 901b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 902b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 903eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 904eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 905eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 906b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 907b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 908b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 909b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 910b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 911f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, 9123a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 913b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 914f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 915b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(12, renderer.getIndex()); 916b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 917b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 918f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 919d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 920d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 92198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 922d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 92398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 92498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 92598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 926d3daa3198e2212c985c634821682d5819346b653Chris Craik } 927d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 928d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 9290b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 930d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 931d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 932d3daa3198e2212c985c634821682d5819346b653Chris Craik 933e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 934d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 935d3daa3198e2212c985c634821682d5819346b653Chris Craik } 936d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 937d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 938d3daa3198e2212c985c634821682d5819346b653Chris Craik } 93998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 940d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 941d3daa3198e2212c985c634821682d5819346b653Chris Craik } 942d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 943d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 944d3daa3198e2212c985c634821682d5819346b653Chris Craik } 945e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 946d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 947d3daa3198e2212c985c634821682d5819346b653Chris Craik } 948d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 9490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 95116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 95216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 9550b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 95616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 95798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 9580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 95998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 96098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 96198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 9620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9637db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedNodeList = TestUtils::createSyncedNodeList(node); 9640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9650b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 96698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 9670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 9680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 969f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 9703a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedNodeList, sLightGeometry, Caches::getInstance()); 9710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 972f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 9730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 9740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 97698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 9770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 9780b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 979f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 980d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 981d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 982d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 983d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 984d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 985d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 986d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 987d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 988d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 989d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 990d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 991d3daa3198e2212c985c634821682d5819346b653Chris Craik } 99298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 993d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 994d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 995d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 99698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 99798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 998d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 999d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 100098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 100198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 1002d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1003d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1004d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1005d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1006d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 1007d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 1008d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 1009d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 1010d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 1011d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1012d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1013d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1014d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1015d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1016d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 1017d3daa3198e2212c985c634821682d5819346b653Chris Craik } 101898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1019d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 1020d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1021d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 102298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 1023d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1024d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 102598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 102698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 1027d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 1028d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1029d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 103098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 103198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 1032d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1033d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1034e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1035d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 1036d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1037d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1038d3daa3198e2212c985c634821682d5819346b653Chris Craik 103916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 104016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 104116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 10420b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 10430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 10440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 104516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 104698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 104798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 10480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 10490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 105016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 105116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 105216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 10530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 10540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 10550b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 10560b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1057eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 10580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 10590b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 106016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 106198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 106298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 10630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 10647db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 10650b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 106698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 10670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 10680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 10690b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1070f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 10713a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedList, sLightGeometry, Caches::getInstance()); 10720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1073f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 10740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(13, renderer.getIndex()); 10750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 10760b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 10770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 10780b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 10790b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 10800b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1081161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 1082161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1083161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 1084161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1085161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1086161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 108716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 10888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1089161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1090161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1091161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1092161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1093161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1094161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 10953a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, zReorder) { 1096d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 1097d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1098d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1099d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1100d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1101d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1102d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1103d3daa3198e2212c985c634821682d5819346b653Chris Craik 110416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 11058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1106161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1107161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1108161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1109161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1110161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1111161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1112161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1113161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1114161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1115161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1116161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1117161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 1118161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1119f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 11203a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 1121161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1122f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1123161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 1124161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1125161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 11263a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionReorder) { 11278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 11288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 11298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 11308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 11318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 11328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 11338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 11348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 11358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 11368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 11378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 11388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 11398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1140678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 11418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 11428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 11438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 11448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1145678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1146678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1147678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1148678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 11498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 11508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 11518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 11528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 11538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1154678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 11558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 11568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 11578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 11588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1159678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 11608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 11618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 11628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 11638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 11648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 11658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 11668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 11678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 11688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 11698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 11708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 11718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 11728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 11738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 11748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 11758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 11768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 11778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 11788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 11798d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 11818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 11828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 11848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 11858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 11868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 11878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 11898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 11908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 11928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 11938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 11958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 11968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 11978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 11998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1200678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1201678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1202678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1203eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 12048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 12058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 12068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 12078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 12088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 12098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1210f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 12113a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 12128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1213f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 12148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 12158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 12168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1217678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1218678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1219678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1220678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1221678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1222678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1223678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1224678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1225678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1226678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1227678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1228678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1229678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1230678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1231678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1232678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1233678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1234678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1235678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1236678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1237678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1238678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1239678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1240678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1241678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1242678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1243678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1244678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1245678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1246678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1247678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1248678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1249678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 1250678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1251678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1252678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1253678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1254678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1255678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1256678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1257678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1258678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1259678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1260678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1261678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1262678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1263678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1264678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1265678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1266678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto child = TestUtils::createNode(100, 100, 300, 300, 1267678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1268678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1269678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1270678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1271678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1272678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1273678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1274678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1275678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1276678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1277678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1278678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1279678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1280678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1281678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1282678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1283678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1284678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1285678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1286678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1287678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1288678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1289678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1290678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto syncedList = TestUtils::createSyncedNodeList(parent); 1291678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1292678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 1293678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 12943a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedList, sLightGeometry, Caches::getInstance()); 1295678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1296678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1297678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1298678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1299678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1300678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1301678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1302678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1303a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1304a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1305a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1306a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1307a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1308a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1309a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1310a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1311a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1312a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1313a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1314a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1315a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1316a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1317a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1318a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1319a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 1320a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1321a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1322a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1323a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1324a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1325a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1326a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1327a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1328a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1329a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1330a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1331a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1332a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1333a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1334a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1335a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto child = TestUtils::createNode(0, 0, 400, 400, 1336a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1337a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 1338a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op); 1339a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1340a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1341a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1342a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1343a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1344a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1345a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1346a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1347a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1348a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1349a748c08241e43fc68c7c34767d819aef5183936eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 13503a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 1351a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1352a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1353a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1354a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1355a748c08241e43fc68c7c34767d819aef5183936eChris Craik 135698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 135798787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 135816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 13598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 136016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 136116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 136298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 136398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 136498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 136598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 136698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 136798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13686e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1369d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1370d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1371d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1372d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 137398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 13746e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 13756e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 137698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 137798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 137898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 13796e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1380d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1381d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1382d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1383d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1384d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1385161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 13868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 13878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 138898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 138998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1390d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 139198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1392f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13933a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 139498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1395f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 139698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 139798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 139898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13996e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 140098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 140198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 140298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 140398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 140498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 140598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 140698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 140798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 14086e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 14096e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 141098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 141198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 141298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 141398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 141498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 141598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 141698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 141798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 141898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 141998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 142098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 142198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 14228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 14238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 142498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 142598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1426eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1427d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 142898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 142998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 143098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1431d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1432d3daa3198e2212c985c634821682d5819346b653Chris Craik 1433f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 14346e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 14353a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 143698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1437f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 143898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 143998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1440d3daa3198e2212c985c634821682d5819346b653Chris Craik 1441f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 144298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 144398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 144498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 144598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 144698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 144798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 144898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 14496e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 14506e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 14516e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 145298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 145398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 145498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 145598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 145698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 145798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 145898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 145998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 146098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 146198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 146298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1463d3daa3198e2212c985c634821682d5819346b653Chris Craik 14648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 146516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 146616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 146798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1468eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 146998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 147098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 147198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 147216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 147398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 147498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 147598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 147698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 147798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 147898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 147998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 148098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 148198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 14827db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 148398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 148498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 1485f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 14866e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, 14873a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance()); 148898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1489f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 149098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 149198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 149298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 149398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1494d3daa3198e2212c985c634821682d5819346b653Chris Craik} 149576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 14963a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowLayering) { 149798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 149898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 149998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 150098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 150198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 150298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 150398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 150498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 150598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 150698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 150798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 15088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 15098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 151098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 151198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 151298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 151398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 151498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1515f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 15166e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 15173a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 151898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1519f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 152098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 152198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 152298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 152316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 152476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1525d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1526d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1527d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1528d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1529d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1530d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1531d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1532d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1533d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1534d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1535d3daa3198e2212c985c634821682d5819346b653Chris Craik 153616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 153716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 153816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 153976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 154076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 154176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 154216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 154376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1544f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 15453a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 154676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1547f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 154876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 154976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 155076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15513a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 155276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 155376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 155476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 155576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 155676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 155776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 155876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 155976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15603a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropClipping) { 156176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 156276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 156376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 156476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 156576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 156676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 156776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 156876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 156976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15703a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropRevealClip) { 157176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 157276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 157376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 157476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 157576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 157676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 157776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 157876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 157976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 158076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15813a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOutlineClip) { 158276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 158376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 158476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 158576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 158676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 158776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 158876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 158976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 159076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 159176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 159276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15933a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropTransform) { 159476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 159576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 159676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 159776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 159876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 159976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 160076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 160176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 160276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 160376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 160476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 160576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 160676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 160776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 160876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 160976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 161076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 161176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 161276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 161376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 161476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 161576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 161676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 161776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 161876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 161976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 162076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 162176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 162276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 162376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 162476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 1625161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 16268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 16278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 16288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 16298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 16308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 16318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 16328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 16338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 16348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 16358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 16368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 16378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 16388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 16398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 16408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 16418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 16428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 164316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 16448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 16458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 16468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 16478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 16488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 16508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 16518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 16528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 16538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 16548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 16558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 16568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 16578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 16598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 16608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 16618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 16628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 16638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 16648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 16658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 16668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 16678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 16688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 16698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 16708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 16728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 167316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 167416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 16758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 16768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 16778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 167816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 167916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 168016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 168116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 168216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 16838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16847db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height 16858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16866e068c0182f6f85bccb855a647510724d1c65a13Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 16873a5811b50157e7ba50854caf957e806aee794d39Chris Craik nodes, sLightGeometry, Caches::getInstance()); 16888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 1689f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 16908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 16928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 16938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16953a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 16968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 16998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 17008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 17018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 17028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 17035430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 17048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 17058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 17068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 17078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 17088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 17098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 17108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 17113a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 17128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 17138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 17148ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 17158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 17168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 17178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 17188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 17198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 17208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 17218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 17228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 17238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 17248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 17258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 17265430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 17278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 17288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 17298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 17303a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 17318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 17328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 17338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 17348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 17358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 17368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 17378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 17388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 17398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 17405430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 17418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 17428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 17438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 17446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 17456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 1746