FrameBuilderTests.cpp revision 223e3b6c2b53a66b4efd8040edfe23ed1a5c925e
1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/* 25ea1724be4d3b6039818f91fc087e1216c1463d5Chris Craik * Copyright (C) 2016 The Android Open Source Project 3b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 4b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Licensed under the Apache License, Version 2.0 (the "License"); 5b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * you may not use this file except in compliance with the License. 6b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * You may obtain a copy of the License at 7b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 8b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * http://www.apache.org/licenses/LICENSE-2.0 9b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * 10b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Unless required by applicable law or agreed to in writing, software 11b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * distributed under the License is distributed on an "AS IS" BASIS, 12b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * See the License for the specific language governing permissions and 14b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * limitations under the License. 15b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik */ 16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <gtest/gtest.h> 18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 19b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <BakedOpState.h> 20d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik#include <DeferredLayerUpdater.h> 21f158b49c888f722194afe5a80539a2b020c130bcChris Craik#include <FrameBuilder.h> 228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik#include <LayerUpdateQueue.h> 23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordedOp.h> 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordingCanvas.h> 258160f20b0aca8c6595d4b385d673f59b6bcd16a4Chris Craik#include <tests/common/TestUtils.h> 26b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <unordered_map> 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikconst LayerUpdateQueue sEmptyLayerUpdateQueue; 336e068c0182f6f85bccb855a647510724d1c65a13Chris Craikconst FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 346e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 44d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 475854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 495854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 50d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 51a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer creation not expected in this test"; 52a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 53a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 55a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 56a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 57a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 58a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 59a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 6098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 61e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 625854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 65a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 66a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 67a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 687cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 6915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 767cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 885854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 935854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 967cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 9715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 9815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1047cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 107b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1085854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 110f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simple) { 111d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 112d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 114d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 115d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 116d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 117d3daa3198e2212c985c634821682d5819346b653Chris Craik } 118d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 119d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 120d3daa3198e2212c985c634821682d5819346b653Chris Craik } 121d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 122d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 123d3daa3198e2212c985c634821682d5819346b653Chris Craik } 124e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 125d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 126d3daa3198e2212c985c634821682d5819346b653Chris Craik } 127d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 128d3daa3198e2212c985c634821682d5819346b653Chris Craik 1298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 1308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 131ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(25, 25); 132b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 10, 10, nullptr); 134b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 135f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1366e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 1375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleTestRenderer renderer; 138f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end 1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 1416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 142f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simpleStroke) { 143386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik class SimpleStrokeTestRenderer : public TestRendererBase { 144386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik public: 145386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik void onPointsOp(const PointsOp& op, const BakedOpState& state) override { 146386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(0, mIndex++); 147386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // even though initial bounds are empty... 148386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_TRUE(op.unmappedBounds.isEmpty()) 149386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "initial bounds should be empty, since they're unstroked"; 150386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(Rect(45, 45, 55, 55), state.computedState.clippedBounds) 151386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "final bounds should account for stroke"; 152386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 153386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }; 154386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 155386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 156386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 157386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPaint strokedPaint; 158386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik strokedPaint.setStrokeWidth(10); 159386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik canvas.drawPoint(50, 50, strokedPaint); 160386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }); 161f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1626e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 163386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 164f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 165386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 166386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 167386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 168f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simpleRejection) { 1698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 171eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 1726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty 1736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 1756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 176f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 1776e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 180f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 183f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simpleBatching) { 184a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 185d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 186d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 187d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 188a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 189d3daa3198e2212c985c634821682d5819346b653Chris Craik } 190d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 191a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 192d3daa3198e2212c985c634821682d5819346b653Chris Craik } 193d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 194d3daa3198e2212c985c634821682d5819346b653Chris Craik 1958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 19715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(10, 10, 19815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik kAlpha_8_SkColorType); // Disable merging by using alpha 8 bitmap 199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 202eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 203a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 5, 0, nullptr); 207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 211f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 2126e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 2135854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 214f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 215a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 21615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 217a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 218a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 219f6c20e4b4232e30901676bcdf1aed64801d50c7eChris CraikTEST(FrameBuilder, clippedMerging) { 22093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 22193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 22293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 22393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 22493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 22593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 22693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 22793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 22893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 22993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 23093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 23193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik auto node = TestUtils::createNode(0, 0, 100, 100, 23293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik [](RenderProperties& props, TestCanvas& canvas) { 23393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik SkBitmap bitmap = TestUtils::createSkBitmap(20, 20); 23493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 23593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 23693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op); 23793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 0, 40, nullptr); 23893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 23993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 24093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op); 24193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 0, nullptr); 24293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 24393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 24493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op); 24593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 80, 40, nullptr); 24693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 24793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 24893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op); 24993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 70, nullptr); 25093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 25193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 252f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 2536e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 25493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 255f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 25693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 25793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 25893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 259f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, textMerging) { 260d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 261d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 262d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 263d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 264d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 265d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 266d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 267d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 268d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 269d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 270d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 271d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 272d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik [](RenderProperties& props, TestCanvas& canvas) { 273d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 274d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 275d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 276d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 277d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 278d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 279d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 280f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 2816e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 282d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 283f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 284d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 285d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 286d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 287f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, textStrikethrough) { 288a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 289a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 290a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 291a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 292a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 293a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 29415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 29515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 29615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 29715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 298a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 299a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 3008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 2000, 3018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 302a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 303a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 304a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 305a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setStrikeThruText(true); 30642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 307a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 308a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TestUtils::drawTextToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 309a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 310a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 311f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, 3126e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 313a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 314f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 315a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 316d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 318b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 319f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer) { 320d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik class TextureLayerTestRenderer : public TestRendererBase { 321d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 322d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 323d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 324e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 325d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 326d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 327d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 328d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 329d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 330d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 331d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 332d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 333d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 334d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [](Matrix4* transform) { 335d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik transform->loadTranslate(5, 5, 0); 336d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 337d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 338d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 339d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 340eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 341d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 342d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 343d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 344d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 345f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 3466e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 347d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik TextureLayerTestRenderer renderer; 348f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 349d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 350d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 351d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 352223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris CraikTEST(FrameBuilder, functor_reject) { 353223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 354223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 355223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 356223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 357223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 358223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 359223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 360223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 361223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 362223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000, 363223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 364223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 365223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.callDrawGLFunction(&noopFunctor); 366223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 367223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 368223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 369223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik TestUtils::createSyncedNodeList(scrolledFunctorView), sLightGeometry, nullptr); 370223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 371223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 372223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 373223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 374223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 375f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderNode) { 376d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 377d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 378d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 379d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 380d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 3815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 382d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 383d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 384d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 385d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 386d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 387d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 388d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 389d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 390d3daa3198e2212c985c634821682d5819346b653Chris Craik } 391d3daa3198e2212c985c634821682d5819346b653Chris Craik } 392d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 393d3daa3198e2212c985c634821682d5819346b653Chris Craik 3948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 3958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 396b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 397b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 398b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 399b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 400b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 402d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 403ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 404ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 405ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 406ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 407eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 408ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 409d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 410ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 411b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 412b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 413f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4146e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 4155854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 416f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 417223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 418b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 419b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 420f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, clipped) { 421d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 422d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 423d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 424d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 425d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 426e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 427d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 428d3daa3198e2212c985c634821682d5819346b653Chris Craik } 429d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 430d3daa3198e2212c985c634821682d5819346b653Chris Craik 4318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 4328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 433ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 434ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 435ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 436ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 437f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, 4380b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver 4396e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 4405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 441f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 442ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 443ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 444f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_simple) { 445d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 446d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 447d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 448d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 449d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 450d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 451d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 452d3daa3198e2212c985c634821682d5819346b653Chris Craik } 453d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 454d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 455d3daa3198e2212c985c634821682d5819346b653Chris Craik } 456d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 457d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 458d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 4595430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 460e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 461d3daa3198e2212c985c634821682d5819346b653Chris Craik 462d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 463d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 464d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 465d3daa3198e2212c985c634821682d5819346b653Chris Craik } 466d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 467d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 468d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 469e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 470d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 471d3daa3198e2212c985c634821682d5819346b653Chris Craik } 472d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 473d3daa3198e2212c985c634821682d5819346b653Chris Craik 4748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 4758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 476eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 4776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 4786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 4796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 480f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4816e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 4825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 483f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 4845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); 485b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 4866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 487f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_nested) { 488d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 489d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 490d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 491d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 492d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 493d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 494d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 495d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 496d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 497d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 498d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 499d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 500d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 501d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 502d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 503d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 504d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 505d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 506d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 507d3daa3198e2212c985c634821682d5819346b653Chris Craik } 508d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 509d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 510d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 511d3daa3198e2212c985c634821682d5819346b653Chris Craik } 51298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 513d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 514d3daa3198e2212c985c634821682d5819346b653Chris Craik } 515e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 516d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 517d3daa3198e2212c985c634821682d5819346b653Chris Craik } 518d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 519d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 520d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 5215430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 522d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 5235430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 524d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 525d3daa3198e2212c985c634821682d5819346b653Chris Craik } 526d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 527d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 528d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 529d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 5305430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 531d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 532d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 5335430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 534d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 535d3daa3198e2212c985c634821682d5819346b653Chris Craik } 536d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 537d3daa3198e2212c985c634821682d5819346b653Chris Craik 5388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 5398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 540eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 5416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 5426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 543eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 5446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 5456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 5466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 5476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5486fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 5496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 5516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 552f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, 5536e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 5545854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 555f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 5565854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(10, renderer.getIndex()); 5576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 5586fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 559f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_contentRejection) { 5608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 5618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 562eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 5636fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 564eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 5656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 5676fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 5686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 572f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5736e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 5746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5755854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 5766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 577f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 578b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 5796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 580f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_simple) { 581b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 582b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 583b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 584b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 585b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 5867435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 587b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 588b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 589b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 590b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 591b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 592b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 593b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 594b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 595b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 596b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 597b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 598b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 599b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 600b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 601b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 602b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 603b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 6047435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 605b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 606b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 607b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 608b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 609b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 610b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 611eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 612b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 613b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 614b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 615f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6166e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 617b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 618f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 619b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 620b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 621b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 622f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 623b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 624b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 625b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 626b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 627b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 628b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 629b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 630b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 631b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 632b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 633b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 634b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 635b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 636b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 637b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 638b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 639b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 640b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 641b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 642b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 643b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 644b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 645b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 646b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 647b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 648b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 649b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 650b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 651b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 652b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 653b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 654b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 655b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 656b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 657b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 658b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 659b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 660eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 661b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 662eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 663eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 664eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 665eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 666b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 667b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 668b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 669f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6706e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 671b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 672f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 673b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 674b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 675b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 676b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 6774876de16e34622634266d09522c9153c78c7c2fbChris CraikTEST(FrameBuilder, saveLayerUnclipped_clearClip) { 6784876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 6794876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 6804876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 6814876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 6824876de16e34622634266d09522c9153c78c7c2fbChris Craik } 6834876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 6844876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 6854876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 6864876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 6874876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 6884876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 6894876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 6904876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 6914876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 6924876de16e34622634266d09522c9153c78c7c2fbChris Craik } 6934876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 6944876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 6954876de16e34622634266d09522c9153c78c7c2fbChris Craik } 6964876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 6974876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 6984876de16e34622634266d09522c9153c78c7c2fbChris Craik } 6994876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 7004876de16e34622634266d09522c9153c78c7c2fbChris Craik 7014876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7024876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 7034876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 7044876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 7054876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 7064876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 7074876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 7084876de16e34622634266d09522c9153c78c7c2fbChris Craik 7094876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 7104876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 7114876de16e34622634266d09522c9153c78c7c2fbChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 7124876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 7134876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7144876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 7154876de16e34622634266d09522c9153c78c7c2fbChris Craik} 7164876de16e34622634266d09522c9153c78c7c2fbChris Craik 7174876de16e34622634266d09522c9153c78c7c2fbChris CraikTEST(FrameBuilder, saveLayerUnclipped_reject) { 7184876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7194876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 7204876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 7214876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 7224876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 7234876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 7244876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 7254876de16e34622634266d09522c9153c78c7c2fbChris Craik 7264876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 7274876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 7284876de16e34622634266d09522c9153c78c7c2fbChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 7294876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 7304876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7314876de16e34622634266d09522c9153c78c7c2fbChris Craik} 7324876de16e34622634266d09522c9153c78c7c2fbChris Craik 733b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 734b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 735b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 736b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 737f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_complex) { 738b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 739b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 740b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 741b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 742b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 743b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 744b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 745b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 746b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 747b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 748b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 749b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 750b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 751b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 752b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 753b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 754b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 755b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 756b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 757b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 758b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 759b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 760b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 761b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 762b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 763b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 764b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 765b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 766b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 767b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 768b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 769b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 770b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 771b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 772b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 773b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 774b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 775b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 776b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 777b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 778b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 779eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 780eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 781eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 782b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 783b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 784b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 785b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 786b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 787f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, 7886e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 789b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 790f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 791b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(12, renderer.getIndex()); 792b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 793b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 794f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 795d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 796d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 79798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 798d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 79998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 80098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 80198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 802d3daa3198e2212c985c634821682d5819346b653Chris Craik } 803d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 804d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 8050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 806d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 807d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 808d3daa3198e2212c985c634821682d5819346b653Chris Craik 809e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 810d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 811d3daa3198e2212c985c634821682d5819346b653Chris Craik } 812d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 813d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 814d3daa3198e2212c985c634821682d5819346b653Chris Craik } 81598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 816d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 817d3daa3198e2212c985c634821682d5819346b653Chris Craik } 818d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 819d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 820d3daa3198e2212c985c634821682d5819346b653Chris Craik } 821e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 822d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 823d3daa3198e2212c985c634821682d5819346b653Chris Craik } 824d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 8250b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 82716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 82816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 8290b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 8300b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 8310b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 83216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 83398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 8340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 83598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 83698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 83798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 8380b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8397db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedNodeList = TestUtils::createSyncedNodeList(node); 8400b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8410b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 84298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 8430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 8440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 845f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 8466e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedNodeList, sLightGeometry, nullptr); 8470b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 848f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 8490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 8500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8510b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 85298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 8530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 8540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 855f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 856d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 857d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 858d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 859d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 860d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 861d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 862d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 863d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 864d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 865d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 866d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 867d3daa3198e2212c985c634821682d5819346b653Chris Craik } 86898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 869d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 870d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 871d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 87298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 87398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 874d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 875d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 87698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 87798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 878d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 879d3daa3198e2212c985c634821682d5819346b653Chris Craik } 880d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 881d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 882d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 883d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 884d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 885d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 886d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 887d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 888d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 889d3daa3198e2212c985c634821682d5819346b653Chris Craik } 890d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 891d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 892d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 893d3daa3198e2212c985c634821682d5819346b653Chris Craik } 89498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 895d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 896d3daa3198e2212c985c634821682d5819346b653Chris Craik } 897d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 89898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 899d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 900d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 90198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 90298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 903d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 904d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 905d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 90698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 90798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 908d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 909d3daa3198e2212c985c634821682d5819346b653Chris Craik } 910e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 911d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 912d3daa3198e2212c985c634821682d5819346b653Chris Craik } 913d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 914d3daa3198e2212c985c634821682d5819346b653Chris Craik 91516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 91616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 91716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9180b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 9200b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 92116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 92298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 92398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 9240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9250b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 92616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 92716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 92816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9290b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9300b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 9310b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 9320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 933eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 9340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 9350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 93616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 93798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 93898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 9390b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9407db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 9410b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 94298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 9430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 9440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 9450b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 946f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 9476e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, sLightGeometry, nullptr); 9480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 949f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 9500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(13, renderer.getIndex()); 9510b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9520b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 9530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 9540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 9550b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 9560b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 957161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 958161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 959161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 960161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 961161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 962161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 96316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 9648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 965161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 966161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 967161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 968161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 969161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 970161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 971f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, zReorder) { 972d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 973d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 974d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 975d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 976d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 977d3daa3198e2212c985c634821682d5819346b653Chris Craik } 978d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 979d3daa3198e2212c985c634821682d5819346b653Chris Craik 98016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 9818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 982161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 983161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 984161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 985161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 986161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 987161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 988161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 989161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 990161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 991161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 992161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 993161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 994161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 995f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 9966e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 997161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 998f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 999161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 1000161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1001161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 1002f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, projectionReorder) { 10038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 10048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 10058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 10068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 10078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 10088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 10098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 10118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 10128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 10138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 10148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 10158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1016678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 10178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 10198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 10208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1021678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1022678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1023678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1024678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 10258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 10278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 10288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 10298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1030678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 10318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 10338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 10348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1035678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 10368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 10378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 10388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 10408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 10418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 10428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 10438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 10448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 10458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 10468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 10478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 10488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 10498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 10508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 10518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 10528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 10538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 10548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 10568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 10578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 10588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 10598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 10608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 10618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 10628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 10638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 10648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 10658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 10668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 10678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 10688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 10698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 10708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 10718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 10728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 10738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 10748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 10758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1076678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1077678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1078678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1079eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 10808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 10818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 10828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 10838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 10848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 10858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1086f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 10876e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 10888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1089f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 10908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 10918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 10928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1093678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1094678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1095678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1096678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1097678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1098678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1099678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1100678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1101678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1102678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1103678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1104678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1105678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1106678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1107678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1108678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1109678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1110678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1111678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1112678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1113678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1114678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1115678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1116678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1117678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1118678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1119678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1120678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1121678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1122678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1123678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1124678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1125678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 1126678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1127678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1128678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1129678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1130678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1131678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1132678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1133678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1134678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1135678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1136678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1137678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1138678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1139678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1140678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1141678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1142678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto child = TestUtils::createNode(100, 100, 300, 300, 1143678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1144678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1145678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1146678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1147678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1148678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1149678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1150678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1151678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1152678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1153678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1154678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1155678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1156678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1157678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1158678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1159678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1160678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1161678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1162678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1163678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1164678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1165678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1166678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto syncedList = TestUtils::createSyncedNodeList(parent); 1167678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1168678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 1169678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 1170678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik syncedList, sLightGeometry, nullptr); 1171678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1172678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1173678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1174678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1175678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1176678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1177678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1178678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1179a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1180a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1181a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1182a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1183a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1184a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1185a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1186a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1187a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1188a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1189a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1190a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1191a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1192a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1193a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1194a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1195a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 1196a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1197a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1198a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1199a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1200a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1201a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1202a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1203a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1204a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1205a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1206a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1207a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1208a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1209a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1210a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1211a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto child = TestUtils::createNode(0, 0, 400, 400, 1212a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1213a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 1214a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op); 1215a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1216a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1217a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1218a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1219a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1220a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1221a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1222a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1223a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1224a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1225a748c08241e43fc68c7c34767d819aef5183936eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 1226a748c08241e43fc68c7c34767d819aef5183936eChris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 1227a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1228a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1229a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1230a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1231a748c08241e43fc68c7c34767d819aef5183936eChris Craik 123298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 123398787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 123416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 12358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 123616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 123716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 123898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 123998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 124098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 124198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 124298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 124398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 12446e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1245d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1246d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1247d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1248d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 124998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 12506e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 12516e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 125298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 125398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 125498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 12556e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1256d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1257d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1258d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1259d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1260d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1261161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 12628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 12638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 126498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 126598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1266d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 126798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1268f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 12696e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, &Caches::getInstance()); 127098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1271f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 127298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 127398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 127498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 12756e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 127698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 127798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 127898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 127998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 128098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 128198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 128298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 128398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 12846e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 12856e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 128698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 128798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 128898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 128998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 129098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 129198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 129298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 129398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 129498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 129598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 129698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 129798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 12988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 12998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 130098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 130198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1302eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1303d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 130498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 130598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 130698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1307d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1308d3daa3198e2212c985c634821682d5819346b653Chris Craik 1309f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13106e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 13116e068c0182f6f85bccb855a647510724d1c65a13Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, 13126e068c0182f6f85bccb855a647510724d1c65a13Chris Craik &Caches::getInstance()); 131398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1314f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 131598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 131698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1317d3daa3198e2212c985c634821682d5819346b653Chris Craik 1318f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 131998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 132098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 132198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 132298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 132398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 132498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 132598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 13266e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 13276e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 13286e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 132998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 133098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 133198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 133298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 133398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 133498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 133598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 133698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 133798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 133898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 133998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1340d3daa3198e2212c985c634821682d5819346b653Chris Craik 13418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 134216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 134316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 134498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1345eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 134698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 134798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 134898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 134916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 135098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 135198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 135298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 135398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 135498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 135598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 135698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 135798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 135898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13597db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 136098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 136198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 1362f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13636e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, 13646e068c0182f6f85bccb855a647510724d1c65a13Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, 13656e068c0182f6f85bccb855a647510724d1c65a13Chris Craik &Caches::getInstance()); 136698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1367f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 136898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 136998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 137098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 137198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1372d3daa3198e2212c985c634821682d5819346b653Chris Craik} 137376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1374f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, shadowLayering) { 137598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 137698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 137798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 137898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 137998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 138098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 138298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 138398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 138498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 13868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 13878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 138898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 138998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 139098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 139198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 139298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1393f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13946e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 13956e068c0182f6f85bccb855a647510724d1c65a13Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, 13966e068c0182f6f85bccb855a647510724d1c65a13Chris Craik &Caches::getInstance()); 139798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1398f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 139998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 140098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 140198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 140216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 140376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1404d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1405d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1406d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1407d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1408d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1409d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1410d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1411d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1412d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1413d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1414d3daa3198e2212c985c634821682d5819346b653Chris Craik 141516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 141616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 141716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 141876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 141976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 142076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 142116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 142276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1423f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 14246e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 142576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1426f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 142776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 142876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 142976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1430f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 143176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 143276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 143376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 143476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 143576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 143676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 143776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 143876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1439f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropClipping) { 144076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 144176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 144276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 144376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 144476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 144576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 144676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 144776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 144876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1449f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropRevealClip) { 145076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 145176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 145276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 145376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 145476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 145576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 145676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 145776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 145876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 145976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1460f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropOutlineClip) { 146176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 146276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 146376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 146476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 146576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 146676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 146776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 146876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 146976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 147076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 147176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1472f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropTransform) { 147376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 147476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 147576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 147676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 147776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 147876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 147976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 148076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 148176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 148276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 148376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 148476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 148576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 148676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 148776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 148876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 148976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 149076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 149176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 149276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 149376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 149476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 149576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 149676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 149776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 149876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 149976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 150076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 150176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 150276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 150376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 1504161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 15058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 15068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 15078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 15088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 15098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 15108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 15118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 15128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 15138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 15148ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 15158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 15168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 15178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 15188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 15198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 15208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 15218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 152216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 15238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 15248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 15258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 15268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 15278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 15298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 15308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 15318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 15328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 15338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 15358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 15368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 15388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 15398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 15418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 15428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 15448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 15458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 15478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 15488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 15498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 15518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 155216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 155316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 15548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 15558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 15568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 155716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 155816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 155916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 156016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 156116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 15628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 15637db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height 15648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15656e068c0182f6f85bccb855a647510724d1c65a13Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 15666e068c0182f6f85bccb855a647510724d1c65a13Chris Craik nodes, sLightGeometry, nullptr); 15678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 1568f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 15698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 15718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 15728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 15738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1574f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 15758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 15768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 15778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 15788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 15798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 15808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 15818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 15825430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 15838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 15848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 15858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 15868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 15878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 15888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 15898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1590f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 15918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 15928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 15938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 15948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 15958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 15968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 15978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 15988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 15998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 16008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 16018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 16038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 16048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 16055430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 16068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 16078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1609f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 16108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 16138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 16148ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 16158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 16168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 16188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 16195430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 16208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 16218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 16246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 1625