FrameBuilderTests.cpp revision 7db5ffb7dbd30202468459e2ef4426e91d4fcbb3
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; 338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikconst Vector3 sLightCenter = {100, 100, 100}; 3498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 365854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 43d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 465854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 485854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 49d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 50a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer creation not expected in this test"; 51a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 52a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 54a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 55a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 56a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 57a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 58a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 60e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 615854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 64a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 65a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 66a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 677cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 6815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 6915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 757cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 785854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 795854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 805854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 875854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 885854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 925854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 935854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 946fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 957cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 9615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 9715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 9815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1037cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 106b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1075854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 109f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simple) { 110d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 111d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 113d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 114d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 115d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 116d3daa3198e2212c985c634821682d5819346b653Chris Craik } 117d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 118d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 119d3daa3198e2212c985c634821682d5819346b653Chris Craik } 120d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 121d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 122d3daa3198e2212c985c634821682d5819346b653Chris Craik } 123e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 124d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 125d3daa3198e2212c985c634821682d5819346b653Chris Craik } 126d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 127d3daa3198e2212c985c634821682d5819346b653Chris Craik 1288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 1298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 130ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(25, 25); 131b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 132b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 10, 10, nullptr); 133b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 134f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1357db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 1365854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleTestRenderer renderer; 137f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end 1396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 1406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 141f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simpleStroke) { 142386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik class SimpleStrokeTestRenderer : public TestRendererBase { 143386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik public: 144386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik void onPointsOp(const PointsOp& op, const BakedOpState& state) override { 145386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(0, mIndex++); 146386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // even though initial bounds are empty... 147386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_TRUE(op.unmappedBounds.isEmpty()) 148386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "initial bounds should be empty, since they're unstroked"; 149386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(Rect(45, 45, 55, 55), state.computedState.clippedBounds) 150386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "final bounds should account for stroke"; 151386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 152386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }; 153386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 154386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 155386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 156386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPaint strokedPaint; 157386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik strokedPaint.setStrokeWidth(10); 158386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik canvas.drawPoint(50, 50, strokedPaint); 159386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }); 160f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1617db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 162386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 163f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 164386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 165386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 166386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 167f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simpleRejection) { 1688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1706fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 1716fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty 1726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 1746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 175f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 1767db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1785854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 179f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 181b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 182f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, simpleBatching) { 183a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 184d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 185d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 186d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 187a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 188d3daa3198e2212c985c634821682d5819346b653Chris Craik } 189d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 190a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 191d3daa3198e2212c985c634821682d5819346b653Chris Craik } 192d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 193d3daa3198e2212c985c634821682d5819346b653Chris Craik 1948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 19615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(10, 10, 19715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik kAlpha_8_SkColorType); // Disable merging by using alpha 8 bitmap 198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 200b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 201b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 202a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 5, 0, nullptr); 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 210f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 2117db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 2125854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 213f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 214a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 21515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 216a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 217a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 218f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, clippedMerging) { 21993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 22093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 22193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 22293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 22393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 22493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 22593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 22693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 22793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 22893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 22993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 23093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik auto node = TestUtils::createNode(0, 0, 100, 100, 23193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik [](RenderProperties& props, TestCanvas& canvas) { 23293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik SkBitmap bitmap = TestUtils::createSkBitmap(20, 20); 23393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 23493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 23593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op); 23693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 0, 40, nullptr); 23793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 23893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 23993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op); 24093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 0, nullptr); 24193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 24293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 24393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op); 24493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 80, 40, nullptr); 24593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 24693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 24793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op); 24893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 70, nullptr); 24993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 25093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 251f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 2527db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 25393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 254f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 25593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 25693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 25793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 258f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, textMerging) { 259d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 260d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 261d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 262d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 263d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 264d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 265d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 266d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 267d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 268d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 269d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 270d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 271d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik [](RenderProperties& props, TestCanvas& canvas) { 272d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 273d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 274d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 275d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 276d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 277d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 278d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 279f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 2807db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 281d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 282f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 283d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 284d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 285d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 286f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, textStrikethrough) { 287a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 288a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 289a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 290a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 291a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 292a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 29315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 29415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 29515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 29615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 297a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 298a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 2998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 2000, 3008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 301a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 302a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 303a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 304a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setStrikeThruText(true); 30542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 306a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 307a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TestUtils::drawTextToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 308a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 309a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 310f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, 3117db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 312a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 313f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 314a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 315d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 316b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 317b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 318f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer) { 319d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik class TextureLayerTestRenderer : public TestRendererBase { 320d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 321d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 322d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 323e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 324d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 325d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 326d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 327d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 328d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 329d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 330d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 331d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 332d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 333d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [](Matrix4* transform) { 334d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik transform->loadTranslate(5, 5, 0); 335d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 336d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 337d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 338d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 339d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.save(SkCanvas::kMatrixClip_SaveFlag); 340d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 341d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 342d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 343d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 344f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 3457db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 346d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik TextureLayerTestRenderer renderer; 347f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 348d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 349d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 350d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 351f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderNode) { 352d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 353d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 354d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 355d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 356d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 3575430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 358d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 359d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 360d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 361d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 362d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 363d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 364d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 365d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 366d3daa3198e2212c985c634821682d5819346b653Chris Craik } 367d3daa3198e2212c985c634821682d5819346b653Chris Craik } 368d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 369d3daa3198e2212c985c634821682d5819346b653Chris Craik 3708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 3718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 372b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 373b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 374b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 375b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 376b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 3778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 378d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 379ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 380ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 381ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 382ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 383ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 384ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 385d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 386ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 387b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 388b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 389f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 3907db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(parent), sLightCenter); 3915854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 392f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 393b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 394b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 395f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, clipped) { 396d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 397d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 398d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 399d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 400d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 401e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 402d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 403d3daa3198e2212c985c634821682d5819346b653Chris Craik } 404d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 405d3daa3198e2212c985c634821682d5819346b653Chris Craik 4068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 4078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 408ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 409ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 410ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 411ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 412f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, 4130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver 4147db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck 200, 200, TestUtils::createSyncedNodeList(node), sLightCenter); 4155854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 416f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 417ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 418ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 419f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_simple) { 420d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 421d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 422d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 423d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 424d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 425d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 426d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 427d3daa3198e2212c985c634821682d5819346b653Chris Craik } 428d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 429d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 430d3daa3198e2212c985c634821682d5819346b653Chris Craik } 431d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 432d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 433d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 4345430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 435e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 436d3daa3198e2212c985c634821682d5819346b653Chris Craik 437d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 438d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 439d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 440d3daa3198e2212c985c634821682d5819346b653Chris Craik } 441d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 442d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 443d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 444e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 445d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 446d3daa3198e2212c985c634821682d5819346b653Chris Craik } 447d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 448d3daa3198e2212c985c634821682d5819346b653Chris Craik 4498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 4508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 4516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, SkCanvas::kClipToLayer_SaveFlag); 4526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 4536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 4546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 455f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 4567db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 4575854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 458f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 4595854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); 460b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 4616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 462f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_nested) { 463d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 464d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 465d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 466d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 467d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 468d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 469d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 470d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 471d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 472d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 473d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 474d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 475d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 476d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 477d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 478d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 479d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 480d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 481d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 482d3daa3198e2212c985c634821682d5819346b653Chris Craik } 483d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 484d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 485d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 486d3daa3198e2212c985c634821682d5819346b653Chris Craik } 48798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 488d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 489d3daa3198e2212c985c634821682d5819346b653Chris Craik } 490e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 491d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 492d3daa3198e2212c985c634821682d5819346b653Chris Craik } 493d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 494d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 495d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 4965430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 497d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 4985430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 499d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 500d3daa3198e2212c985c634821682d5819346b653Chris Craik } 501d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 502d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 503d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 504d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 5055430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 506d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 507d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 5085430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 509d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 510d3daa3198e2212c985c634821682d5819346b653Chris Craik } 511d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 512d3daa3198e2212c985c634821682d5819346b653Chris Craik 5138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 5148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 5156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.saveLayerAlpha(0, 0, 800, 800, 128, SkCanvas::kClipToLayer_SaveFlag); 5166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 5176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 5186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.saveLayerAlpha(0, 0, 400, 400, 128, SkCanvas::kClipToLayer_SaveFlag); 5196fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 5206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 5216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 5226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 5246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 5266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 527f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, 5287db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 5295854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 530f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 5315854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(10, renderer.getIndex()); 5326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 5336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 534f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayer_contentRejection) { 5358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 5368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 5376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 5386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 5396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.saveLayerAlpha(200, 200, 400, 400, 128, SkCanvas::kClipToLayer_SaveFlag); 5406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 5426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 5436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 5466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 547f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5487db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 5496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 5505854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 5516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 552f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 553b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 5546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 555f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_simple) { 556b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 557b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 558b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 559b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 560b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 5617435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 562b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 563b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 564b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 565b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 566b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 567b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 568b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 569b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 570b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 571b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 572b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 573b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 574b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 575b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 576b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 577b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 578b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 5797435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 580b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 581b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 582b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 583b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 584b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 585b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 5867db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SkCanvas::SaveFlags)(0)); 587b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 588b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 589b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 590f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5917db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 592b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 593f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 594b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 595b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 596b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 597f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 598b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 599b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 600b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 601b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 602b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 603b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 604b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 605b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 606b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 607b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 608b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 609b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 610b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 611b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 612b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 613b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 614b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 615b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 616b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 617b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 618b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 619b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 620b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 621b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 622b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 623b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 624b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 625b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 626b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 627b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 628b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 629b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 630b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 631b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 632b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 633b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 634b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 635b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int restoreTo = canvas.save(SkCanvas::kMatrixClip_SaveFlag); 636b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 637b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(0, 0, 5, 5, 128, SkCanvas::kMatrixClip_SaveFlag); 638b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(95, 0, 100, 5, 128, SkCanvas::kMatrixClip_SaveFlag); 639b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(0, 95, 5, 100, 128, SkCanvas::kMatrixClip_SaveFlag); 640b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(95, 95, 100, 100, 128, SkCanvas::kMatrixClip_SaveFlag); 641b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 642b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 643b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 644f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6457db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 646b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 647f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 648b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 649b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 650b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 651b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 652b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 653b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 654b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 655b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 656f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, saveLayerUnclipped_complex) { 657b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 658b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 659b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 660b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 661b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 662b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 663b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 664b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 665b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 666b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 667b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 668b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 669b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 670b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 671b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 672b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 673b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 674b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 675b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 676b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 677b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 678b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 679b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 680b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 681b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 682b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 683b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 684b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 685b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 686b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 687b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 688b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 689b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 690b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 691b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 692b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 693b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 694b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 695b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 696b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 697b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 698b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SkCanvas::SaveFlags)0); // unclipped 699b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(100, 100, 400, 400, 128, SkCanvas::kClipToLayer_SaveFlag); // clipped 700b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SkCanvas::SaveFlags)0); // unclipped 701b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 702b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 703b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 704b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 705b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 706f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, 7077db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 708b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 709f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 710b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(12, renderer.getIndex()); 711b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 712b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 713f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 714d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 715d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 71698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 717d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 71898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 71998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 72098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 721d3daa3198e2212c985c634821682d5819346b653Chris Craik } 722d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 723d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 7240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 725d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 726d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 727d3daa3198e2212c985c634821682d5819346b653Chris Craik 728e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 729d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 730d3daa3198e2212c985c634821682d5819346b653Chris Craik } 731d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 732d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 733d3daa3198e2212c985c634821682d5819346b653Chris Craik } 73498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 735d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 736d3daa3198e2212c985c634821682d5819346b653Chris Craik } 737d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 738d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 739d3daa3198e2212c985c634821682d5819346b653Chris Craik } 740e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 741d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 742d3daa3198e2212c985c634821682d5819346b653Chris Craik } 743d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 7440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 7458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 74616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 74716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 7480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 7490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 7500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 75116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 75298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 7530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 75498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 75598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 75698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 7570b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 7587db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedNodeList = TestUtils::createSyncedNodeList(node); 7590b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 7600b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 76198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 7620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 7630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 764f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 76598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik syncedNodeList, sLightCenter); 7660b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 767f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 7680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 7690b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 7700b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 77198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 7720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 7730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 774f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 775d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 776d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 777d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 778d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 779d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 780d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 781d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 782d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 783d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 784d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 785d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 786d3daa3198e2212c985c634821682d5819346b653Chris Craik } 78798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 788d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 789d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 790d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 79198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 79298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 793d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 794d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 79598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 79698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 797d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 798d3daa3198e2212c985c634821682d5819346b653Chris Craik } 799d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 800d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 801d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 802d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 803d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 804d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 805d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 806d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 807d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 808d3daa3198e2212c985c634821682d5819346b653Chris Craik } 809d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 810d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 811d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 812d3daa3198e2212c985c634821682d5819346b653Chris Craik } 81398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 814d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 815d3daa3198e2212c985c634821682d5819346b653Chris Craik } 816d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 81798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 818d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 819d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 82098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 82198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 822d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 823d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 824d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 82598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 82698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 827d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 828d3daa3198e2212c985c634821682d5819346b653Chris Craik } 829e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 830d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 831d3daa3198e2212c985c634821682d5819346b653Chris Craik } 832d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 833d3daa3198e2212c985c634821682d5819346b653Chris Craik 83416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 83516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 83616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 8370b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 8380b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 8390b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 84016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 84198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 84298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 8430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 84516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 84616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 84716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 8480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 8490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 8500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 8510b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8520b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.saveLayerAlpha(50, 50, 150, 150, 128, SkCanvas::kClipToLayer_SaveFlag); 8530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 8540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 85516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 85698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 85798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 8580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8597db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 8600b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 86198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 8620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 8630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 8640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 865f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 86698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik syncedList, sLightCenter); 8670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 868f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 8690b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(13, renderer.getIndex()); 8700b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 8710b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 8720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 8730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 8740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 8750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 876161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 877161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 878161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 879161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 880161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 881161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 88216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 8838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 884161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 885161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 886161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 887161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 888161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 889161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 890f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, zReorder) { 891d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 892d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 893d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 894d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 895d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 896d3daa3198e2212c985c634821682d5819346b653Chris Craik } 897d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 898d3daa3198e2212c985c634821682d5819346b653Chris Craik 89916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 9008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 901161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 902161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 903161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 904161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 905161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 906161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 907161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 908161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 909161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 910161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 911161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 912161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 913161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 914f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 9157db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(parent), sLightCenter); 916161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 917f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 918161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 919161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 920161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 921f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, projectionReorder) { 9228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 9238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 9248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 9258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 9268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 9278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 9288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 9298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 9308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 9318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 9328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 9338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 9348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 9358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 9368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 9378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 9388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 9398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(50, 50, 0); // TODO: should scroll be respected here? 9408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 9418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 9428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 9438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 9448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 9458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 9468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 9478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 9488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 9498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedMatrix, state.computedState.transform); 9508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 9518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 9528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 9538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 9548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 9558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 9568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 9578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 9588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 9598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 9608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 9618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 9628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 9638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 9648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 9658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 9668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 9678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 9688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 9698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 9708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 9718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 9728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 9738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 9748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 9758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 9768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 9778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 9788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 9798d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 9808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 9818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 9828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 9838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 9848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 9858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 9868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 9878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 9888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 9898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 9908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 9918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 9928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 9938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 9948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 9958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 9968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 997f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 9987db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(parent), sLightCenter); 9998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1000f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 10018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 10028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 10038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 100498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 100598787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 100616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 10078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 100816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 100916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 101098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 101198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 101298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 101398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 101498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 101598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1016f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, shadow) { 1017d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1018d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1019d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1020d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 102198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 102298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(op.casterPath->isRect(nullptr)); 102398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowMatrixXY); 102498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 102598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 102698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 102798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowMatrixZ); 1028d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1029d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1030d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1031d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1032d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1033161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 10348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 10358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 103698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 103798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1038d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 103998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1040f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 10417db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(parent), sLightCenter); 104298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1043f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 104498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 104598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 104698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1047f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, shadowSaveLayer) { 104898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 104998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 105098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 105198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 105298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 105398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 105498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 105598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 105698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(50, op.lightCenter.x); 105798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(40, op.lightCenter.y); 105898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 105998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 106098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 106198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 106298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 106398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 106498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 106598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 106698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 106798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 106898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 106998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 10708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 10718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 107298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 107398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 107498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SkCanvas::kClipToLayer_SaveFlag); 1075d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 107698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 107798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 107898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1079d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1080d3daa3198e2212c985c634821682d5819346b653Chris Craik 1081f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 10827db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(parent), (Vector3) { 100, 100, 100 }); 108398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1084f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 108598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 108698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1087d3daa3198e2212c985c634821682d5819346b653Chris Craik 1088f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 108998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 109098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 109198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 109298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 109398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 109498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 109598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 109698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(50, op.lightCenter.x); 109798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(40, op.lightCenter.y); 109898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 109998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 110098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 110198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 110298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 110398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 110498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 110598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 110698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 110798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 110898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1109d3daa3198e2212c985c634821682d5819346b653Chris Craik 11108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 111116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 111216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 111398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 111498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag); 111598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 111698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 111798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 111816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 111998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 112098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 112198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 112298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 112398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 112498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 112598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 112698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 112798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 11287db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 112998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 113098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 1131f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 113298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik syncedList, (Vector3) { 100, 100, 100 }); 113398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1134f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 113598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 113698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 113798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 113898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1139d3daa3198e2212c985c634821682d5819346b653Chris Craik} 114076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1141f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, shadowLayering) { 114298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 114398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 114498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 114598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 114698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 114798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 114898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 114998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 115098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 115198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 115298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 11538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 11548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 115598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 115698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 115798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 115898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 115998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1160f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 11617db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(parent), sLightCenter); 116298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1163f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 116498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 116598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 116698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 116716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 116876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1169d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1170d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1171d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1172d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1173d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1174d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1175d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1176d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1177d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1178d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1179d3daa3198e2212c985c634821682d5819346b653Chris Craik 118016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 118116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 118216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 118376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 118476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 118576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 118616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 118776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1188f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 11897db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck TestUtils::createSyncedNodeList(node), sLightCenter); 119076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1191f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 119276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 119376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 119476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1195f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 119676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 119776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 119876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 119976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 120076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 120176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 120276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 120376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1204f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropClipping) { 120576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 120676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 120776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 120876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 120976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 121076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 121176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 121276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 121376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1214f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropRevealClip) { 121576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 121676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 121776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 121876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 121976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 122076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 122176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 122276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 122376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 122476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1225f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropOutlineClip) { 122676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 122776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 122876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 122976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 123076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 123176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 123276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 123376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 123476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 123576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 123676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1237f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropTransform) { 123876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 123976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 124076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 124176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 124276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 124376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 124476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 124576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 124676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 124776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 124876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 124976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 125076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 125176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 125276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 125376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 125476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 125576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 125676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 125776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 125876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 125976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 126076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 126176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 126276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 126376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 126476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 126576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 126676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 126776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 126876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 1269161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 12708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 12718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 12728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 12738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 12748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 12758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 12768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 12778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 12788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 12798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 12808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 12818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 12828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 12838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 12848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 12858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 12868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 128716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 12888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 12898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 12908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 12918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 12928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 12938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 12948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 12958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 12968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 12978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 12988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 12998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 13008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 13018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 13028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 13038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 13048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 13058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 13068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 13078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 13088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 13098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 13108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 13118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 13128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 13138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 13148ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 13158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 13168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 131716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 131816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 13198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 13208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 13218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 132216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 132316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 132416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 132516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 132616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 13278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 13287db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height 13298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1330f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, nodes, sLightCenter); 13318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 1332f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 13338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 13348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 13358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 13368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 13378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1338f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 13398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 13408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 13418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 13428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 13438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 13448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 13458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 13465430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 13478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 13488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 13498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 13508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 13518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 13528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 13538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1354f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 13558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 13568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 13578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 13588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 13598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 13608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 13618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 13628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 13638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 13648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 13658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 13668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 13678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 13688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 13695430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 13708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 13718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 13728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 1373f158b49c888f722194afe5a80539a2b020c130bcChris CraikTEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 13748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 13758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 13768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 13778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 13788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 13798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 13808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 13818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 13828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 13835430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 13848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 13858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 13868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 13876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 13886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 1389