1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 25ea1724be4d3b6039818f91fc087e1216c1463d5Chris Craik * Copyright (C) 2016 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <gtest/gtest.h> 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <BakedOpState.h> 20d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include <DeferredLayerUpdater.h> 21f158b49c888f722194afe5a80539a2b020c130bcChris Craik#include <FrameBuilder.h> 228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik#include <LayerUpdateQueue.h> 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordedOp.h> 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordingCanvas.h> 258160f20b0aca8c6595d4b385d673f59b6bcd16a4Chris Craik#include <tests/common/TestUtils.h> 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <unordered_map> 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 326e068c0182f6f85bccb855a647510724d1c65a13Chris Craikconst FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 336e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 355854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 365854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 42d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 455854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 475854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 48d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 4974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 50a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 51a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik virtual void recycleTemporaryLayer(OffscreenBuffer*) { 5374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 5474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 5598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 56a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 57a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 58a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 59a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 60a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 6198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 62e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 635854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 66a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 67a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 68a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 697cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 777cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 875854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 915854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 955854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 966fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 977cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 9815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1057cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 108b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1095854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1113a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simple) { 112d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 113d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 115d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 116d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 117d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 118d3daa3198e2212c985c634821682d5819346b653Chris Craik } 119d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 120d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 121d3daa3198e2212c985c634821682d5819346b653Chris Craik } 122d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 123d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 124d3daa3198e2212c985c634821682d5819346b653Chris Craik } 125e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 126d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 127d3daa3198e2212c985c634821682d5819346b653Chris Craik } 128d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 129d3daa3198e2212c985c634821682d5819346b653Chris Craik 1308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 1318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 132ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(25, 25); 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 134b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 10, 10, nullptr); 135b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 1369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 1379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleTestRenderer renderer; 141f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1425854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end 1436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 1446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1453a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleStroke) { 146386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik class SimpleStrokeTestRenderer : public TestRendererBase { 147386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik public: 148386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik void onPointsOp(const PointsOp& op, const BakedOpState& state) override { 149386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(0, mIndex++); 150386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // even though initial bounds are empty... 151386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_TRUE(op.unmappedBounds.isEmpty()) 152386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "initial bounds should be empty, since they're unstroked"; 153386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(Rect(45, 45, 55, 55), state.computedState.clippedBounds) 154386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "final bounds should account for stroke"; 155386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 156386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }; 157386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 158386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 159386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 160386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPaint strokedPaint; 161386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik strokedPaint.setStrokeWidth(10); 162386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik canvas.drawPoint(50, 50, strokedPaint); 163386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }); 1649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 1659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 168386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 169f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 170386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 171386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 172386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 1733a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleRejection) { 1748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 176eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 1776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty 1786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 1806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 1819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 1829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 184b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 186f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 187b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1893a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleBatching) { 190a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 191d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 192d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 193d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 194a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 195d3daa3198e2212c985c634821682d5819346b653Chris Craik } 196d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 197a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 198d3daa3198e2212c985c634821682d5819346b653Chris Craik } 199d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 200d3daa3198e2212c985c634821682d5819346b653Chris Craik 2018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 2028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 20315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(10, 10, 20415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik kAlpha_8_SkColorType); // Disable merging by using alpha 8 bitmap 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 208eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 209a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 5, 0, nullptr); 213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 2169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 2179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 219b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2205854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 221f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 222a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 22315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 224a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 225a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 2269cd1bbe5c9e14472e631d8cc10005613925f34afChris CraikRENDERTHREAD_TEST(FrameBuilder, deferRenderNode_translateClip) { 2279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik class DeferRenderNodeTranslateClipTestRenderer : public TestRendererBase { 2289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public: 2299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(0, mIndex++); 2319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(5, 10, 55, 60), state.computedState.clippedBounds); 2329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom, 2339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik state.computedState.clipSideFlags); 2349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }; 2369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto node = TestUtils::createNode(0, 0, 100, 100, 2389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 2399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 2409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }); 2419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(5, 10, Rect(50, 50), // translate + clip node 2459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik *TestUtils::getSyncedNode(node)); 2469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik DeferRenderNodeTranslateClipTestRenderer renderer; 2489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(1, renderer.getIndex()); 2509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik} 2519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2529cd1bbe5c9e14472e631d8cc10005613925f34afChris CraikRENDERTHREAD_TEST(FrameBuilder, deferRenderNodeScene) { 2539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik class DeferRenderNodeSceneTestRenderer : public TestRendererBase { 2549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public: 2559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik const Rect& clippedBounds = state.computedState.clippedBounds; 2579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik Matrix4 expected; 2589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik switch (mIndex++) { 2599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 0: 2609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // background - left side 2619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(600, 100, 700, 500), clippedBounds); 2629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(100, 100, 0); 2639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 1: 2659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // background - top side 2669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(100, 400, 600, 500), clippedBounds); 2679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(100, 100, 0); 2689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 2: 2709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // content 2719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(100, 100, 700, 500), clippedBounds); 2729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(-50, -50, 0); 2739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 3: 2759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // overlay 2769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(0, 0, 800, 200), clippedBounds); 2779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik default: 2799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik ADD_FAILURE() << "Too many rects observed"; 2809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(expected, state.computedState.transform); 2829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }; 2849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik std::vector<sp<RenderNode>> nodes; 2869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik SkPaint transparentPaint; 2879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik transparentPaint.setAlpha(128); 2889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // backdrop 2909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik nodes.push_back(TestUtils::createNode(100, 100, 700, 500, // 600x400 2919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 2929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 600, 400, transparentPaint); 2939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 2949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // content 2969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik Rect contentDrawBounds(150, 150, 650, 450); // 500x300 2979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik nodes.push_back(TestUtils::createNode(0, 0, 800, 600, 2989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 2999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 800, 600, transparentPaint); 3009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // overlay 3039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik nodes.push_back(TestUtils::createNode(0, 0, 800, 600, 3049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 3059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 800, 200, transparentPaint); 3069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik for (auto& node : nodes) { 3099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik TestUtils::syncHierarchyPropertiesAndDisplayList(node); 3109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 3119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600, 3139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 3149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds); 3159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik DeferRenderNodeSceneTestRenderer renderer; 3179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(4, renderer.getIndex()); 3199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik} 3209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3216246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, empty_noFbo0) { 3226246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyNoFbo0TestRenderer : public TestRendererBase { 3236246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 3246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 3256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 3266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 3286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 3296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3306246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 3316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // Use layer update constructor, so no work is enqueued for Fbo0 3339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik LayerUpdateQueue emptyLayerUpdateQueue; 3349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(emptyLayerUpdateQueue, sLightGeometry, Caches::getInstance()); 3356246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyNoFbo0TestRenderer renderer; 3366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 3386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, empty_withFbo0) { 3406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyWithFbo0TestRenderer : public TestRendererBase { 3416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 3426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 3436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 3446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 3466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 3476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 3496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 3506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 3516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // no drawn content 3526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 3536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // Draw, but pass node without draw content, so no work is done for primary frame 3559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 3569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 3579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 3589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3596246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyWithFbo0TestRenderer renderer; 3606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced," 3626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik " but fbo0 update lifecycle should still be observed"; 3636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 3646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 36580d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikRENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_rects) { 36680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawRectsTestRenderer : public TestRendererBase { 36780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 36880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 36980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(mIndex++, 0) << "Should be one rect"; 37080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds) 37180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Last rect should occlude others."; 37280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 37380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 37480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 37580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 37680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 37780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 37880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 37980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 38080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 38180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // Damage (and therefore clip) is same as last draw, subset of renderable area. 38280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // This means last op occludes other contents, and they'll be rejected to avoid overdraw. 3839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200, 3849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 3859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 38680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 38780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(3u, node->getDisplayList()->getOps().size()) 38880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 38980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 39080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawRectsTestRenderer renderer; 39180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 39280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op"; 39380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 39480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 39580d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikRENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_bitmaps) { 39680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik static SkBitmap opaqueBitmap = TestUtils::createSkBitmap(50, 50, 39780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik SkColorType::kRGB_565_SkColorType); 39880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik static SkBitmap transpBitmap = TestUtils::createSkBitmap(50, 50, 39980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik SkColorType::kAlpha_8_SkColorType); 40080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase { 40180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 40280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 40380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik switch(mIndex++) { 40480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 0: 40580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(opaqueBitmap.pixelRef(), op.bitmap->pixelRef()); 40680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 40780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 1: 40880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(transpBitmap.pixelRef(), op.bitmap->pixelRef()); 40980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 41080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik default: 41180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik ADD_FAILURE() << "Only two ops expected."; 41280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 41380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 41480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 41580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 41680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik auto node = TestUtils::createNode(0, 0, 50, 50, 41780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 41880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 41980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 42080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawBitmap(transpBitmap, 0, 0, nullptr); 42180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 42280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // only the below draws should remain, since they're 42380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawBitmap(opaqueBitmap, 0, 0, nullptr); 42480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawBitmap(transpBitmap, 0, 0, nullptr); 42580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 4269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50, 4279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 42980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 43080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(5u, node->getDisplayList()->getOps().size()) 43180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 43280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 43380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawBitmapsTestRenderer renderer; 43480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 435a82ffc549bd6dbf8cfc6f4d646d0f458dca54014sergeyv EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops"; 43680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 43780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 4383a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clippedMerging) { 43993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 44093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 44193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 44293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 44393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 44493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 44593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 44693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 44793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 44893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 44993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 45093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik auto node = TestUtils::createNode(0, 0, 100, 100, 45193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik [](RenderProperties& props, TestCanvas& canvas) { 45293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik SkBitmap bitmap = TestUtils::createSkBitmap(20, 20); 45393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 45493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 45593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op); 45693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 0, 40, nullptr); 45793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 45893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 45993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op); 46093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 0, nullptr); 46193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 46293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 46393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op); 46493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 80, 40, nullptr); 46593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 46693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 46793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op); 46893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 70, nullptr); 46993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 47093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 4719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 4729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 4749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 47593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 476f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 47793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 47893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 47993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 4803a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textMerging) { 481d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 482d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 483d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 484d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 485d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 486d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 487d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 488d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 489d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 490d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 491d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 492d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 493d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik [](RenderProperties& props, TestCanvas& canvas) { 494d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 495d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 496d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 497d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 498dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 499dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 500d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 5019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 5029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 505d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 506f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 507d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 508d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 509d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 5103a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStrikethrough) { 511a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 512a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 513a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 514a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 515a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 516a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 51715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 51815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 51915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 52015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 521a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 522a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 5238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 2000, 5248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 525a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 526a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 527a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 528a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setStrikeThruText(true); 52942a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 530a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 531dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 532a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 533a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 5349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 5359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000, 5369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 539a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 540f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 541a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 542d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 543b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 544b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 5457c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = { 5467c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; 5477c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5483a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStyle) { 5497c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik class TextStyleTestRenderer : public TestRendererBase { 5507c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik public: 5517c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 5527c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, mIndex); 5537c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(3u, opList.count); 5547c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik mIndex += opList.count; 5557c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5567c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik int index = 0; 5577c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 5587c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto state = opList.states[index++]; 5597c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(style, state->op->paint->getStyle()) 5607c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Remainder of validation relies upon stable merged order"; 5617c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, state->computedState.clipSideFlags) 5627c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Clipped bounds validation requires unclipped ops"; 5637c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 5647c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5657c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect fill = opList.states[0]->computedState.clippedBounds; 5667c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect stroke = opList.states[1]->computedState.clippedBounds; 5677c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) 5687c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Stroke+Fill should be same as stroke"; 5697c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5707c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_TRUE(stroke.contains(fill)); 5717c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_FALSE(fill.contains(stroke)); 5727c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 57379abbf22d4f672208327546661e694d837f564a9Derek Sollenberger // outset by half the stroke width 5747c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect outsetFill(fill); 57579abbf22d4f672208327546661e694d837f564a9Derek Sollenberger outsetFill.outset(5); 5767c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, outsetFill); 5777c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 5787c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }; 5797c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 5807c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik [](RenderProperties& props, TestCanvas& canvas) { 5817c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint paint; 5827c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 5837c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setAntiAlias(true); 5847c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextSize(50); 5857c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStrokeWidth(10); 5867c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 5877c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // draw 3 copies of the same text overlapping, each with a different style. 5887c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // They'll get merged, but with 5897c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 5907c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStyle(style); 591dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 5927c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 5937c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }); 5949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 5959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5977c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TextStyleTestRenderer renderer; 5987c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 5997c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; 6007c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik} 6017c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 602aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { 603aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { 604d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 605d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 606d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 607e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 608d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 609d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 610d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 611d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 612d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 613d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 614d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 615d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 616d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 617243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik SkMatrix::MakeTrans(5, 5)); 618d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 619d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 620d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 621eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 622d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 623d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 624d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 625d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 6269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 6279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 6289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 631aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerClipLocalMatrixTestRenderer renderer; 632f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 633d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 634d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 635d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 636aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { 637aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { 638aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik public: 639aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 640aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(0, mIndex++); 641aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 642aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik Matrix4 expected; 643aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik expected.loadTranslate(35, 45, 0); 644aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 645aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik } 646aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }; 647aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 648aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 649aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 650aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 651aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 652aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 653aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.save(SaveFlags::MatrixClip); 654aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.translate(30, 40); 655aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 656aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.restore(); 657aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 658aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 6599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 6609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 663aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerCombineMatricesTestRenderer renderer; 664aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 665aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(1, renderer.getIndex()); 666aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 667aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 668aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { 669aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 670aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 671aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected 672aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 673aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 674aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 675aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 676aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 6779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 6789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 6799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 682aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FailRenderer renderer; 683aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 684aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 685aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 6863a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, functor_reject) { 687223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 688223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 689223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 690223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 691223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 692223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 693223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 694223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 695223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 696223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000, 697223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 698223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 699cd1c3eba69d044b551cededad75474038f919890John Reck canvas.callDrawGLFunction(&noopFunctor, nullptr); 700223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 701223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 7029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7033a5811b50157e7ba50854caf957e806aee794d39Chris Craik sLightGeometry, Caches::getInstance()); 7049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(scrolledFunctorView)); 7059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 706223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 707223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 708223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 709223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 710223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 711a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikRENDERTHREAD_TEST(FrameBuilder, deferColorOp_unbounded) { 712a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik class ColorTestRenderer : public TestRendererBase { 713a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik public: 714a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 715a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(0, mIndex++); 716a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds) 717a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik << "Color op should be expanded to bounds of surrounding"; 718a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik } 719a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }; 720a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 721a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik auto unclippedColorView = TestUtils::createNode(0, 0, 10, 10, 722a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 723a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik props.setClipToBounds(false); 724a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 725a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }); 726a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 7279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 728a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik sLightGeometry, Caches::getInstance()); 7299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(unclippedColorView)); 7309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 731a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik ColorTestRenderer renderer; 732a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 733a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected"; 734a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 735a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 736a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikTEST(FrameBuilder, renderNode) { 737d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 738d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 739d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 740d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 741d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 7425430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 743d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 744d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 745d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 746d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 747d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 748d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 749d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 750d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 751d3daa3198e2212c985c634821682d5819346b653Chris Craik } 752d3daa3198e2212c985c634821682d5819346b653Chris Craik } 753d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 754d3daa3198e2212c985c634821682d5819346b653Chris Craik 7558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 7568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 757b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 758b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 759b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 760b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 761b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 7628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 763d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 764ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 765ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 766ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 767ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 768eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 769ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 770d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 771ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 772b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 773b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 7749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 7769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 7779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 7785854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 779f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 780223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 781b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 782b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 7833a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clipped) { 784d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 785d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 786d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 787d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 788d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 789e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 790d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 791d3daa3198e2212c985c634821682d5819346b653Chris Craik } 792d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 793d3daa3198e2212c985c634821682d5819346b653Chris Craik 7948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 796ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 797ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 798ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 799ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 8009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // clip to small area, should see in receiver 8019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200, 8029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 8049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8055854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 806f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 807ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 808ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 8093a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) { 810d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 811d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 812d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 813d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 814d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 815d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 816d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 817d3daa3198e2212c985c634821682d5819346b653Chris Craik } 818d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 819d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 820d3daa3198e2212c985c634821682d5819346b653Chris Craik } 821d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 822d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 823d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 8245430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 825e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 826d3daa3198e2212c985c634821682d5819346b653Chris Craik 827d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 828d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 829d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 830d3daa3198e2212c985c634821682d5819346b653Chris Craik } 831d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 832d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 833d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 834e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 835d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 836d3daa3198e2212c985c634821682d5819346b653Chris Craik } 83774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 83874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 83974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(nullptr, offscreenBuffer); 84074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 841d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 842d3daa3198e2212c985c634821682d5819346b653Chris Craik 8438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 8448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 845eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 8466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 8476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 8486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 8499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 8519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 8539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8545854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 855f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 85674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, renderer.getIndex()); 857b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 8586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8593a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) { 860d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 861d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 862d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 863d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 864d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 865d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 866d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 867d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 868d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 869d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 870d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 871d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 872d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 873d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 874d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 875d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 876d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 877d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 878d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 879d3daa3198e2212c985c634821682d5819346b653Chris Craik } 880d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 881d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 882d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 883d3daa3198e2212c985c634821682d5819346b653Chris Craik } 88498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 885d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 886d3daa3198e2212c985c634821682d5819346b653Chris Craik } 887e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 888d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 889d3daa3198e2212c985c634821682d5819346b653Chris Craik } 890d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 891d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 892d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 8935430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 894d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 8955430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 896d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 897d3daa3198e2212c985c634821682d5819346b653Chris Craik } 898d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 899d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 900d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 901d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 9025430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 903d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 904d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 9055430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 906d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 907d3daa3198e2212c985c634821682d5819346b653Chris Craik } 90874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 90974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik const int index = mIndex++; 91074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik // order isn't important, but we need to see both 91174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik if (index == 10) { 91274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer); 91374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else if (index == 11) { 91474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer); 91574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else { ADD_FAILURE(); } 91674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 917d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 918d3daa3198e2212c985c634821682d5819346b653Chris Craik 9198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 9208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 921eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 9226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 9236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 924eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 9256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 9266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 9276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 9286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 9306fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 9326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800, 9349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 9359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 9369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 9375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 938f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 93974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, renderer.getIndex()); 9406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 9416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9423a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) { 9438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 9448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 945eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 9466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 947eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 9486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 9506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 9516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 9559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 9569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 9579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 9589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 9596fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9605854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 9616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 962f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 963b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 9646fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 9653a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) { 966b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 967b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 968b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 969b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 970b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 9717435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 972b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 973b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 974b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 975b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 976b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 977b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 978b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 979b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 980b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 981b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 982b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 983b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 984b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 985b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 986b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 987b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 988b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 9897435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 990b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 991b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 992b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 993b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 994b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 995b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 996eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 997b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 998b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 999b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 10009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 10019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 10029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 10039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 10049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1005b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 1006f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1007b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 1008b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1009b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 101045e83338e525070702c12d68d904107989f439f9Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_round) { 101145e83338e525070702c12d68d904107989f439f9Chris Craik class SaveLayerUnclippedRoundTestRenderer : public TestRendererBase { 101245e83338e525070702c12d68d904107989f439f9Chris Craik public: 101345e83338e525070702c12d68d904107989f439f9Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 101445e83338e525070702c12d68d904107989f439f9Chris Craik EXPECT_EQ(0, mIndex++); 101545e83338e525070702c12d68d904107989f439f9Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds) 101645e83338e525070702c12d68d904107989f439f9Chris Craik << "Bounds rect should round out"; 101745e83338e525070702c12d68d904107989f439f9Chris Craik } 101845e83338e525070702c12d68d904107989f439f9Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {} 101945e83338e525070702c12d68d904107989f439f9Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override {} 102045e83338e525070702c12d68d904107989f439f9Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 102145e83338e525070702c12d68d904107989f439f9Chris Craik EXPECT_EQ(1, mIndex++); 102245e83338e525070702c12d68d904107989f439f9Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds) 102345e83338e525070702c12d68d904107989f439f9Chris Craik << "Bounds rect should round out"; 102445e83338e525070702c12d68d904107989f439f9Chris Craik } 102545e83338e525070702c12d68d904107989f439f9Chris Craik }; 102645e83338e525070702c12d68d904107989f439f9Chris Craik 102745e83338e525070702c12d68d904107989f439f9Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 102845e83338e525070702c12d68d904107989f439f9Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 102945e83338e525070702c12d68d904107989f439f9Chris Craik canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out 103045e83338e525070702c12d68d904107989f439f9Chris Craik 128, (SaveFlags::Flags)(0)); 103145e83338e525070702c12d68d904107989f439f9Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 103245e83338e525070702c12d68d904107989f439f9Chris Craik canvas.restore(); 103345e83338e525070702c12d68d904107989f439f9Chris Craik }); 103445e83338e525070702c12d68d904107989f439f9Chris Craik 103545e83338e525070702c12d68d904107989f439f9Chris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 103645e83338e525070702c12d68d904107989f439f9Chris Craik sLightGeometry, Caches::getInstance()); 103745e83338e525070702c12d68d904107989f439f9Chris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 103845e83338e525070702c12d68d904107989f439f9Chris Craik 103945e83338e525070702c12d68d904107989f439f9Chris Craik SaveLayerUnclippedRoundTestRenderer renderer; 104045e83338e525070702c12d68d904107989f439f9Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 104145e83338e525070702c12d68d904107989f439f9Chris Craik EXPECT_EQ(2, renderer.getIndex()); 104245e83338e525070702c12d68d904107989f439f9Chris Craik} 104345e83338e525070702c12d68d904107989f439f9Chris Craik 10443a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 1045b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 1046b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1047b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1048b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1049b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 1050b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 1051b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 1052b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 1053b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 1054b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 1055b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 1056b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 1057b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 1058b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 1059b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 1060b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1061b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1062b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1063b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 1064b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 1065b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 1066b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 1067b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 1068b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 1069b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1070b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1071b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1072b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1073b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1074b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1075b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 1076b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1077b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1078b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1079b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1080b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1081b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1082eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 1083b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 1084eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 1085eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 1086eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 1087eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 1088b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 1089b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 1090b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 10919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 10929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 10939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 10949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 10959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1096b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 1097f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1098b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 1099b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 1100b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1101b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 11023a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_clearClip) { 11034876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 11044876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 11054876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 11064876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 11074876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11084876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 11094876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 11104876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 11114876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 11124876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 11134876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 11144876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 11154876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 11164876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 11174876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11184876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 11194876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 11204876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11214876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 11224876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 11234876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11244876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 11254876de16e34622634266d09522c9153c78c7c2fbChris Craik 11264876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 11274876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 11284876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 11294876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 11304876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 11314876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 11324876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 11334876de16e34622634266d09522c9153c78c7c2fbChris Craik 11344876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 11359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 11369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 11379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 11389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 11394876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 11404876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11414876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 11424876de16e34622634266d09522c9153c78c7c2fbChris Craik} 11434876de16e34622634266d09522c9153c78c7c2fbChris Craik 11443a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_reject) { 11454876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 11464876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 11474876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 11484876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 11494876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 11504876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 11514876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 11524876de16e34622634266d09522c9153c78c7c2fbChris Craik 11534876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 11549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, 11559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 11569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 11579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 11584876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 11594876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11604876de16e34622634266d09522c9153c78c7c2fbChris Craik} 11614876de16e34622634266d09522c9153c78c7c2fbChris Craik 1162b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 1163b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 1164b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 1165b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 11663a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) { 1167b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 1168b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1169b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1170b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 1171b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 1172b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1173b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1174b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1175b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 1176b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1177b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1178b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1179b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 1180b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1181b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1182b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 1183b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 1184b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 1185b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 1186b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 1187b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1188b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1189b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1190b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 1191b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1192b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 1193b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1194b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1195b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1196b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 1197b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1198b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1199b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 120074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1201b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1202b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 1203b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 1204b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 120574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 120674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, mIndex++); 120774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer); 120874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1209b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1210b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1211b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 1212b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1213eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 1214eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 1215eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 1216b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 1217b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1218b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1219b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1220b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 12219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 12229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600, 12239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 12249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 12259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1226b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 1227f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 122874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, renderer.getIndex()); 1229b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1230b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1231f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 1232d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 1233d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 123498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1235d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 123698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 123798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 123898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 1239d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1240d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1241d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 12420b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1243d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 1244d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 1245d3daa3198e2212c985c634821682d5819346b653Chris Craik 1246e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 1247d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 1248d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1249d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1250d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 1251d3daa3198e2212c985c634821682d5819346b653Chris Craik } 125298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1253d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 1254d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1255d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1256d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 1257d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1258e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1259d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 1260d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1261d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 12620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 126416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 126516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 12660b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 12670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 12680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 126916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 127098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 12710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 127298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 127398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 127498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 12750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(node); 12770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12780b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 127998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 12800b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 12810b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 12839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 12849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 12859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 12869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 12870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 1288f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 12890b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 12900b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12910b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 129298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 12930b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 12940b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1295f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 1296d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 1297d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 1298d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 1299d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 1300d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 1301d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 1302d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 1303d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1304d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1305d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 1306d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 1307d3daa3198e2212c985c634821682d5819346b653Chris Craik } 130898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1309d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1310d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 1311d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 131298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 131398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 1314d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 1315d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 131698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 131798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 1318d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1319d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1320d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1321d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1322d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 1323d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 1324d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 1325d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 1326d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 1327d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1328d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1329d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1330d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1331d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1332d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 1333d3daa3198e2212c985c634821682d5819346b653Chris Craik } 133498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1335d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 1336d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1337d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 133898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 1339d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1340d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 134198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 134298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 1343d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 1344d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1345d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 134698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 134798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 1348d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1349d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1350e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1351d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 1352d3daa3198e2212c985c634821682d5819346b653Chris Craik } 135374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 135474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, mIndex++); 135574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1356d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1357d3daa3198e2212c985c634821682d5819346b653Chris Craik 135816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 135916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 136016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 13610b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 13620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 13630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 136416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 136598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 136698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 13670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 136916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 137016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 137116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 13720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 13730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 13740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 13750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1376eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 13770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 13780b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 137916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 138098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 138198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 13820b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 13840b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 138598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 13860b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 13870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 13880b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 13909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 13919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 13929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 13939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 13940b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1395f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 139674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(14, renderer.getIndex()); 13970b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 13990b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 14000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 14010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 14020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14036246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14046246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, buildLayer) { 14056246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class BuildLayerTestRenderer : public TestRendererBase { 14066246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 14076246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 14086246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 14096246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 14106246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 14116246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 14126246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14136246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 14146246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 14156246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14166246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 14176246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Transform should be reset within layer"; 14186246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14196246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 14206246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Damage rect should be used to clip layer content"; 14216246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14226246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endLayer() override { 14236246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, mIndex++); 14246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 14266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 14276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 14296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 14306246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 14326246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 14346246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 14356246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik props.mutateLayerProperties().setType(LayerType::RenderLayer); 14366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 14376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 14386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 14396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // create RenderNode's layer here in same way prepareTree would 14416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 14426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = &layer; 14436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik TestUtils::syncHierarchyPropertiesAndDisplayList(node); 14456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // only enqueue partial damage 14476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 14486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 14496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // Draw, but pass empty node list, so no work is done for primary frame 14519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(layerUpdateQueue, sLightGeometry, Caches::getInstance()); 14526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik BuildLayerTestRenderer renderer; 14536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 14546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(3, renderer.getIndex()); 14556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 14566246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // clean up layer pointer, so we can safely destruct RenderNode 14576246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = nullptr; 14586246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 14596246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 1460161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 1461161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1462161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 1463161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1464161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1465161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 146616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 14678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1468161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1469161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1470161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1471161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1472161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1473161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 14743a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, zReorder) { 1475d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 1476d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1477d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1478d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1479d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1480d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1481d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1482d3daa3198e2212c985c634821682d5819346b653Chris Craik 148316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 14848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1485161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1486161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1487161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1488161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1489161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1490161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1491161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1492161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1493161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1494161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1495161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1496161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 1497161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 14989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 14999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 15009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 15019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1502161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1503f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1504161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 1505161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1506161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 15073a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionReorder) { 15088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 15098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 15108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 15118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 15128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 15138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 15148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 15158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 15168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 15178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 15188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 15198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 15208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1521678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 15228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 15238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 15248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 15258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1526678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1527678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1528678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1529678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 15308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 15318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 15328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 15338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 15348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1535678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 15368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 15378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 15388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 15398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1540678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 15418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 15428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 15438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 15448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 15458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 15468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 15478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 15488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 15498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 15508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 15518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 15528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 15538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 15548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 15558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 15568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 15578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 15588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 15598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 15608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 15618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 15628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 15638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 15648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 15658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 15668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 15678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 15688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 15698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 15708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 15718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 15728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 15738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 15748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 15758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 15768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 15778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 15788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 15798d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 15808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1581678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1582678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1583678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1584eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 15858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 15868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 15878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 15888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 15898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 15908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 15919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 15929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 15939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 15949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 15958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1596f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 15978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 15988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 15998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1600678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1601678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1602678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1603678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1604678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1605678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1606678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1607678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1608678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1609678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1610678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1611678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1612678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1613678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1614678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1615678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1616678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1617678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1618678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1619678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1620678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1621678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1622678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1623678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1624678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1625678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1626678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1627678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1628678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1629678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1630678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1631678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1632678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 1633678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1634678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1635678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1636678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1637678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1638678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1639678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1640678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1641678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1642678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1643678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1644678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1645678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1646678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1647678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1648678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1649678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto child = TestUtils::createNode(100, 100, 300, 300, 1650678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1651678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1652678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1653678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1654678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1655678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1656678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1657678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1658678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1659678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1660678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1661678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1662678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1663678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1664678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1665678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1666678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1667678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1668678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1669678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1670678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1671678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1672678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 16739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 16749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1675678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1676678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 16779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 16789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 16799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 16809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 16819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 16829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1683678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1684678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1685678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1686678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1687678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1688678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1689678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1690678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1691a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1692a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1693a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1694a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1695a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1696a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1697a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1698a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1699a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1700a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1701a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1702a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1703a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1704a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1705a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1706a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1707a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 1708a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1709a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1710a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1711a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1712a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1713a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1714a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1715a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1716a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1717a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1718a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1719a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1720a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1721a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1722a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1723a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto child = TestUtils::createNode(0, 0, 400, 400, 1724a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1725a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 1726a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op); 1727a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1728a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1729a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1730a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1731a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1732a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1733a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1734a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1735a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1736a748c08241e43fc68c7c34767d819aef5183936eChris Craik 17379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 17389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 17399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 17409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1741a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1742a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1743a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1744a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1745a748c08241e43fc68c7c34767d819aef5183936eChris Craik 174698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 174798787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 174816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 17498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 175016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 175116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 175298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 175398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 175498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 175598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 175698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 175798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 17586e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1759d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1760d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1761d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1762d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 176398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 17646e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 17656e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 176698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 176798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 176898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 17696e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1770d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1771d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1772d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1773d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1774d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1775161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 17768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 17778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 177898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 177998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1780d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 178198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 17829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 17839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 17849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 17859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 178698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1787f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 178898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 178998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 179098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 17916e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 179298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 179398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 179498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 179598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 179698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 179798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 179898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 179998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 18006e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 18016e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 180298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 180398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 180498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 180598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 180698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 180798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 180898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 180998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 181098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 181198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 181274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 181374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, mIndex++); 181474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 181598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 181698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 18178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 18188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 181998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 182098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1821eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1822d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 182398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 182498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 182598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1826d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1827d3daa3198e2212c985c634821682d5819346b653Chris Craik 18289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 18293a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 18309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 18319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 183298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1833f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 183474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(6, renderer.getIndex()); 183598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1836d3daa3198e2212c985c634821682d5819346b653Chris Craik 1837f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 183898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 183998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 184098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 184198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 184298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 184398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 184498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 18456e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 18466e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 18476e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 184898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 184998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 185098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 185198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 185298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 185398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 185498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 185598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 185698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 185798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 185898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1859d3daa3198e2212c985c634821682d5819346b653Chris Craik 18608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 186116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 186216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 186398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1864eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 186598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 186698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 186798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 186816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 186998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 187098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 187198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 187298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 187398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 187498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 187598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 187698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 187798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 18789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 187998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 188098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 18819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 18829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 18833a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance()); 18849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 18859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 18869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 188798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1888f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 188998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 189098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 189198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 189298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1893d3daa3198e2212c985c634821682d5819346b653Chris Craik} 189476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 18953a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowLayering) { 189698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 189798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 189898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 189998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 190098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 190198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 190298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 190398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 190498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 190598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 190698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 19078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 19088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 190998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 191098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 191198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 191298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 19139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 19143a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 19159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 19169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 191798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1918f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 191998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 192098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 192198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1922d645640180c25c2711e99aa82ec629155f8e91baChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowClipping) { 1923d645640180c25c2711e99aa82ec629155f8e91baChris Craik class ShadowClippingTestRenderer : public TestRendererBase { 1924d645640180c25c2711e99aa82ec629155f8e91baChris Craik public: 1925d645640180c25c2711e99aa82ec629155f8e91baChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1926d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(0, mIndex++); 1927d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipState->rect) 1928d645640180c25c2711e99aa82ec629155f8e91baChris Craik << "Shadow must respect pre-barrier canvas clip value."; 1929d645640180c25c2711e99aa82ec629155f8e91baChris Craik } 1930d645640180c25c2711e99aa82ec629155f8e91baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1931d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(1, mIndex++); 1932d645640180c25c2711e99aa82ec629155f8e91baChris Craik } 1933d645640180c25c2711e99aa82ec629155f8e91baChris Craik }; 1934d645640180c25c2711e99aa82ec629155f8e91baChris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 1935d645640180c25c2711e99aa82ec629155f8e91baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1936d645640180c25c2711e99aa82ec629155f8e91baChris Craik // Apply a clip before the reorder barrier/shadow casting child is drawn. 1937d645640180c25c2711e99aa82ec629155f8e91baChris Craik // This clip must be applied to the shadow cast by the child. 1938d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.clipRect(25, 25, 75, 75, SkRegion::kIntersect_Op); 1939d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.insertReorderBarrier(true); 1940d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1941d645640180c25c2711e99aa82ec629155f8e91baChris Craik }); 1942d645640180c25c2711e99aa82ec629155f8e91baChris Craik 19439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 1944d645640180c25c2711e99aa82ec629155f8e91baChris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 19459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 19469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1947d645640180c25c2711e99aa82ec629155f8e91baChris Craik ShadowClippingTestRenderer renderer; 1948d645640180c25c2711e99aa82ec629155f8e91baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1949d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(2, renderer.getIndex()); 1950d645640180c25c2711e99aa82ec629155f8e91baChris Craik} 1951d645640180c25c2711e99aa82ec629155f8e91baChris Craik 195216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 195376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1954d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1955d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1956d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1957d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1958d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1959d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1960d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1961d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1962d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1963d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1964d3daa3198e2212c985c634821682d5819346b653Chris Craik 196516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 196616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 196716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 196876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 196976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 197076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 197116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 197276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 19739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, 19749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 19759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 19769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 197776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1978f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 197976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 198076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 198176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 19823a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 198376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 198476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 198576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 198676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 198776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 198876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 198976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 199076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 19913a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropClipping) { 199276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 199376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 199476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 199576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 199676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 199776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 199876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 199976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 200076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20013a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropRevealClip) { 200276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 200376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 200476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 200576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 200676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 200776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 200876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 200976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 201076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 201176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20123a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOutlineClip) { 201376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 201476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 201576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 201676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 201776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 201876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 201976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 202076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 202176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 202276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 202376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20243a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropTransform) { 202576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 202676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 202776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 202876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 202976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 203076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 203176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 203276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 203376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 203476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 203576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 203676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 203776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 203876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 203976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 204076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 204176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 204276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 204376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 204476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 204576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 204676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 204776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 204876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 204976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 205076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 205176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 205276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 205376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 205476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 205576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 2056161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 20578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 20588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 20598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 20608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 20618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 2062c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck Matrix4 drawLayerMatrix; 20638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 20648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 20658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 20668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 20678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 20688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 20698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 20708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 20718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 20728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 20738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 20748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 207516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 20768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 20778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 20788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 20798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 20808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 20818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 20828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 20838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 20848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 20858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 20868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 20878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 20888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 20898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 20908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 20918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 20928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 20938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 20948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 20958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 20968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 20978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 2098c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck mOutData->drawLayerMatrix = state.computedState.transform; 20998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 210074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 210174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 210274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 21038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 21048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 21058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 21068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 21088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 210916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 211016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 21118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 21128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 21138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 211416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 211516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 211616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 211716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 211816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 21198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 21209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height 21219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 21229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 21239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 21249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 21258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 2127f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 21288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 213074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 21318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 21328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21333a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 21348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 21358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 21368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 21378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 21388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 21398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 21408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 21415430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 21428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 21438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 21448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 21458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 21468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 2147c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck expected.loadTranslate(10, 0, 0); 2148c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix) 2149c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck << "expect drawLayer to be translated as part of being clipped"; 21508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 21518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21523a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 21538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 21548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 21558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 21568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 21578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 21588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 21598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 21608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 21618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 21628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 21638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 21648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 21658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 21668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 21675430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 21688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 21698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 21708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21713a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 21728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 21738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 21748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 21758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 21768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 21778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 21788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 21798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 21808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 21815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 21828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 21838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 21848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 218504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris CraikRENDERTHREAD_TEST(FrameBuilder, clip_replace) { 218604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik class ClipReplaceTestRenderer : public TestRendererBase { 218704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik public: 218804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 218904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(0, mIndex++); 219004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_TRUE(op.localClip->intersectWithRoot); 219104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect) 219204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik << "Expect resolved clip to be intersection of viewport clip and clip op"; 219304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 219404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }; 219504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik auto node = TestUtils::createNode(20, 20, 30, 30, 219604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 219704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik canvas.clipRect(0, -20, 10, 30, SkRegion::kReplace_Op); 219804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 219904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }); 220004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 22019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50, 22029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 22039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 22049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 220504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik ClipReplaceTestRenderer renderer; 220604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 220704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(1, renderer.getIndex()); 220804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 220904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 22106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 22116fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 2212