FrameBuilderTests.cpp revision 04d46eb69fb4f4c4c332c36c6ae845da3b2ae848
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; 336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craikconst std::vector< sp<RenderNode> > sEmptyNodeList; 346e068c0182f6f85bccb855a647510724d1c65a13Chris Craikconst FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 356e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 3698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 385854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 425854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 436fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 45d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 485854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 496fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 505854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 51d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 5274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 53a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 54a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik virtual void recycleTemporaryLayer(OffscreenBuffer*) { 5674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 5774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 5898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 59a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 60a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 61a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 62a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 63a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 6498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 65e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 665854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 69a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 70a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 71a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 727cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 807cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 8115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 8215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 875854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 895854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 925854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 935854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 975854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 985854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 1007cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 10415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1087cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1125854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1143a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simple) { 115d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 116d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 118d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 119d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 120d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 121d3daa3198e2212c985c634821682d5819346b653Chris Craik } 122d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 123d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 124d3daa3198e2212c985c634821682d5819346b653Chris Craik } 125d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 126d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 127d3daa3198e2212c985c634821682d5819346b653Chris Craik } 128e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 129d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 130d3daa3198e2212c985c634821682d5819346b653Chris Craik } 131d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 132d3daa3198e2212c985c634821682d5819346b653Chris Craik 1338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 1348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 135ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(25, 25); 136b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 137b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 10, 10, nullptr); 138b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 139f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1403a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 1415854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleTestRenderer renderer; 142f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1435854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end 1446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 1456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 1463a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleStroke) { 147386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik class SimpleStrokeTestRenderer : public TestRendererBase { 148386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik public: 149386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik void onPointsOp(const PointsOp& op, const BakedOpState& state) override { 150386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(0, mIndex++); 151386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik // even though initial bounds are empty... 152386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_TRUE(op.unmappedBounds.isEmpty()) 153386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "initial bounds should be empty, since they're unstroked"; 154386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(Rect(45, 45, 55, 55), state.computedState.clippedBounds) 155386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik << "final bounds should account for stroke"; 156386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik } 157386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }; 158386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 159386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik auto node = TestUtils::createNode(0, 0, 100, 200, 160386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 161386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SkPaint strokedPaint; 162386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik strokedPaint.setStrokeWidth(10); 163386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik canvas.drawPoint(50, 50, strokedPaint); 164386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik }); 165f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200, 1663a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 167386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 168f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 169386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 170386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 171386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 1723a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleRejection) { 1738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 1748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 175eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 1766fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); // intersection should be empty 1776fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1786fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 1796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 180f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 1813a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 182b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 184f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 186b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1873a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, simpleBatching) { 188a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 189d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 190d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 191d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 192a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 193d3daa3198e2212c985c634821682d5819346b653Chris Craik } 194d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 195a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 196d3daa3198e2212c985c634821682d5819346b653Chris Craik } 197d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 198d3daa3198e2212c985c634821682d5819346b653Chris Craik 1998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 2008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 20115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(10, 10, 20215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik kAlpha_8_SkColorType); // Disable merging by using alpha 8 bitmap 203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 204b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 206eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 207a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawBitmap(bitmap, 5, 0, nullptr); 211b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 215f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 2163a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 2175854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 218f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 219a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 22015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 221a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 222a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 2236246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, empty_noFbo0) { 2246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyNoFbo0TestRenderer : public TestRendererBase { 2256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 2266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 2276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 2286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 2296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 2306246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 2316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 2326246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 2336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 2346246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // Pass empty node list, so no work is enqueued for Fbo0 2356246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 2366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik sEmptyNodeList, sLightGeometry, Caches::getInstance()); 2376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyNoFbo0TestRenderer renderer; 2386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 2406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 2416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, empty_withFbo0) { 2426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyWithFbo0TestRenderer : public TestRendererBase { 2436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 2446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 2456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 2466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 2476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 2486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 2496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 2506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 2516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 2526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 2536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // no drawn content 2546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 2556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik auto syncedNodeList = TestUtils::createSyncedNodeList(node); 2566246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 2576246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // Draw, but pass empty node list, so no work is done for primary frame 2586246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 2596246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik syncedNodeList, sLightGeometry, Caches::getInstance()); 2606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyWithFbo0TestRenderer renderer; 2616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced," 2636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik " but fbo0 update lifecycle should still be observed"; 2646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 2656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 26680d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikRENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_rects) { 26780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawRectsTestRenderer : public TestRendererBase { 26880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 26980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 27080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(mIndex++, 0) << "Should be one rect"; 27180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds) 27280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Last rect should occlude others."; 27380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 27480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 27580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 27680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 27780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 27880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 27980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 28080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 28180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 28280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // Damage (and therefore clip) is same as last draw, subset of renderable area. 28380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // This means last op occludes other contents, and they'll be rejected to avoid overdraw. 28480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik SkRect damageRect = SkRect::MakeLTRB(10, 10, 190, 190); 28580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, damageRect, 200, 200, 28680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 28780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 28880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(3u, node->getDisplayList()->getOps().size()) 28980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 29080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 29180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawRectsTestRenderer renderer; 29280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 29380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op"; 29480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 29580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 29680d2ade939153da87b3cd3b0a69a713bf68b64baChris CraikRENDERTHREAD_TEST(FrameBuilder, avoidOverdraw_bitmaps) { 29780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik static SkBitmap opaqueBitmap = TestUtils::createSkBitmap(50, 50, 29880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik SkColorType::kRGB_565_SkColorType); 29980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik static SkBitmap transpBitmap = TestUtils::createSkBitmap(50, 50, 30080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik SkColorType::kAlpha_8_SkColorType); 30180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase { 30280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 30380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 30480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik switch(mIndex++) { 30580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 0: 30680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(opaqueBitmap.pixelRef(), op.bitmap->pixelRef()); 30780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 30880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 1: 30980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(transpBitmap.pixelRef(), op.bitmap->pixelRef()); 31080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 31180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik default: 31280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik ADD_FAILURE() << "Only two ops expected."; 31380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 31480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 31580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 31680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 31780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik auto node = TestUtils::createNode(0, 0, 50, 50, 31880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 31980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 32080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 32180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawBitmap(transpBitmap, 0, 0, nullptr); 32280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 32380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // only the below draws should remain, since they're 32480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawBitmap(opaqueBitmap, 0, 0, nullptr); 32580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawBitmap(transpBitmap, 0, 0, nullptr); 32680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 32780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 32880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(50, 50), 50, 50, 32980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 33080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 33180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(5u, node->getDisplayList()->getOps().size()) 33280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 33380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 33480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawBitmapsTestRenderer renderer; 33580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 336a82ffc549bd6dbf8cfc6f4d646d0f458dca54014sergeyv EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops"; 33780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 33880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 3393a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clippedMerging) { 34093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 34193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 34293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 34393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 34493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 34593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 34693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 34793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 34893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 34993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 35093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 35193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik auto node = TestUtils::createNode(0, 0, 100, 100, 35293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik [](RenderProperties& props, TestCanvas& canvas) { 35393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik SkBitmap bitmap = TestUtils::createSkBitmap(20, 20); 35493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 35593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 35693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(10, 0, 50, 100, SkRegion::kReplace_Op); 35793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 0, 40, nullptr); 35893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 35993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 36093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 10, 100, 50, SkRegion::kReplace_Op); 36193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 0, nullptr); 36293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 36393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 36493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(50, 0, 90, 100, SkRegion::kReplace_Op); 36593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 80, 40, nullptr); 36693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 36793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 36893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.clipRect(0, 50, 100, 90, SkRegion::kReplace_Op); 36993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik canvas.drawBitmap(bitmap, 40, 70, nullptr); 37093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 37193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 372f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 3733a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 37493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 375f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 37693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 37793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 37893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 3793a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textMerging) { 380d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 381d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 382d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 383d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 384d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 385d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 386d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 387d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 388d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 389d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 390d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 391d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 392d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik [](RenderProperties& props, TestCanvas& canvas) { 393d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 394d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 395d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 396d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 397dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 398dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 399d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 400f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 4013a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 402d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 403f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 404d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 405d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 406d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 4073a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStrikethrough) { 408a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 409a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 410a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 411a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 412a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 413a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 41415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 41515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 41615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 41715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 418a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 419a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 4208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 2000, 4218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 422a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 423a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 424a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 425a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setStrikeThruText(true); 42642a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 427a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 428dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 429a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 430a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 431f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000, 4323a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 433a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 434f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 435a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 436d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 437b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 438b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 4397c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = { 4407c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; 4417c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 4423a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, textStyle) { 4437c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik class TextStyleTestRenderer : public TestRendererBase { 4447c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik public: 4457c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 4467c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, mIndex); 4477c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(3u, opList.count); 4487c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik mIndex += opList.count; 4497c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 4507c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik int index = 0; 4517c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 4527c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto state = opList.states[index++]; 4537c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(style, state->op->paint->getStyle()) 4547c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Remainder of validation relies upon stable merged order"; 4557c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, state->computedState.clipSideFlags) 4567c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Clipped bounds validation requires unclipped ops"; 4577c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 4587c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 4597c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect fill = opList.states[0]->computedState.clippedBounds; 4607c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect stroke = opList.states[1]->computedState.clippedBounds; 4617c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) 4627c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Stroke+Fill should be same as stroke"; 4637c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 4647c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_TRUE(stroke.contains(fill)); 4657c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_FALSE(fill.contains(stroke)); 4667c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 46779abbf22d4f672208327546661e694d837f564a9Derek Sollenberger // outset by half the stroke width 4687c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect outsetFill(fill); 46979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger outsetFill.outset(5); 4707c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, outsetFill); 4717c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 4727c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }; 4737c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto node = TestUtils::createNode(0, 0, 400, 400, 4747c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik [](RenderProperties& props, TestCanvas& canvas) { 4757c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint paint; 4767c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 4777c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setAntiAlias(true); 4787c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextSize(50); 4797c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStrokeWidth(10); 4807c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 4817c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // draw 3 copies of the same text overlapping, each with a different style. 4827c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // They'll get merged, but with 4837c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 4847c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStyle(style); 485dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 4867c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 4877c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }); 4887c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 4893a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 4907c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TextStyleTestRenderer renderer; 4917c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 4927c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; 4937c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik} 4947c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 495aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { 496aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { 497d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 498d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 499d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 500e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 501d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 502d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 503d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 504d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 505d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 506d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 507d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 508d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 509d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 510243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik SkMatrix::MakeTrans(5, 5)); 511d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 512d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 513d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 514eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 515d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.clipRect(50, 50, 150, 150, SkRegion::kIntersect_Op); 516d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 517d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 518d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 519f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5203a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 521aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerClipLocalMatrixTestRenderer renderer; 522f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 523d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 524d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 525d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 526aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_combineMatrices) { 527aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { 528aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik public: 529aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 530aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(0, mIndex++); 531aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 532aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik Matrix4 expected; 533aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik expected.loadTranslate(35, 45, 0); 534aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 535aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik } 536aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }; 537aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 538aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 539aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 540aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 541aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 542aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 543aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.save(SaveFlags::MatrixClip); 544aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.translate(30, 40); 545aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 546aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.restore(); 547aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 548aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 549aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 550aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 551aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerCombineMatricesTestRenderer renderer; 552aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 553aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(1, renderer.getIndex()); 554aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 555aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 556aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris CraikRENDERTHREAD_TEST(FrameBuilder, textureLayer_reject) { 557aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 558aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 559aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik layerUpdater->backingLayer()->setRenderTarget(GL_NONE); // Should be rejected 560aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 561aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 562aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 563aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 564aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 565aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 566aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 567aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FailRenderer renderer; 568aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 569aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 570aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 5713a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, functor_reject) { 572223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 573223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 574223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 575223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 576223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 577223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 578223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 579223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 580223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 581223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik auto scrolledFunctorView = TestUtils::createNode(0, 0, 400, 1000000, 582223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 583223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 584223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.callDrawGLFunction(&noopFunctor); 585223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 586223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 587223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 5883a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(scrolledFunctorView), 5893a5811b50157e7ba50854caf957e806aee794d39Chris Craik sLightGeometry, Caches::getInstance()); 590223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 591223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 592223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 593223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 594223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 595a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikRENDERTHREAD_TEST(FrameBuilder, deferColorOp_unbounded) { 596a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik class ColorTestRenderer : public TestRendererBase { 597a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik public: 598a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 599a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(0, mIndex++); 600a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds) 601a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik << "Color op should be expanded to bounds of surrounding"; 602a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik } 603a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }; 604a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 605a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik auto unclippedColorView = TestUtils::createNode(0, 0, 10, 10, 606a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 607a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik props.setClipToBounds(false); 608a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 609a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }); 610a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 611a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 612a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik TestUtils::createSyncedNodeList(unclippedColorView), 613a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik sLightGeometry, Caches::getInstance()); 614a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik ColorTestRenderer renderer; 615a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 616a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected"; 617a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 618a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 619a204848b1dc63877a12e2d24108e9d8e1e691e28Chris CraikTEST(FrameBuilder, renderNode) { 620d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 621d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 622d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 623d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 624d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 6255430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 626d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 627d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 628d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 629d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 630d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 631d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 632d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 633d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 634d3daa3198e2212c985c634821682d5819346b653Chris Craik } 635d3daa3198e2212c985c634821682d5819346b653Chris Craik } 636d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 637d3daa3198e2212c985c634821682d5819346b653Chris Craik 6388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(10, 10, 110, 110, 6398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 640b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 641b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 642b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 643b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 644b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 6458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 646d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 647ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 648ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 649ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 650ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 651eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 652ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 653d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 654ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 655b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 656b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 657f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 6583a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 6595854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 660f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 661223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 662b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 663b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 6643a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, clipped) { 665d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 666d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 667d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 668d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 669d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 670e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 671d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 672d3daa3198e2212c985c634821682d5819346b653Chris Craik } 673d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 674d3daa3198e2212c985c634821682d5819346b653Chris Craik 6758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 6768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 677ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkBitmap bitmap = TestUtils::createSkBitmap(200, 200); 678ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawBitmap(bitmap, 0, 0, nullptr); 679ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 680ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 681f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, 6820b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver 6833a5811b50157e7ba50854caf957e806aee794d39Chris Craik 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 6845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 685f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 686ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 687ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 6883a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) { 689d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 690d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 691d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 692d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 693d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 694d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 695d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 696d3daa3198e2212c985c634821682d5819346b653Chris Craik } 697d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 698d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 699d3daa3198e2212c985c634821682d5819346b653Chris Craik } 700d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 701d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 702d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 7035430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 704e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 705d3daa3198e2212c985c634821682d5819346b653Chris Craik 706d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 707d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 708d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 709d3daa3198e2212c985c634821682d5819346b653Chris Craik } 710d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 711d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 712d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 713e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 714d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 715d3daa3198e2212c985c634821682d5819346b653Chris Craik } 71674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 71774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 71874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(nullptr, offscreenBuffer); 71974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 720d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 721d3daa3198e2212c985c634821682d5819346b653Chris Craik 7228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 7238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 724eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 7256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 7266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 7276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 728f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 7293a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 7305854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 731f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 73274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, renderer.getIndex()); 733b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 7346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 7353a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) { 736d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 737d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 738d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 739d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 740d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 741d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 742d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 743d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 744d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 745d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 746d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 747d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 748d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 749d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 750d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 751d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 752d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 753d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 754d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 755d3daa3198e2212c985c634821682d5819346b653Chris Craik } 756d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 757d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 758d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 759d3daa3198e2212c985c634821682d5819346b653Chris Craik } 76098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 761d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 762d3daa3198e2212c985c634821682d5819346b653Chris Craik } 763e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 764d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 765d3daa3198e2212c985c634821682d5819346b653Chris Craik } 766d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 767d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 768d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 7695430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 770d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 7715430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 772d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 773d3daa3198e2212c985c634821682d5819346b653Chris Craik } 774d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 775d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 776d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 777d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 7785430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 779d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 780d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 7815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 782d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 783d3daa3198e2212c985c634821682d5819346b653Chris Craik } 78474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 78574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik const int index = mIndex++; 78674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik // order isn't important, but we need to see both 78774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik if (index == 10) { 78874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer); 78974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else if (index == 11) { 79074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer); 79174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else { ADD_FAILURE(); } 79274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 793d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 794d3daa3198e2212c985c634821682d5819346b653Chris Craik 7958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 800, 800, 7968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 797eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 7986fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 7996fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 800eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 8016fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 8026fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 8036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 8046fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 8056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 8066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 8076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 8086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 809f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800, 8103a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 8115854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 812f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 81374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, renderer.getIndex()); 8146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 8156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8163a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) { 8178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 8188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 819eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 8206fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.clipRect(200, 200, 400, 400, SkRegion::kIntersect_Op); 821eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 8226fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8236fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 8246fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 8256fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 8276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 8286fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 829f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 8303a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 8316fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8325854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 8336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 834f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 835b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 8366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 8373a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) { 838b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 839b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 840b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 841b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 842b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 8437435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 844b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 845b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 846b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 847b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 848b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 849b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 850b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 851b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 852b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 853b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 854b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 855b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 856b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 857b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 858b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 859b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 860b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 8617435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 862b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 863b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 864b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 865b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 866b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 867b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 868eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 869b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 870b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 871b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 872f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 8733a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 874b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 875f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 876b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 877b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 878b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 8793a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 880b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 881b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 882b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 883b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 884b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 885b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 886b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 887b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 888b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 889b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 890b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 891b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 892b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 893b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 894b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 895b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 896b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 897b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 898b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 899b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 900b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 901b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 902b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 903b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 904b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 905b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 906b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 907b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 908b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 909b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 910b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 911b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 912b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 913b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 914b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 915b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 916b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 917eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 918b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 919eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 920eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 921eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 922eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 923b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 924b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 925b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 926f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 9273a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 928b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 929f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 930b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 931b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 932b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 933b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 9343a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_clearClip) { 9354876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 9364876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 9374876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 9384876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 9394876de16e34622634266d09522c9153c78c7c2fbChris Craik } 9404876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 9414876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 9424876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 9434876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(SkXfermode::kClear_Mode, PaintUtils::getXfermodeDirect(op.paint)); 9444876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 9454876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 9464876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 9474876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 9484876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 9494876de16e34622634266d09522c9153c78c7c2fbChris Craik } 9504876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 9514876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 9524876de16e34622634266d09522c9153c78c7c2fbChris Craik } 9534876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 9544876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 9554876de16e34622634266d09522c9153c78c7c2fbChris Craik } 9564876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 9574876de16e34622634266d09522c9153c78c7c2fbChris Craik 9584876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 9594876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 9604876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 9614876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 9624876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 9634876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 9644876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 9654876de16e34622634266d09522c9153c78c7c2fbChris Craik 9664876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 9674876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 9683a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 9694876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 9704876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 9714876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 9724876de16e34622634266d09522c9153c78c7c2fbChris Craik} 9734876de16e34622634266d09522c9153c78c7c2fbChris Craik 9743a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_reject) { 9754876de16e34622634266d09522c9153c78c7c2fbChris Craik auto node = TestUtils::createNode(0, 0, 200, 200, 9764876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 9774876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 9784876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 9794876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 9804876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 9814876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 9824876de16e34622634266d09522c9153c78c7c2fbChris Craik 9834876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 9844876de16e34622634266d09522c9153c78c7c2fbChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 9853a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 9864876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 9874876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 9884876de16e34622634266d09522c9153c78c7c2fbChris Craik} 9894876de16e34622634266d09522c9153c78c7c2fbChris Craik 990b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 991b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 992b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 993b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 9943a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) { 995b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 996b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 997b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 998b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 999b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 1000b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1001b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1002b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1003b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 1004b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1005b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1006b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1007b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 1008b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1009b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1010b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 1011b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 1012b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 1013b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 1014b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 1015b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1016b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1017b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1018b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 1019b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1020b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 1021b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1022b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1023b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1024b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 1025b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1026b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1027b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 102874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1029b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1030b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 1031b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 1032b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 103374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 103474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, mIndex++); 103574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer); 103674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1037b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1038b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1039b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto node = TestUtils::createNode(0, 0, 600, 600, // 500x500 triggers clipping 1040b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1041eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 1042eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 1043eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 1044b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 1045b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1046b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1047b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1048b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 1049f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600, 10503a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 1051b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 1052f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 105374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, renderer.getIndex()); 1054b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1055b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1056f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) { 1057d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 1058d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 105998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1060d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 106198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 106298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 106398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 1064d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1065d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1066d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 10670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1068d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 1069d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 1070d3daa3198e2212c985c634821682d5819346b653Chris Craik 1071e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 1072d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 1073d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1074d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1075d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 1076d3daa3198e2212c985c634821682d5819346b653Chris Craik } 107798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1078d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 1079d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1080d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1081d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 1082d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1083e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1084d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 1085d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1086d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 10870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 10888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 108916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 109016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 10910b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 10920b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 10930b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 109416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 109598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 10960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 109798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 109898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 109998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 11000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 11017db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedNodeList = TestUtils::createSyncedNodeList(node); 11020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 11030b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 110498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 11050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 11060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1107f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 11083a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedNodeList, sLightGeometry, Caches::getInstance()); 11090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 1110f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 11110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 11120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 11130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 111498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 11150b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 11160b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1117f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) { 1118d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 1119d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 1120d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 1121d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 1122d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 1123d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 1124d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 1125d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1126d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1127d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 1128d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 1129d3daa3198e2212c985c634821682d5819346b653Chris Craik } 113098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1131d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1132d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 1133d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 113498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 113598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 1136d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 1137d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 113898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 113998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 1140d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1141d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1142d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1143d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1144d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 1145d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 1146d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 1147d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 1148d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 1149d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1150d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1151d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1152d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1153d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1154d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 1155d3daa3198e2212c985c634821682d5819346b653Chris Craik } 115698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1157d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 1158d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1159d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 116098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 1161d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1162d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 116398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 116498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 1165d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 1166d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1167d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 116898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 116998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 1170d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1171d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1172e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1173d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 1174d3daa3198e2212c985c634821682d5819346b653Chris Craik } 117574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 117674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, mIndex++); 117774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1178d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1179d3daa3198e2212c985c634821682d5819346b653Chris Craik 118016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto child = TestUtils::createNode(50, 50, 150, 150, 118116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 118216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 11830b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 11840b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 11850b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 118616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 118798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 118898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 11890b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 11900b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 119116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 200, 200, 119216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 119316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 11940b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 11950b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 11960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 11970b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1198eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 11990b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 12000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 120116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 120298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 120398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 12040b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12057db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 12060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 120798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 12080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 12090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 12100b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1211f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 12123a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedList, sLightGeometry, Caches::getInstance()); 12130b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1214f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 121574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(14, renderer.getIndex()); 12160b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12170b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 12180b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 12190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 12200b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 12210b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 12226246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12236246d27813f25b85f6e4b5cb1121fe8484bcce2dChris CraikRENDERTHREAD_TEST(FrameBuilder, buildLayer) { 12246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class BuildLayerTestRenderer : public TestRendererBase { 12256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 12266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 12276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 12286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 12296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 12306246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 12316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 12326246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 12336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 12346246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12356246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 12366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Transform should be reset within layer"; 12376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 12396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Damage rect should be used to clip layer content"; 12406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 12416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endLayer() override { 12426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, mIndex++); 12436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 12446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 12456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 12466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 12476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 12486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 12496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 12506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 12516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik auto node = TestUtils::createNode(10, 10, 110, 110, 12536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 12546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik props.mutateLayerProperties().setType(LayerType::RenderLayer); 12556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 12566246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 12576246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 12586246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12596246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // create RenderNode's layer here in same way prepareTree would 12606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 12616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = &layer; 12626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik auto syncedNodeList = TestUtils::createSyncedNodeList(node); 12646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // only enqueue partial damage 12666246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 12676246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 12686246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12696246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // Draw, but pass empty node list, so no work is done for primary frame 12706246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(1, 1), 1, 1, 12716246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik sEmptyNodeList, sLightGeometry, Caches::getInstance()); 12726246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik BuildLayerTestRenderer renderer; 12736246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 12746246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(3, renderer.getIndex()); 12756246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 12766246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // clean up layer pointer, so we can safely destruct RenderNode 12776246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = nullptr; 12786246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 12796246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 1280161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedRect(RecordingCanvas* canvas, uint8_t expectedDrawOrder) { 1281161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1282161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik paint.setColor(SkColorSetARGB(256, 0, 0, expectedDrawOrder)); // order put in blue channel 1283161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1284161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1285161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikstatic void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder, float z) { 128616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 12878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1288161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1289161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1290161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1291161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1292161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1293161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 12943a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, zReorder) { 1295d3daa3198e2212c985c634821682d5819346b653Chris Craik class ZReorderTestRenderer : public TestRendererBase { 1296d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1297d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1298d3daa3198e2212c985c634821682d5819346b653Chris Craik int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1299d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1300d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1301d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1302d3daa3198e2212c985c634821682d5819346b653Chris Craik 130316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto parent = TestUtils::createNode(0, 0, 100, 100, 13048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1305161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1306161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1307161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1308161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1309161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1310161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1311161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1312161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1313161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1314161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1315161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1316161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 1317161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1318f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 13193a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 1320161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1321f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1322161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik EXPECT_EQ(10, renderer.getIndex()); 1323161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1324161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 13253a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionReorder) { 13268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 13278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 13288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 13298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 13308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 13318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 13328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 13338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 13348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 13358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 13368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 13378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 13388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1339678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 13408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 13418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 13428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 13438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1344678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1345678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1346678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1347678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 13488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 13498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 13508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 13518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 13528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1353678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 13548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 13558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 13568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 13578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1358678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 13598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 13608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 13618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 13628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 13638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 13648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 13658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 13668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 13678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 13688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 13698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 13708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 100, 100, 13718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 13728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 13738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 13748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 13758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 13768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 13778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 13788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 13798d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 13808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 13818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 13828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto projectingRipple = TestUtils::createNode(50, 0, 100, 50, 13838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 13848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 13858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 13868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 13878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 13888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 13898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 13908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto child = TestUtils::createNode(0, 50, 100, 100, 13918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 13928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 13938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 13948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 13958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 13968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 13978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 100, 100, 13988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1399678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1400678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1401678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1402eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 14038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 14048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 14058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 14068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 14078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 14088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1409f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100, 14103a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 14118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1412f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 14138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 14148d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 14158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 1416678ff81105753656aa4822f4f675ef96dc9d2b83Chris CraikRENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) { 1417678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1418678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1419678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1420678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1421678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1422678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1423678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1424678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1425678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1426678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1427678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1428678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1429678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1430678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1431678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1432678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1433678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1434678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1435678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1436678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1437678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1438678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1439678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1440678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1441678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1442678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1443678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1444678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1445678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1446678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1447678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1448678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 1449678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1450678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1451678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1452678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1453678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1454678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1455678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1456678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1457678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1458678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1459678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1460678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1461678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1462678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1463678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1464678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1465678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto child = TestUtils::createNode(100, 100, 300, 300, 1466678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1467678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1468678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1469678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1470678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1471678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1472678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1473678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1474678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1475678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1476678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1477678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1478678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1479678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1480678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1481678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1482678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1483678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1484678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1485678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1486678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1487678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1488678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1489678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik auto syncedList = TestUtils::createSyncedNodeList(parent); 1490678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1491678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 1492678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 14933a5811b50157e7ba50854caf957e806aee794d39Chris Craik syncedList, sLightGeometry, Caches::getInstance()); 1494678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1495678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1496678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1497678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1498678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1499678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1500678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1501678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1502a748c08241e43fc68c7c34767d819aef5183936eChris CraikRENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) { 1503a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1504a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1505a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1506a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1507a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1508a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1509a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1510a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1511a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1512a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1513a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1514a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1515a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1516a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1517a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1518a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 1519a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto receiverBackground = TestUtils::createNode(0, 0, 400, 400, 1520a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1521a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1522a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1523a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1524a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto projectingRipple = TestUtils::createNode(0, 0, 200, 200, 1525a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1526a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1527a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1528a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1529a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1530a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1531a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1532a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1533a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1534a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto child = TestUtils::createNode(0, 0, 400, 400, 1535a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1536a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 1537a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.clipRect(100, 100, 300, 300, SkRegion::kIntersect_Op); 1538a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1539a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1540a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1541a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1542a748c08241e43fc68c7c34767d819aef5183936eChris Craik auto parent = TestUtils::createNode(0, 0, 400, 400, 1543a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1544a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1545a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1546a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1547a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1548a748c08241e43fc68c7c34767d819aef5183936eChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400, 15493a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 1550a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1551a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1552a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1553a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1554a748c08241e43fc68c7c34767d819aef5183936eChris Craik 155598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 155698787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 155716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck return TestUtils::createNode(0, 0, 100, 100, 15588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 155916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 156016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 156198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 156298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 156398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 156498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 156598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 156698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 15676e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadow) { 1568d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1569d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1570d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1571d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 157298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 15736e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 15746e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 157598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 157698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 157798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 15786e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1579d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1580d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1581d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1582d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1583d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1584161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 15858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 15868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 158798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 158898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1589d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 159098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1591f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 15923a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance()); 159398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1594f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 159598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 159698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 159798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 15986e068c0182f6f85bccb855a647510724d1c65a13Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) { 159998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 160098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 160198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 160298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 160398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 160498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 160598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 160698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 16076e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 16086e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 160998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 161098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 161198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 161298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 161398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 161498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 161598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 161698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 161798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 161898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 161974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 162074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, mIndex++); 162174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 162298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 162398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 16248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 16258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 162698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 162798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1628eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1629d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 163098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 163198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 163298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1633d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1634d3daa3198e2212c985c634821682d5819346b653Chris Craik 1635f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 16366e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 16373a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 163898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1639f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 164074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(6, renderer.getIndex()); 164198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1642d3daa3198e2212c985c634821682d5819346b653Chris Craik 1643f158b49c888f722194afe5a80539a2b020c130bcChris CraikRENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) { 164498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 164598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 164698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 164798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 164898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 164998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 165098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 16516e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 16526e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 16536e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 165498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 165598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 165698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 165798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 165898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 165998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 166098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 166198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 166298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 166398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 166498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1665d3daa3198e2212c985c634821682d5819346b653Chris Craik 16668d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(50, 60, 150, 160, 166716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 166816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 166998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1670eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 167198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 167298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 167398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 167416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 167598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 167698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 167798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 167898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 167998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 168098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 168198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 168298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 168398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 16847db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto syncedList = TestUtils::createSyncedNodeList(parent); 168598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 168698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 1687f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 16886e068c0182f6f85bccb855a647510724d1c65a13Chris Craik syncedList, 16893a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance()); 169098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 1691f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 169298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 169398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 169498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 169598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 1696d3daa3198e2212c985c634821682d5819346b653Chris Craik} 169776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 16983a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, shadowLayering) { 169998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 170098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 170198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 170298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 170398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 170498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 170598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 170698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 170798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 170898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 170998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 17108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik auto parent = TestUtils::createNode(0, 0, 200, 200, 17118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 171298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 171398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 171498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 171598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 171698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 1717f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 17186e068c0182f6f85bccb855a647510724d1c65a13Chris Craik TestUtils::createSyncedNodeList(parent), 17193a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 172098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 1721f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 172298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 172398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 172498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 172516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 172676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 1727d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 1728d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1729d3daa3198e2212c985c634821682d5819346b653Chris Craik PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 1730d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 1731d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1732d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 1733d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 1734d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1735d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 1736d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1737d3daa3198e2212c985c634821682d5819346b653Chris Craik 173816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 100, 100, 173916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 174016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 174176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 174276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 174376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 174416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 174576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 1746f158b49c888f722194afe5a80539a2b020c130bcChris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200, 17473a5811b50157e7ba50854caf957e806aee794d39Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 174876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 1749f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 175076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 175176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 175276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 17533a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 175476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 175576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 175676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 175776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 175876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 175976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 176076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 176176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 17623a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropClipping) { 176376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 176476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 176576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 176676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 176776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 176876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 176976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 177076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 177176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 17723a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropRevealClip) { 177376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 177476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 177576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 177676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 177776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 177876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 177976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 178076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 178176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 178276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 17833a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropOutlineClip) { 178476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 178576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 178676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 178776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 178876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 178976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 179076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 179176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 179276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 179376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 179476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 17953a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropTransform) { 179676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 179776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 179876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 179976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 180076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 180176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 180276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 180376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 180476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 180576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 180676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 180776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 180876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 180976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 181076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 181176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 181276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 181376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 181476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 181576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 181676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 181776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 181876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 181976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 182076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 182176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 182276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 182376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 182476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 182576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 182676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 1827161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 18288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 18298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 18308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 18318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 18328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 18338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 18348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 18358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 18368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 18378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 18388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 18398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 18408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 18418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 18428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 18438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 18448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 184516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 18468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 18478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 18488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 18498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 18508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 18518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 18528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 18538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 18548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 18558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 18568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 18578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 18588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 18598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 18608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 18618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 18628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 18638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 18648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 18658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 18668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 18678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 18688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 186974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 187074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 187174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 18728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 18738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 18748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 18758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 18768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 18778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 187816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck auto node = TestUtils::createNode(0, 0, 10000, 10000, 187916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 18808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 18818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 18828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 188316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 188416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 188516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 188616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 188716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 18888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 18897db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height 18908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 18916e068c0182f6f85bccb855a647510724d1c65a13Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200, 18923a5811b50157e7ba50854caf957e806aee794d39Chris Craik nodes, sLightGeometry, Caches::getInstance()); 18938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 1894f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 18958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 18968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 189774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 18988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 18998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 19003a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 19018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 19028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 19038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 19048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 19058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 19068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 19078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 19085430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 19098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 19108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 19118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 19128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 19138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 19148ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 19158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 19163a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 19178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 19188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 19198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 19208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 19218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 19228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 19238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 19248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 19258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 19268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 19278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 19288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 19298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 19308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 19315430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 19328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 19338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 19348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 19353a5811b50157e7ba50854caf957e806aee794d39Chris CraikRENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 19368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 19378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 19388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 19398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 19408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 19418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 19428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 19438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 19448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 19455430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 19468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 19478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 19488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 194904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris CraikRENDERTHREAD_TEST(FrameBuilder, clip_replace) { 195004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik class ClipReplaceTestRenderer : public TestRendererBase { 195104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik public: 195204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 195304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(0, mIndex++); 195404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_TRUE(op.localClip->intersectWithRoot); 195504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect) 195604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik << "Expect resolved clip to be intersection of viewport clip and clip op"; 195704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 195804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }; 195904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik auto node = TestUtils::createNode(20, 20, 30, 30, 196004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 196104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik canvas.clipRect(0, -20, 10, 30, SkRegion::kReplace_Op); 196204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik canvas.drawColor(SK_ColorWHITE, SkXfermode::Mode::kSrcOver_Mode); 196304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }); 196404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 196504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(10, 10, 40, 40), 50, 50, 196604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance()); 196704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik ClipReplaceTestRenderer renderer; 196804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 196904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(1, renderer.getIndex()); 197004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 197104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 19726fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 19736fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 1974