FrameBuilderTests.cpp revision dccca44ffda4836b56a21da95a046c9708ffd49c
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); 277dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 278dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 279d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 280f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 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++) { 308dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 309a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 310a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 311f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, 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 3197c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = { 3207c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; 3217c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3227c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris CraikTEST(FrameBuilder, textStyle) { 3237c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik class TextStyleTestRenderer : public TestRendererBase { 3247c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik public: 3257c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 3267c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, mIndex); 3277c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(3u, opList.count); 3287c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik mIndex += opList.count; 3297c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3307c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik int index = 0; 3317c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 3327c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto state = opList.states[index++]; 3337c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(style, state->op->paint->getStyle()) 3347c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Remainder of validation relies upon stable merged order"; 3357c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, state->computedState.clipSideFlags) 3367c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Clipped bounds validation requires unclipped ops"; 3377c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 3387c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3397c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect fill = opList.states[0]->computedState.clippedBounds; 3407c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect stroke = opList.states[1]->computedState.clippedBounds; 3417c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) 3427c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Stroke+Fill should be same as stroke"; 3437c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3447c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_TRUE(stroke.contains(fill)); 3457c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_FALSE(fill.contains(stroke)); 3467c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3477c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect outsetFill(fill); 3487c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik outsetFill.outset(10); 3497c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, outsetFill); 3507c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 3517c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }; 3527c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 3537c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik [](RenderProperties& props, TestCanvas& canvas) { 3547c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint paint; 3557c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 3567c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setAntiAlias(true); 3577c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextSize(50); 3587c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStrokeWidth(10); 3597c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 3607c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // draw 3 copies of the same text overlapping, each with a different style. 3617c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // They'll get merged, but with 3627c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 3637c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStyle(style); 364dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 3657c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 3667c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }); 3677c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 3687c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 3697c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TextStyleTestRenderer renderer; 3707c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3717c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; 3727c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik} 3737c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 374f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer) { 375d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik class TextureLayerTestRenderer : public TestRendererBase { 376d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 377d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 378d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 379e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 380d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 381d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 382d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 383d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 384d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 385d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 386d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 387d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 388d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 389d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [](Matrix4* transform) { 390d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik transform->loadTranslate(5, 5, 0); 391d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 392d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 393d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 394d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 395eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 396d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 397d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 398d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 399d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 400f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4016e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 402d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik TextureLayerTestRenderer renderer; 403f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 404d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 405d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 406d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 407223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris CraikTEST(FrameBuilder, functor_reject) { 408223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 409223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 410223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 411223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 412223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 413223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 414223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 415223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 416223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 417223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000, 418223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 419223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 420223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.callDrawGLFunction(&noopFunctor); 421223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 422223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 423223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 424223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik TestUtils::createSyncedNodeList(scrolledFunctorView), sLightGeometry, nullptr); 425223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 426223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 427223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 428223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 429223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 430f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderNode) { 431d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 432d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 433d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 434d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 435d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 4365430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 437d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 438d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 439d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 440d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 441d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 442d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 443d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 444d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 445d3daa3198e2212c985c634821682d5819346b653Chris Craik } 446d3daa3198e2212c985c634821682d5819346b653Chris Craik } 447d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 448d3daa3198e2212c985c634821682d5819346b653Chris Craik 4498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 4508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 451b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 452b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 453b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 454b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 455b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 457d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 458ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 459ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 460ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 461ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 462eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 463ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 464d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 465ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 466b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 467b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 468f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4696e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 4705854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 471f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 472223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 473b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 474b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 475f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, clipped) { 476d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 477d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 478d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 479d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 480d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 481e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 482d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 483d3daa3198e2212c985c634821682d5819346b653Chris Craik } 484d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 485d3daa3198e2212c985c634821682d5819346b653Chris Craik 4868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 4878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 488ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 489ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 490ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 491ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 492f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, 4930b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver 4946e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 4955854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 496f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 497ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 498ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 499f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_simple) { 500d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 501d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 502d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 503d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 504d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 505d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 506d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 507d3daa3198e2212c985c634821682d5819346b653Chris Craik } 508d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 509d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 510d3daa3198e2212c985c634821682d5819346b653Chris Craik } 511d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 512d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 513d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 5145430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 515e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 516d3daa3198e2212c985c634821682d5819346b653Chris Craik 517d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 518d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 519d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 520d3daa3198e2212c985c634821682d5819346b653Chris Craik } 521d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 522d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 523d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 524e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 525d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 526d3daa3198e2212c985c634821682d5819346b653Chris Craik } 527d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 528d3daa3198e2212c985c634821682d5819346b653Chris Craik 5298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 5308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 531eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 5326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 5336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 535f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5366e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 5375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 538f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 5395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); 540b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 5416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 542f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_nested) { 543d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 544d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 545d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 546d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 547d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 548d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 549d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 550d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 551d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 552d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 553d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 554d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 555d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 556d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 557d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 558d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 559d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 560d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 561d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 562d3daa3198e2212c985c634821682d5819346b653Chris Craik } 563d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 564d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 565d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 566d3daa3198e2212c985c634821682d5819346b653Chris Craik } 56798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 568d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 569d3daa3198e2212c985c634821682d5819346b653Chris Craik } 570e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 571d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 572d3daa3198e2212c985c634821682d5819346b653Chris Craik } 573d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 574d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 575d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 5765430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 577d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 5785430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 579d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 580d3daa3198e2212c985c634821682d5819346b653Chris Craik } 581d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 582d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 583d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 584d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 5855430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 586d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 587d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 5885430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 589d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 590d3daa3198e2212c985c634821682d5819346b653Chris Craik } 591d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 592d3daa3198e2212c985c634821682d5819346b653Chris Craik 5938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 5948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 595eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 5966fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 5976fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 598eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 5996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 6006fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 6016fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 6026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 6046fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 6066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 607f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, 6086e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 6095854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 610f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 6115854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(10, renderer.getIndex()); 6126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 6136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 614f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_contentRejection) { 6158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 6168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 617eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 6186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 619eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 6206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 6226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 6236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 6266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 627f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6286e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 6296fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 6305854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 6316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 632f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 633b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 6346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 635f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_simple) { 636b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 637b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 638b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 639b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 640b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 6417435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 642b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 643b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 644b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 645b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 646b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 647b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 648b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 649b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 650b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 651b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 652b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 653b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 654b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 655b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 656b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 657b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 658b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 6597435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 660b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 661b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 662b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 663b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 664b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 665b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 666eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 667b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 668b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 669b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 670f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6716e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 672b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 673f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 674b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 675b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 676b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 677f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 678b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 679b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 680b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 681b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 682b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 683b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 684b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 685b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 686b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 687b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 688b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 689b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 690b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 691b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 692b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 693b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 694b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 695b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 696b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 697b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 698b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 699b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 700b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 701b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 702b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 703b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 704b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 705b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 706b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 707b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 708b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 709b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 710b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 711b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 712b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 713b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 714b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 715eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 716b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 717eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 718eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 719eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 720eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 721b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 722b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 723b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 724f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 7256e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 726b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 727f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 728b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 729b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 730b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 731b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 7324876de16e34622634266d09522c9153c78c7c2fbChris CraikTEST(FrameBuilder, saveLayerUnclipped_clearClip) { 7334876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 7344876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 7354876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 7364876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 7374876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7384876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 7394876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 7404876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 7414876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 7424876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 7434876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 7444876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 7454876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 7464876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 7474876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7484876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 7494876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 7504876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7514876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 7524876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 7534876de16e34622634266d09522c9153c78c7c2fbChris Craik } 7544876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 7554876de16e34622634266d09522c9153c78c7c2fbChris Craik 7564876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7574876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 7584876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 7594876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 7604876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 7614876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 7624876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 7634876de16e34622634266d09522c9153c78c7c2fbChris Craik 7644876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 7654876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 7664876de16e34622634266d09522c9153c78c7c2fbChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 7674876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 7684876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7694876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 7704876de16e34622634266d09522c9153c78c7c2fbChris Craik} 7714876de16e34622634266d09522c9153c78c7c2fbChris Craik 7724876de16e34622634266d09522c9153c78c7c2fbChris CraikTEST(FrameBuilder, saveLayerUnclipped_reject) { 7734876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7744876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 7754876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 7764876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 7774876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 7784876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 7794876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 7804876de16e34622634266d09522c9153c78c7c2fbChris Craik 7814876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 7824876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 7834876de16e34622634266d09522c9153c78c7c2fbChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 7844876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 7854876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7864876de16e34622634266d09522c9153c78c7c2fbChris Craik} 7874876de16e34622634266d09522c9153c78c7c2fbChris Craik 788b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 789b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 790b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 791b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 792f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_complex) { 793b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 794b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 795b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 796b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 797b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 798b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 799b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 800b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 801b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 802b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 803b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 804b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 805b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 806b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 807b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 808b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 809b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 810b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 811b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 812b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 813b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 814b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 815b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 816b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 817b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 818b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 819b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 820b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 821b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 822b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 823b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 824b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 825b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 826b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 827b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 828b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 829b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 830b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 831b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 832b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 833b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 834eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 835eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 836eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 837b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 838b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 839b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 840b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 841b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 842f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, 8436e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 844b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 845f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 846b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(12, renderer.getIndex()); 847b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 848b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 849f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 850d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 851d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 85298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 853d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 85498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 85598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 85698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 857d3daa3198e2212c985c634821682d5819346b653Chris Craik } 858d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 859d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 8600b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 861d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 862d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 863d3daa3198e2212c985c634821682d5819346b653Chris Craik 864e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 865d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 866d3daa3198e2212c985c634821682d5819346b653Chris Craik } 867d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 868d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 869d3daa3198e2212c985c634821682d5819346b653Chris Craik } 87098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 871d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 872d3daa3198e2212c985c634821682d5819346b653Chris Craik } 873d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 874d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 875d3daa3198e2212c985c634821682d5819346b653Chris Craik } 876e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 877d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 878d3daa3198e2212c985c634821682d5819346b653Chris Craik } 879d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 8800b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 88216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 88316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 8840b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 8850b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 8860b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 88716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 88898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 8890b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 89098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 89198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 89298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 8930b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8947db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedNodeList = TestUtils::createSyncedNodeList(node); 8950b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 89798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 8980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 8990b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 900f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 9016e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedNodeList, sLightGeometry, nullptr); 9020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 903f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 9040b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 9050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 90798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 9080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 9090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 910f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 911d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 912d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 913d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 914d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 915d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 916d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 917d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 918d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 919d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 920d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 921d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 922d3daa3198e2212c985c634821682d5819346b653Chris Craik } 92398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 924d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 925d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 926d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 92798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 92898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 929d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 930d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 93198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 93298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 933d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 934d3daa3198e2212c985c634821682d5819346b653Chris Craik } 935d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 936d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 937d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 938d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 939d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 940d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 941d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 942d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 943d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 944d3daa3198e2212c985c634821682d5819346b653Chris Craik } 945d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 946d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 947d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 948d3daa3198e2212c985c634821682d5819346b653Chris Craik } 94998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 950d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 951d3daa3198e2212c985c634821682d5819346b653Chris Craik } 952d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 95398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 954d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 955d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 95698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 95798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 958d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 959d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 960d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 96198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 96298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 963d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 964d3daa3198e2212c985c634821682d5819346b653Chris Craik } 965e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 966d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 967d3daa3198e2212c985c634821682d5819346b653Chris Craik } 968d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 969d3daa3198e2212c985c634821682d5819346b653Chris Craik 97016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 97116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 97216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 9750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 97616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 97798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 97898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 9790b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9800b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 98116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 98216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 98316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 9840b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 9850b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 9860b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 9870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 988eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 9890b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 9900b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 99116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 99298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 99398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 9940b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 9957db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 9960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 99798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 9980b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 9990b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 10000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1001f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 10026e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, sLightGeometry, nullptr); 10030b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1004f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 10050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(13, renderer.getIndex()); 10060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 10070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 10080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 10090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 10100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 10110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1012161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 1013161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1014161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 1015161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1016161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1017161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 101816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 10198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1020161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1021161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1022161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1023161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1024161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1025161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1026f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, zReorder) { 1027d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 1028d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1029d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1030d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1031d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1032d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1033d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1034d3daa3198e2212c985c634821682d5819346b653Chris Craik 103516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 10368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1037161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1038161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1039161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1040161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1041161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1042161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1043161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1044161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1045161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1046161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1047161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1048161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 1049161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1050f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 10516e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 1052161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1053f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1054161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 1055161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1056161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 1057f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, projectionReorder) { 10588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 10598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 10608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 10618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 10628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 10638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 10648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 10668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 10678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 10688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 10698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 10708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1071678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 10728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 10748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 10758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1076678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1077678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1078678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1079678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 10808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 10828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 10838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 10848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1085678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 10868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 10878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 10888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 10898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1090678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 10918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 10928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 10938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 10948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 10958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 10968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 10978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 10988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 10998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 11008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 11018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 11028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 11038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 11048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 11058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 11068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 11078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 11088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 11098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 11108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 11128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 11138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 11158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 11168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 11178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 11188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 11208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 11218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 11238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 11248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 11258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 11268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 11278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 11288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 11308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1131678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1132678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1133678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1134eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 11358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 11368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 11378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 11388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 11398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 11408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1141f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 11426e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 11438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1144f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 11468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 11478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1148678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1149678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1150678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1151678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1152678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1153678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1154678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1155678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1156678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1157678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1158678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1159678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1160678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1161678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1162678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1163678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1164678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1165678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1166678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1167678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1168678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1169678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1170678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1171678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1172678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1173678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1174678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1175678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1176678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1177678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1178678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1179678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1180678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 1181678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1182678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1183678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1184678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1185678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1186678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1187678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1188678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1189678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1190678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1191678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1192678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1193678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1194678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1195678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1196678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1197678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto child = TestUtils::createNode(100, 100, 300, 300, 1198678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1199678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1200678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1201678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1202678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1203678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1204678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1205678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1206678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1207678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1208678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1209678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1210678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1211678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1212678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1213678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1214678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1215678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1216678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1217678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1218678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1219678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1220678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1221678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto syncedList = TestUtils::createSyncedNodeList(parent); 1222678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1223678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 1224678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 1225678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik syncedList, sLightGeometry, nullptr); 1226678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1227678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1228678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1229678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1230678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1231678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1232678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1233678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1234a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1235a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1236a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1237a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1238a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1239a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1240a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1241a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1242a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1243a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1244a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1245a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1246a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1247a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1248a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1249a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1250a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 1251a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1252a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1253a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1254a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1255a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1256a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1257a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1258a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1259a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1260a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1261a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1262a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1263a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1264a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1265a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1266a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto child = TestUtils::createNode(0, 0, 400, 400, 1267a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1268a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 1269a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op); 1270a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1271a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1272a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1273a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1274a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1275a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1276a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1277a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1278a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1279a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1280a748c08241e43fc68c7c34767d819aef5183936eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 1281a748c08241e43fc68c7c34767d819aef5183936eChris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr); 1282a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1283a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1284a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1285a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1286a748c08241e43fc68c7c34767d819aef5183936eChris Craik 128798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 128898787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 128916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 12908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 129116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 129216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 129398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 129498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 129598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 129698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 129798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 129898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 12996e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1300d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1301d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1302d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1303d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 130498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 13056e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 13066e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 130798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 130898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 130998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 13106e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1311d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1312d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1313d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1314d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1315d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1316161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 13178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 13188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 131998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 132098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1321d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 132298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1323f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13246e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, &Caches::getInstance()); 132598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1326f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 132798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 132898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 132998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13306e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 133198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 133298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 133398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 133498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 133598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 133698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 133798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 133898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 13396e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 13406e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 134198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 134298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 134398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 134498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 134598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 134698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 134798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 134898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 134998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 135098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 135198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 135298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 13538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 13548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 135598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 135698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1357eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1358d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 135998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 136098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 136198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1362d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1363d3daa3198e2212c985c634821682d5819346b653Chris Craik 1364f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 13656e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 13666e068c0182f6f85bccb855a647510724d1c65a13Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, 13676e068c0182f6f85bccb855a647510724d1c65a13Chris Craik &Caches::getInstance()); 136898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1369f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 137098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 137198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1372d3daa3198e2212c985c634821682d5819346b653Chris Craik 1373f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 137498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 137598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 137698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 137798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 137898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 137998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 138098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 13816e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 13826e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 13836e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 138498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 138698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 138798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 138898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 138998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 139098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 139198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 139298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 139398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 139498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1395d3daa3198e2212c985c634821682d5819346b653Chris Craik 13968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 139716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 139816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 139998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1400eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 140198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 140298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 140398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 140416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 140598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 140698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 140798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 140898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 140998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 141098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 141198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 141298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 141398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 14147db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 141598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 141698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 1417f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 14186e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, 14196e068c0182f6f85bccb855a647510724d1c65a13Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, 14206e068c0182f6f85bccb855a647510724d1c65a13Chris Craik &Caches::getInstance()); 142198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1422f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 142398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 142498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 142598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 142698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1427d3daa3198e2212c985c634821682d5819346b653Chris Craik} 142876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1429f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, shadowLayering) { 143098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 143198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 143298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 143398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 143498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 143598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 143698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 143798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 143898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 143998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 144098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 14418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 14428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 144398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 144498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 144598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 144698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 144798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1448f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 14496e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 14506e068c0182f6f85bccb855a647510724d1c65a13Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, 14516e068c0182f6f85bccb855a647510724d1c65a13Chris Craik &Caches::getInstance()); 145298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1453f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 145498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 145598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 145698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 145716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 145876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1459d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1460d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1461d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1462d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1463d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1464d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1465d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1466d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1467d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1468d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1469d3daa3198e2212c985c634821682d5819346b653Chris Craik 147016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 147116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 147216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 147376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 147476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 147576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 147616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 147776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1478f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 14796e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr); 148076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1481f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 148276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 148376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 148476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1485f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 148676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 148776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 148876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 148976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 149076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 149176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 149276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 149376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1494f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropClipping) { 149576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 149676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 149776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 149876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 149976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 150076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 150176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 150276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 150376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1504f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropRevealClip) { 150576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 150676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 150776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 150876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 150976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 151076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 151176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 151276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 151376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 151476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1515f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropOutlineClip) { 151676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 151776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 151876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 151976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 152076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 152176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 152276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 152376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 152476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 152576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 152676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1527f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropTransform) { 152876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 152976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 153076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 153176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 153276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 153376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 153476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 153576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 153676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 153776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 153876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 153976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 154076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 154176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 154276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 154376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 154476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 154576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 154676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 154776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 154876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 154976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 155076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 155176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 155276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 155376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 155476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 155576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 155676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 155776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 155876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 1559161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 15608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 15618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 15628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 15638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 15648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 15658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 15668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 15678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 15688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 15698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 15708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 15718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 15728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 15738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 15748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 15758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 15768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 157716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 15788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 15798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 15808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 15818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 15828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 15848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 15858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 15868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 15878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 15888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 15908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 15918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 15928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 15938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 15948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 15968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 15978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 15988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 15998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 16008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 16018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 16028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 16038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 16048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 16068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 160716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 160816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 16098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 16108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 16118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 161216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 161316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 161416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 161516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 161616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 16178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16187db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height 16198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16206e068c0182f6f85bccb855a647510724d1c65a13Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 16216e068c0182f6f85bccb855a647510724d1c65a13Chris Craik nodes, sLightGeometry, nullptr); 16228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 1623f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 16248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 16268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 16278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1629f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 16308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 16338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 16348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 16368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 16375430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 16388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 16398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 16408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 16418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 16428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 16438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1645f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 16468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 16498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 16508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 16518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 16528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 16538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 16548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 16558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 16568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 16588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 16598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 16605430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 16618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 16628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1664f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 16658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 16668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 16678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 16688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 16698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 16708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 16718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 16728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 16738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 16745430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 16758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 16768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 16778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 16786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 16796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 1680