FrameBuilderTests.cpp revision 79abbf22d4f672208327546661e694d837f564a9
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 375f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer) { 376d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik class TextureLayerTestRenderer : 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, 390d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [](Matrix4* transform) { 391d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik transform->loadTranslate(5, 5, 0); 392d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 393d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 394d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 395d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 396eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 397d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 398d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 399d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 400d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 401f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4023a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 403d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik TextureLayerTestRenderer renderer; 404f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 405d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 406d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 407d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 4083a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, functor_reject) { 409223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 410223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 411223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 412223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 413223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 414223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 415223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 416223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 417223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 418223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000, 419223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 420223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 421223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.callDrawGLFunction(&noopFunctor); 422223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 423223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 424223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4253a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(scrolledFunctorView), 4263a5811b50157e7ba50854caf957e806aee794d39Chris Craik sLightGeometry, Caches::getInstance()); 427223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 428223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 429223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 430223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 431223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 4323a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderNode) { 433d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 434d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 435d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 436d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 437d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 4385430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 439d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 440d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 441d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 442d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 443d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 444d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 445d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 446d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 447d3daa3198e2212c985c634821682d5819346b653Chris Craik } 448d3daa3198e2212c985c634821682d5819346b653Chris Craik } 449d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 450d3daa3198e2212c985c634821682d5819346b653Chris Craik 4518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 4528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 456b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 457b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 459d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 460ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 461ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 462ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 463ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 464eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 465ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 466d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 467ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 468b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 469b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 470f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4713a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 4725854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 473f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 474223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 475b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 476b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4773a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clipped) { 478d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 479d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 480d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 481d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 482d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 483e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 484d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 485d3daa3198e2212c985c634821682d5819346b653Chris Craik } 486d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 487d3daa3198e2212c985c634821682d5819346b653Chris Craik 4888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 4898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 490ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 491ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 492ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 493ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 494f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, 4950b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver 4963a5811b50157e7ba50854caf957e806aee794d39Chris Craik 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 4975854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 498f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 499ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 500ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 5013a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) { 502d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 503d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 504d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 505d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 506d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 507d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 508d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 509d3daa3198e2212c985c634821682d5819346b653Chris Craik } 510d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 511d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 512d3daa3198e2212c985c634821682d5819346b653Chris Craik } 513d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 514d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 515d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 5165430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 517e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 518d3daa3198e2212c985c634821682d5819346b653Chris Craik 519d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 520d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 521d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 522d3daa3198e2212c985c634821682d5819346b653Chris Craik } 523d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 524d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 525d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 526e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 527d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 528d3daa3198e2212c985c634821682d5819346b653Chris Craik } 529d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 530d3daa3198e2212c985c634821682d5819346b653Chris Craik 5318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 5328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 533eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 5346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 5356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 537f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5383a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 5395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 540f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 5415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); 542b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 5436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5443a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) { 545d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 546d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 547d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 548d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 549d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 550d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 551d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 552d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 553d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 554d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 555d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 556d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 557d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 558d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 559d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 560d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 561d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 562d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 563d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 564d3daa3198e2212c985c634821682d5819346b653Chris Craik } 565d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 566d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 567d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 568d3daa3198e2212c985c634821682d5819346b653Chris Craik } 56998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 570d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 571d3daa3198e2212c985c634821682d5819346b653Chris Craik } 572e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 573d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 574d3daa3198e2212c985c634821682d5819346b653Chris Craik } 575d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 576d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 577d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 5785430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 579d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 5805430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 581d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 582d3daa3198e2212c985c634821682d5819346b653Chris Craik } 583d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 584d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 585d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 586d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 5875430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 588d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 589d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 5905430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 591d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 592d3daa3198e2212c985c634821682d5819346b653Chris Craik } 593d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 594d3daa3198e2212c985c634821682d5819346b653Chris Craik 5958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 5968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 597eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 5986fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 5996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 600eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 6016fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 6026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 6036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 6046fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 6066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 6086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 609f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, 6103a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 6115854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 612f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 6135854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(10, renderer.getIndex()); 6146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 6156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6163a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) { 6178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 6188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 619eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 6206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 621eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 6226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 6246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 6256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 629f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6303a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 6316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6325854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 6336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 634f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 635b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 6366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6373a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) { 638b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 639b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 640b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 641b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 642b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 6437435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 644b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 645b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 646b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 647b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 648b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 649b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 650b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 651b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 652b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 653b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 654b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 655b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 656b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 657b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 658b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 659b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 660b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 6617435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 662b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 663b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 664b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 665b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 666b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 667b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 668eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 669b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 670b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 671b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 672f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6733a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 674b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 675f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 676b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 677b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 678b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 6793a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 680b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 681b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 682b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 683b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 684b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 685b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 686b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 687b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 688b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 689b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 690b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 691b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 692b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 693b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 694b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 695b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 696b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 697b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 698b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 699b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 700b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 701b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 702b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 703b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 704b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 705b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 706b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 707b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 708b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 709b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 710b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 711b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 712b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 713b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 714b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 715b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 716b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 717eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 718b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 719eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 720eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 721eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 722eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 723b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 724b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 725b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 726f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 7273a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 728b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 729f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 730b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 731b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 732b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 733b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 7343a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_clearClip) { 7354876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 7364876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 7374876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 7384876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 7394876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7404876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 7414876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 7424876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 7434876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 7444876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 7454876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 7464876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 7474876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 7484876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 7494876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7504876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 7514876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 7524876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7534876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 7544876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 7554876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7564876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 7574876de16e34622634266d09522c9153c78c7c2fbChris Craik 7584876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7594876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 7604876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 7614876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 7624876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 7634876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 7644876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 7654876de16e34622634266d09522c9153c78c7c2fbChris Craik 7664876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 7674876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 7683a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 7694876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 7704876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7714876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 7724876de16e34622634266d09522c9153c78c7c2fbChris Craik} 7734876de16e34622634266d09522c9153c78c7c2fbChris Craik 7743a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_reject) { 7754876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7764876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 7774876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 7784876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 7794876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 7804876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 7814876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 7824876de16e34622634266d09522c9153c78c7c2fbChris Craik 7834876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 7844876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 7853a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 7864876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 7874876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7884876de16e34622634266d09522c9153c78c7c2fbChris Craik} 7894876de16e34622634266d09522c9153c78c7c2fbChris Craik 790b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 791b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 792b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 793b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 7943a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) { 795b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 796b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 797b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 798b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 799b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 800b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 801b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 802b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 803b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 804b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 805b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 806b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 807b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 808b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 809b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 810b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 811b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 812b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 813b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 814b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 815b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 816b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 817b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 818b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 819b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 820b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 821b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 822b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 823b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 824b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 825b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 826b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 827b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 828b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 829b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 830b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 831b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 832b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 833b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 834b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 835b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 836eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 837eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 838eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 839b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 840b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 841b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 842b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 843b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 844f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, 8453a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 846b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 847f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 848b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(12, renderer.getIndex()); 849b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 850b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 851f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 852d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 853d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 85498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 855d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 85698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 85798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 85898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 859d3daa3198e2212c985c634821682d5819346b653Chris Craik } 860d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 861d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 8620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 863d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 864d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 865d3daa3198e2212c985c634821682d5819346b653Chris Craik 866e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 867d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 868d3daa3198e2212c985c634821682d5819346b653Chris Craik } 869d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 870d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 871d3daa3198e2212c985c634821682d5819346b653Chris Craik } 87298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 873d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 874d3daa3198e2212c985c634821682d5819346b653Chris Craik } 875d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 876d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 877d3daa3198e2212c985c634821682d5819346b653Chris Craik } 878e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 879d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 880d3daa3198e2212c985c634821682d5819346b653Chris Craik } 881d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 8820b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 88416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 88516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 8860b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 8870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 8880b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 88916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 89098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 8910b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 89298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 89398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 89498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 8950b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8967db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedNodeList = TestUtils::createSyncedNodeList(node); 8970b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 89998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 9000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 9010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 902f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 9033a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedNodeList, sLightGeometry, Caches::getInstance()); 9040b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 905f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 9060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 9070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 90998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 9100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 9110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 912f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 913d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 914d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 915d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 916d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 917d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 918d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 919d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 920d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 921d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 922d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 923d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 924d3daa3198e2212c985c634821682d5819346b653Chris Craik } 92598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 926d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 927d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 928d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 92998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 93098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 931d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 932d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 93398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 93498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 935d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 936d3daa3198e2212c985c634821682d5819346b653Chris Craik } 937d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 938d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 939d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 940d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 941d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 942d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 943d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 944d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 945d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 946d3daa3198e2212c985c634821682d5819346b653Chris Craik } 947d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 948d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 949d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 950d3daa3198e2212c985c634821682d5819346b653Chris Craik } 95198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 952d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 953d3daa3198e2212c985c634821682d5819346b653Chris Craik } 954d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 95598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 956d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 957d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 95898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 95998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 960d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 961d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 962d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 96398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 96498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 965d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 966d3daa3198e2212c985c634821682d5819346b653Chris Craik } 967e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 968d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 969d3daa3198e2212c985c634821682d5819346b653Chris Craik } 970d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 971d3daa3198e2212c985c634821682d5819346b653Chris Craik 97216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 97316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 97416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9760b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 9770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 97816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 97998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 98098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 9810b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9820b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 98316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 98416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 98516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9860b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 9880b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 9890b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 990eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 9910b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 9920b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 99316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 99498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 99598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 9960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9977db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 9980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 99998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 10000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 10010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 10020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1003f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 10043a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedList, sLightGeometry, Caches::getInstance()); 10050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1006f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 10070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(13, renderer.getIndex()); 10080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 10090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 10100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 10110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 10120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 10130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1014161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 1015161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1016161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 1017161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1018161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1019161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 102016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 10218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1022161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1023161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1024161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1025161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1026161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1027161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 10283a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, zReorder) { 1029d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 1030d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1031d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1032d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1033d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1034d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1035d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1036d3daa3198e2212c985c634821682d5819346b653Chris Craik 103716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 10388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1039161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1040161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1041161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1042161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1043161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1044161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1045161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1046161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1047161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1048161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1049161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1050161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 1051161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1052f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 10533a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 1054161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1055f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1056161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 1057161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1058161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 10593a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionReorder) { 10608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 10618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 10628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 10638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 10648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 10658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 10668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 10688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 10698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 10708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 10718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 10728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1073678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 10748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 10768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 10778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1078678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1079678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1080678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1081678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 10828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 10848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 10858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 10868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1087678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 10888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 10908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 10918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1092678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 10938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 10948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 10958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 10978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 10988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 10998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 11008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 11018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 11028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 11038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 11048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 11058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 11068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 11078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 11088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 11098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 11108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 11118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 11128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 11148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 11158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 11178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 11188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 11198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 11208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 11228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 11238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 11258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 11268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 11288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 11298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 11308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 11328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1133678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1134678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1135678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1136eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 11378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 11388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 11398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 11408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 11418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1143f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 11443a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 11458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1146f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 11488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 11498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1150678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1151678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1152678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1153678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1154678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1155678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1156678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1157678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1158678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1159678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1160678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1161678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1162678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1163678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1164678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1165678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1166678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1167678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1168678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1169678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1170678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1171678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1172678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1173678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1174678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1175678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1176678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1177678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1178678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1179678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1180678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1181678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1182678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 1183678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1184678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1185678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1186678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1187678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1188678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1189678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1190678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1191678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1192678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1193678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1194678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1195678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1196678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1197678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1198678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1199678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto child = TestUtils::createNode(100, 100, 300, 300, 1200678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1201678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1202678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1203678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1204678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1205678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1206678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1207678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1208678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1209678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1210678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1211678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1212678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1213678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1214678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1215678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1216678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1217678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1218678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1219678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1220678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1221678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1222678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1223678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto syncedList = TestUtils::createSyncedNodeList(parent); 1224678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1225678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 1226678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 12273a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedList, sLightGeometry, Caches::getInstance()); 1228678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1229678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1230678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1231678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1232678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1233678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1234678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1235678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1236a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1237a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1238a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1239a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1240a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1241a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1242a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1243a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1244a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1245a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1246a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1247a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1248a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1249a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1250a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1251a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1252a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 1253a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1254a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1255a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1256a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1257a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1258a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1259a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1260a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1261a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1262a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1263a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1264a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1265a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1266a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1267a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1268a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto child = TestUtils::createNode(0, 0, 400, 400, 1269a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1270a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 1271a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op); 1272a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1273a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1274a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1275a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1276a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1277a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1278a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1279a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1280a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1281a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1282a748c08241e43fc68c7c34767d819aef5183936eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 12833a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 1284a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1285a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1286a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1287a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1288a748c08241e43fc68c7c34767d819aef5183936eChris Craik 128998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 129098787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 129116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 12928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 129316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 129416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 129598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 129698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 129798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 129898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 129998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 130098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13016e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1302d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1303d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1304d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1305d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 130698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 13076e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 13086e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 130998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 131098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 131198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 13126e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1313d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1314d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1315d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1316d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1317d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1318161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 13198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 13208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 132198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 132298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1323d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 132498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1325f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13263a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 132798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1328f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 132998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 133098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 133198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13326e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 133398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 133498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 133598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 133698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 133798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 133898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 133998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 134098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 13416e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 13426e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 134398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 134498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 134598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 134698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 134798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 134898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 134998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 135098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 135198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 135298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 135398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 135498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 13568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 135798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 135898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1359eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1360d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 136198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 136298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 136398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1364d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1365d3daa3198e2212c985c634821682d5819346b653Chris Craik 1366f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13676e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 13683a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 136998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1370f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 137198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 137298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1373d3daa3198e2212c985c634821682d5819346b653Chris Craik 1374f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 137598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 137698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 137798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 137898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 137998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 138198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 13826e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 13836e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 13846e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 138598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 138798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 138898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 139098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 139198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 139298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 139398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 139498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 139598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1396d3daa3198e2212c985c634821682d5819346b653Chris Craik 13978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 139816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 139916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 140098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1401eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 140298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 140398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 140498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 140516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 140698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 140798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 140898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 140998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 141098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 141198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 141298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 141398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 141498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 14157db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 141698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 141798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 1418f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 14196e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, 14203a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance()); 142198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1422f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 142398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 142498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 142598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 142698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1427d3daa3198e2212c985c634821682d5819346b653Chris Craik} 142876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 14293a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowLayering) { 143098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 143198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 143298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 143398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 143498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 143598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 143698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 143798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 143898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 143998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 144098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 14418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 14428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 144398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 144498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 144598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 144698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 144798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1448f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 14496e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 14503a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 145198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1452f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 145398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 145498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 145598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 145616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 145776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1458d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1459d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1460d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1461d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1462d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1463d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1464d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1465d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1466d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1467d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1468d3daa3198e2212c985c634821682d5819346b653Chris Craik 146916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 147016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 147116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 147276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 147376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 147476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 147516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 147676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1477f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 14783a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 147976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1480f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 148176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 148276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 148376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 14843a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 148576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 148676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 148776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 148876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 148976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 149076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 149176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 149276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 14933a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropClipping) { 149476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 149576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 149676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 149776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 149876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 149976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 150076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 150176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 150276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15033a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropRevealClip) { 150476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 150576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 150676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 150776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 150876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 150976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 151076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 151176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 151276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 151376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15143a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOutlineClip) { 151576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 151676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 151776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 151876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 151976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 152076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 152176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 152276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 152376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 152476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 152576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 15263a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropTransform) { 152776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 152876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 152976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 153076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 153176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 153276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 153376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 153476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 153576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 153676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 153776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 153876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 153976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 154076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 154176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 154276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 154376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 154476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 154576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 154676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 154776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 154876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 154976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 155076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 155176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 155276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 155376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 155476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 155576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 155676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 155776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 1558161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 15598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 15608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 15618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 15628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 15638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 15648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 15658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 15668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 15678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 15688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 15698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 15708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 15718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 15728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 15738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 15748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 15758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 157616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 15778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 15788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 15798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 15808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 15818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 15838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 15848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 15858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 15868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 15878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 15898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 15908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 15928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 15938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 15958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 15968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 15988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 15998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 16008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 16018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 16028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 16038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 16058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 160616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 160716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 16088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 16098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 16108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 161116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 161216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 161316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 161416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 161516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 16168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16177db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height 16188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16196e068c0182f6f85bccb855a647510724d1c65a13Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 16203a5811b50157e7ba50854caf957e806aee794d39Chris Craik nodes, sLightGeometry, Caches::getInstance()); 16218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 1622f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 16238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 16258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 16268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16283a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 16298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 16328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 16338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 16358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 16365430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 16378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 16388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 16398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 16408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 16418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 16428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16443a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 16458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 16488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 16498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 16508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 16518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 16528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 16538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 16548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 16558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 16578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 16588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 16595430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 16608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 16618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16633a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 16648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 16678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 16688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 16698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 16708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 16728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 16735430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 16748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 16758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 16786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 1679