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> 228cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel#include <GlLayer.h> 238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik#include <LayerUpdateQueue.h> 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordedOp.h> 25b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RecordingCanvas.h> 268160f20b0aca8c6595d4b385d673f59b6bcd16a4Chris Craik#include <tests/common/TestUtils.h> 27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 28b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <unordered_map> 29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 31b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 32b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 336e068c0182f6f85bccb855a647510724d1c65a13Chris Craikconst FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 346e068c0182f6f85bccb855a647510724d1c65a13Chris Craik 356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik/** 365854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual class implemented by each test to redirect static operation / state transitions to 375854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * virtual methods. 386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Virtual dispatch allows for default behaviors to be specified (very common case in below tests), 405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * and allows Renderer vs Dispatching behavior to be merged. 416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * 426fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * onXXXOp methods fail by default - tests should override ops they expect 43d3daa3198e2212c985c634821682d5819346b653Chris Craik * startRepaintLayer fails by default - tests should override if expected 446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik * startFrame/endFrame do nothing by default - tests should override to intercept 456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik */ 465854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestRendererBase { 476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craikpublic: 485854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik virtual ~TestRendererBase() {} 49d3daa3198e2212c985c634821682d5819346b653Chris Craik virtual OffscreenBuffer* startTemporaryLayer(uint32_t, uint32_t) { 5074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 51a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik return nullptr; 52a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 5374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik virtual void recycleTemporaryLayer(OffscreenBuffer*) { 5474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ADD_FAILURE() << "Temporary layers not expected in this test"; 5574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 5698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startRepaintLayer(OffscreenBuffer*, const Rect& repaintRect) { 57a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer repaint not expected in this test"; 58a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 59a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void endLayer() { 60a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << "Layer updates not expected in this test"; 61a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 6298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik virtual void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) {} 63e4db79de127cfe961195f52907af8451026eaa20Chris Craik virtual void endFrame(const Rect& repaintRect) {} 645854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 6515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for single draw methods 6615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 67a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik virtual void on##Type(const Type&, const BakedOpState&) { \ 68a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik ADD_FAILURE() << #Type " not expected in this test"; \ 69a6ac95e5772c5df441b49189af3a0df79a22679dChris Craik } 707cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X) 7115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 7215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 7315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define virtual defaults for merged draw methods 7415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 7515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik virtual void onMerged##Type##s(const MergedBakedOpList& opList) { \ 7615c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik ADD_FAILURE() << "Merged " #Type "s not expected in this test"; \ 7715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 787cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X) 7915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 8015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 815854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int getIndex() { return mIndex; } 825854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik 835854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikprotected: 845854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik int mIndex = 0; 855854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik}; 866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 875854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik/** 885854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik * Dispatches all static methods to similar formed methods on renderer, which fail by default but 898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * are overridden by subclasses per test. 905854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik */ 915854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass TestDispatcher { 925854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikpublic: 9315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define single op methods, which redirect to TestRendererBase 9415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 955854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik static void on##Type(TestRendererBase& renderer, const Type& op, const BakedOpState& state) { \ 965854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik renderer.on##Type(op, state); \ 976fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 987cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_RENDERABLE_OPS(X); 9915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 10015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik 10115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik // define merged op methods, which redirect to TestRendererBase 10215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#define X(Type) \ 10315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik static void onMerged##Type##s(TestRendererBase& renderer, const MergedBakedOpList& opList) { \ 10415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik renderer.onMerged##Type##s(opList); \ 10515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik } 1067cbf63da4f29e5a6b131796eb3b67fd9ff1521b8Chris Craik MAP_MERGEABLE_OPS(X); 10715c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik#undef X 1086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}; 109b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 1105854b34881b1a747ac80b5077869ef270a92b1f4Chris Craikclass FailRenderer : public TestRendererBase {}; 1116fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 11298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simple) { 113d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleTestRenderer : public TestRendererBase { 114d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 11598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 116d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 117d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(100u, width); 118d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(200u, height); 119d3daa3198e2212c985c634821682d5819346b653Chris Craik } 120d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 121d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 122d3daa3198e2212c985c634821682d5819346b653Chris Craik } 123d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 124d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 125d3daa3198e2212c985c634821682d5819346b653Chris Craik } 126e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 127d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 128d3daa3198e2212c985c634821682d5819346b653Chris Craik } 129d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 130d3daa3198e2212c985c634821682d5819346b653Chris Craik 13106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 200, 1328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 133aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(25, 25)); 134b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 200, SkPaint()); 135aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 10, 10, nullptr); 136b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 1379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 1389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 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 14698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_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 15906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(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 }); 1659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 1669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 1679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 169386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik SimpleStrokeTestRenderer renderer; 170f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 171386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik EXPECT_EQ(1, renderer.getIndex()); 172386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik} 173386aa031793bb037ec43b6cdbd8908c343cc86cbChris Craik 17449b403dc9c47ada51c8e5b883347682a868515f8Chris Craik 17549b403dc9c47ada51c8e5b883347682a868515f8Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, arcStrokeClip) { 17649b403dc9c47ada51c8e5b883347682a868515f8Chris Craik class ArcStrokeClipTestRenderer : public TestRendererBase { 17749b403dc9c47ada51c8e5b883347682a868515f8Chris Craik public: 17849b403dc9c47ada51c8e5b883347682a868515f8Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 17949b403dc9c47ada51c8e5b883347682a868515f8Chris Craik EXPECT_EQ(0, mIndex++); 18049b403dc9c47ada51c8e5b883347682a868515f8Chris Craik EXPECT_EQ(Rect(25, 25, 175, 175), op.unmappedBounds); 18149b403dc9c47ada51c8e5b883347682a868515f8Chris Craik EXPECT_EQ(Rect(25, 25, 175, 175), state.computedState.clippedBounds); 18249b403dc9c47ada51c8e5b883347682a868515f8Chris Craik EXPECT_EQ(OpClipSideFlags::Full, state.computedState.clipSideFlags) 18349b403dc9c47ada51c8e5b883347682a868515f8Chris Craik << "Arc op clipped conservatively, since path texture may be expanded"; 18449b403dc9c47ada51c8e5b883347682a868515f8Chris Craik } 18549b403dc9c47ada51c8e5b883347682a868515f8Chris Craik }; 18649b403dc9c47ada51c8e5b883347682a868515f8Chris Craik 18749b403dc9c47ada51c8e5b883347682a868515f8Chris Craik auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 18849b403dc9c47ada51c8e5b883347682a868515f8Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 18949b403dc9c47ada51c8e5b883347682a868515f8Chris Craik canvas.clipRect(25, 25, 175, 175, SkClipOp::kIntersect); 19049b403dc9c47ada51c8e5b883347682a868515f8Chris Craik SkPaint aaPaint; 19149b403dc9c47ada51c8e5b883347682a868515f8Chris Craik aaPaint.setAntiAlias(true); 19249b403dc9c47ada51c8e5b883347682a868515f8Chris Craik canvas.drawArc(25, 25, 175, 175, 40, 180, true, aaPaint); 19349b403dc9c47ada51c8e5b883347682a868515f8Chris Craik }); 19449b403dc9c47ada51c8e5b883347682a868515f8Chris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 19549b403dc9c47ada51c8e5b883347682a868515f8Chris Craik sLightGeometry, Caches::getInstance()); 19649b403dc9c47ada51c8e5b883347682a868515f8Chris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 19749b403dc9c47ada51c8e5b883347682a868515f8Chris Craik 19849b403dc9c47ada51c8e5b883347682a868515f8Chris Craik ArcStrokeClipTestRenderer renderer; 19949b403dc9c47ada51c8e5b883347682a868515f8Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 20049b403dc9c47ada51c8e5b883347682a868515f8Chris Craik EXPECT_EQ(1, renderer.getIndex()); 20149b403dc9c47ada51c8e5b883347682a868515f8Chris Craik} 20249b403dc9c47ada51c8e5b883347682a868515f8Chris Craik 20398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleRejection) { 20406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 2058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 206eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 2076c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); // intersection should be empty 2086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 2096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 2106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 2119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 2129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 214b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2155854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 216f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 218b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 21998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleBatching) { 220a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 221d3daa3198e2212c985c634821682d5819346b653Chris Craik class SimpleBatchingTestRenderer : public TestRendererBase { 222d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 223d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 224a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects"; 225d3daa3198e2212c985c634821682d5819346b653Chris Craik } 226d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 227a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps"; 228d3daa3198e2212c985c634821682d5819346b653Chris Craik } 229d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 230d3daa3198e2212c985c634821682d5819346b653Chris Craik 23106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 2328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 233aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv 234aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10, 235aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv kAlpha_8_SkColorType)); // Disable merging by using alpha 8 bitmap 236b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 237b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 239eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 240a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 241b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.translate(0, 10); 242b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 10, 10, SkPaint()); 243aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 5, 0, nullptr); 244b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 245b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.restore(); 246b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 2479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 2489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 250b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2515854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SimpleBatchingTestRenderer renderer; 252f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 253a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 25415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik << "Expect number of ops = 2 * loop count"; 255a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik} 256a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 25798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNode_translateClip) { 2589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik class DeferRenderNodeTranslateClipTestRenderer : public TestRendererBase { 2599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public: 2609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(0, mIndex++); 2629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(5, 10, 55, 60), state.computedState.clippedBounds); 2639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom, 2649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik state.computedState.clipSideFlags); 2659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 2669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }; 2679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 26806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 2709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 2719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }); 2729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 2759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(5, 10, Rect(50, 50), // translate + clip node 2769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik *TestUtils::getSyncedNode(node)); 2779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik DeferRenderNodeTranslateClipTestRenderer renderer; 2799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(1, renderer.getIndex()); 2819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik} 2829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 28398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNodeScene) { 2849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik class DeferRenderNodeSceneTestRenderer : public TestRendererBase { 2859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik public: 2869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik const Rect& clippedBounds = state.computedState.clippedBounds; 2889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik Matrix4 expected; 2899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik switch (mIndex++) { 2909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 0: 2919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // background - left side 2929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(600, 100, 700, 500), clippedBounds); 2939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(100, 100, 0); 2949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 2959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 1: 2969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // background - top side 2979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(100, 400, 600, 500), clippedBounds); 2989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(100, 100, 0); 2999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 3009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 2: 3019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // content 3029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(100, 100, 700, 500), clippedBounds); 3039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik expected.loadTranslate(-50, -50, 0); 3049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 3059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik case 3: 3069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // overlay 3079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(Rect(0, 0, 800, 200), clippedBounds); 3089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik break; 3099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik default: 3109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik ADD_FAILURE() << "Too many rects observed"; 3119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 3129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik EXPECT_EQ(expected, state.computedState.transform); 3139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 3149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik }; 3159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik std::vector<sp<RenderNode>> nodes; 3179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik SkPaint transparentPaint; 3189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik transparentPaint.setAlpha(128); 3199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // backdrop 32106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev nodes.push_back(TestUtils::createNode<RecordingCanvas>(100, 100, 700, 500, // 600x400 3229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 3239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 600, 400, transparentPaint); 3249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // content 3279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik Rect contentDrawBounds(150, 150, 650, 450); // 500x300 32806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600, 3299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 3309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 800, 600, transparentPaint); 3319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // overlay 33406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600, 3359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) { 3369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik canvas.drawRect(0, 0, 800, 200, transparentPaint); 3379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik })); 3389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 3399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik for (auto& node : nodes) { 3409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik TestUtils::syncHierarchyPropertiesAndDisplayList(node); 3419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik } 3429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 34347aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck { 34447aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600, 34547aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck sLightGeometry, Caches::getInstance()); 34647aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds); 34747aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck 34847aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck DeferRenderNodeSceneTestRenderer renderer; 34947aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck frameBuilder.replayBakedOps<TestDispatcher>(renderer); 35047aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck EXPECT_EQ(4, renderer.getIndex()); 35147aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck } 3529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 35347aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck for (auto& node : nodes) { 3542de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck EXPECT_TRUE(node->isValid()); 35547aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck EXPECT_FALSE(node->nothingToDraw()); 3562de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck node->setStagingDisplayList(nullptr); 3572de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck EXPECT_FALSE(node->isValid()); 3582de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck EXPECT_FALSE(node->nothingToDraw()); 3592de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck node->destroyHardwareResources(); 36047aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck EXPECT_TRUE(node->nothingToDraw()); 3612de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck EXPECT_FALSE(node->isValid()); 36247aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck } 36347aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck 36447aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck { 36547aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck // Validate no crashes if any nodes are missing DisplayLists 36647aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600, 36747aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck sLightGeometry, Caches::getInstance()); 36847aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds); 36947aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck 37047aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck FailRenderer renderer; 37147aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck frameBuilder.replayBakedOps<TestDispatcher>(renderer); 37247aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck } 3739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik} 3749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 37598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_noFbo0) { 3766246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyNoFbo0TestRenderer : public TestRendererBase { 3776246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 3786246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 3796246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 3806246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3816246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 3826246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 3836246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3846246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 3856246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 3869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // Use layer update constructor, so no work is enqueued for Fbo0 3879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik LayerUpdateQueue emptyLayerUpdateQueue; 3889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(emptyLayerUpdateQueue, sLightGeometry, Caches::getInstance()); 3896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyNoFbo0TestRenderer renderer; 3906246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 3916246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 3926246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 39398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_withFbo0) { 3946246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class EmptyWithFbo0TestRenderer : public TestRendererBase { 3956246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 3966246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 3976246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 3986246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 3996246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 4006246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 4016246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 4026246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 40306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 4046246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 4056246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // no drawn content 4066246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 4076246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 4089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // Draw, but pass node without draw content, so no work is done for primary frame 4099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 4109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 4129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 4136246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EmptyWithFbo0TestRenderer renderer; 4146246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 4156246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced," 4166246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik " but fbo0 update lifecycle should still be observed"; 4176246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 4186246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 41998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_rects) { 42080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawRectsTestRenderer : public TestRendererBase { 42180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 42280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 42380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(mIndex++, 0) << "Should be one rect"; 42480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds) 42580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Last rect should occlude others."; 42680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 42780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 42806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 42980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 43080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 43180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 43280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 43380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 43480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 43580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // Damage (and therefore clip) is same as last draw, subset of renderable area. 43680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // This means last op occludes other contents, and they'll be rejected to avoid overdraw. 4379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200, 4389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 44080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 44180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(3u, node->getDisplayList()->getOps().size()) 44280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 44380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 44480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawRectsTestRenderer renderer; 44580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 44680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op"; 44780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 44880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 44998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_bitmaps) { 450aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv static sk_sp<Bitmap> opaqueBitmap(TestUtils::createBitmap(50, 50, 451aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv SkColorType::kRGB_565_SkColorType)); 452aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv static sk_sp<Bitmap> transpBitmap(TestUtils::createBitmap(50, 50, 453aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv SkColorType::kAlpha_8_SkColorType)); 45480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase { 45580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik public: 45680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 45780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik switch(mIndex++) { 45880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 0: 459ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv EXPECT_EQ(opaqueBitmap.get(), op.bitmap); 46080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 46180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik case 1: 462ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv EXPECT_EQ(transpBitmap.get(), op.bitmap); 46380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik break; 46480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik default: 46580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik ADD_FAILURE() << "Only two ops expected."; 46680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 46780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik } 46880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }; 46980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 47006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 50, 50, 47180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 47280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 47380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik canvas.drawRect(0, 0, 50, 50, SkPaint()); 474aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*transpBitmap, 0, 0, nullptr); 47580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 47680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik // only the below draws should remain, since they're 477aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*opaqueBitmap, 0, 0, nullptr); 478aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*transpBitmap, 0, 0, nullptr); 47980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik }); 4809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50, 4819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 4829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 48380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 48480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik EXPECT_EQ(5u, node->getDisplayList()->getOps().size()) 48580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik << "Recording must not have rejected ops, in order for this test to be valid"; 48680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 48780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik AvoidOverdrawBitmapsTestRenderer renderer; 48880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 489a82ffc549bd6dbf8cfc6f4d646d0f458dca54014sergeyv EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops"; 49080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik} 49180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik 49298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clippedMerging) { 49393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik class ClippedMergingTestRenderer : public TestRendererBase { 49493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik public: 49593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik void onMergedBitmapOps(const MergedBakedOpList& opList) override { 49693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(0, mIndex); 49793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik mIndex += opList.count; 49893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4u, opList.count); 49993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip); 50093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right, 50193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik opList.clipSideFlags); 50293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik } 50393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }; 50406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 50506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 506aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20)); 50793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 50893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // left side clipped (to inset left half) 509a0a74d5f8ee1dbd04772ffb1775d045ce6b5934bMike Reed canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace_deprecated); 510aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 0, 40, nullptr); 51193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 51293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // top side clipped (to inset top half) 513a0a74d5f8ee1dbd04772ffb1775d045ce6b5934bMike Reed canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace_deprecated); 514aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 40, 0, nullptr); 51593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 51693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // right side clipped (to inset right half) 517a0a74d5f8ee1dbd04772ffb1775d045ce6b5934bMike Reed canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace_deprecated); 518aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 80, 40, nullptr); 51993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 52093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik // bottom not clipped, just abutting (inset bottom half) 521a0a74d5f8ee1dbd04772ffb1775d045ce6b5934bMike Reed canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace_deprecated); 522aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 40, 70, nullptr); 52393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik }); 52493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 5259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 5269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 52993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik ClippedMergingTestRenderer renderer; 530f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 53193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik EXPECT_EQ(4, renderer.getIndex()); 53293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik} 53393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik 53498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, regionClipStopsMerge) { 535f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik class RegionClipStopsMergeTestRenderer : public TestRendererBase { 536f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik public: 537f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; } 538f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik }; 539f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 540f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 541f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik SkPath path; 542f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik path.addCircle(200, 200, 200, SkPath::kCW_Direction); 543f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik canvas.save(SaveFlags::MatrixClip); 5446c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipPath(&path, SkClipOp::kIntersect); 545f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik SkPaint paint; 546f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 547f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik paint.setAntiAlias(true); 548f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik paint.setTextSize(50); 549f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 550f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200); 551f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik canvas.restore(); 552f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik }); 553f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik 554f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 555f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik sLightGeometry, Caches::getInstance()); 556f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 557f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik 558f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik RegionClipStopsMergeTestRenderer renderer; 559f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 560f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik EXPECT_EQ(2, renderer.getIndex()); 561f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik} 562f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik 56398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textMerging) { 564d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik class TextMergingTestRenderer : public TestRendererBase { 565d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik public: 566d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 567d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(0, mIndex); 568d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik mIndex += opList.count; 569d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2u, opList.count); 570d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags); 571d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags); 572d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags); 573d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik } 574d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }; 57506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 57606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 577d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik SkPaint paint; 578d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 579d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setAntiAlias(true); 580d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik paint.setTextSize(50); 581dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped 582dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped 583d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik }); 5849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 5859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 5869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 5879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 588d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik TextMergingTestRenderer renderer; 589f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 590d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops"; 591d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik} 592d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 59398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStrikethrough) { 594a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik const int LOOPS = 5; 595a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik class TextStrikethroughTestRenderer : public TestRendererBase { 596a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik public: 597a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 598a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text"; 599a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 60015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 60115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(0, mIndex); 60215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik mIndex += opList.count; 60315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik EXPECT_EQ(5u, opList.count); 604a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 605a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }; 60606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 2000, 6078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 608a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik SkPaint textPaint; 609a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setAntiAlias(true); 610a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik textPaint.setTextSize(20); 611f77ca0872102116f58693d26703af8279573d014Derek Sollenberger textPaint.setFlags(textPaint.getFlags() | SkPaint::kStrikeThruText_ReserveFlag); 61242a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 613a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik for (int i = 0; i < LOOPS; i++) { 614dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1)); 615a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik } 616a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik }); 6179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 6189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000, 6199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 622a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik TextStrikethroughTestRenderer renderer; 623f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 624a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik EXPECT_EQ(2 * LOOPS, renderer.getIndex()) 625d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik << "Expect number of ops = 2 * loop count"; 626b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 627b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 6287c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = { 6297c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style }; 6307c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 63198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStyle) { 6327c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik class TextStyleTestRenderer : public TestRendererBase { 6337c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik public: 6347c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik void onMergedTextOps(const MergedBakedOpList& opList) override { 6357c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, mIndex); 6367c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(3u, opList.count); 6377c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik mIndex += opList.count; 6387c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 6397c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik int index = 0; 6407c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 6417c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik auto state = opList.states[index++]; 6427c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(style, state->op->paint->getStyle()) 6437c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Remainder of validation relies upon stable merged order"; 6447c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik ASSERT_EQ(0, state->computedState.clipSideFlags) 6457c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Clipped bounds validation requires unclipped ops"; 6467c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 6477c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 6487c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect fill = opList.states[0]->computedState.clippedBounds; 6497c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect stroke = opList.states[1]->computedState.clippedBounds; 6507c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds) 6517c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik << "Stroke+Fill should be same as stroke"; 6527c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 6537c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_TRUE(stroke.contains(fill)); 6547c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_FALSE(fill.contains(stroke)); 6557c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 65679abbf22d4f672208327546661e694d837f564a9Derek Sollenberger // outset by half the stroke width 6577c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik Rect outsetFill(fill); 65879abbf22d4f672208327546661e694d837f564a9Derek Sollenberger outsetFill.outset(5); 6597c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(stroke, outsetFill); 6607c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 6617c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }; 66206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 66306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 6647c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik SkPaint paint; 6657c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 6667c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setAntiAlias(true); 6677c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setTextSize(50); 6687c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStrokeWidth(10); 6697c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 6707c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // draw 3 copies of the same text overlapping, each with a different style. 6717c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik // They'll get merged, but with 6727c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik for (auto style : styles) { 6737c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik paint.setStyle(style); 674dccca44ffda4836b56a21da95a046c9708ffd49csergeyv TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); 6757c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik } 6767c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik }); 6779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 6789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 6799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 6807c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik TextStyleTestRenderer renderer; 6817c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 6827c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops"; 6837c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik} 6847c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik 68598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_clipLocalMatrix) { 686aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase { 687d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik public: 688d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 689d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(0, mIndex++); 690e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect()); 691d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds); 692d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 693d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik Matrix4 expected; 694d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik expected.loadTranslate(5, 5, 0); 695d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 696d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik } 697d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }; 698d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 699d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 700243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik SkMatrix::MakeTrans(5, 5)); 701d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 70206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 703d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 704eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 7056c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect); 706d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawLayer(layerUpdater.get()); 707d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.restore(); 708d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik }); 7099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 7109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 7129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 7139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 714aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerClipLocalMatrixTestRenderer renderer; 715f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 716d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik EXPECT_EQ(1, renderer.getIndex()); 717d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik} 718d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 71998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_combineMatrices) { 720aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik class TextureLayerCombineMatricesTestRenderer : public TestRendererBase { 721aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik public: 722aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override { 723aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(0, mIndex++); 724aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 725aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik Matrix4 expected; 726aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik expected.loadTranslate(35, 45, 0); 727aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 728aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik } 729aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }; 730aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 731aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 732aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 733aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 73406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 735aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 736aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.save(SaveFlags::MatrixClip); 737aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.translate(30, 40); 738aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 739aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.restore(); 740aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 741aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 7429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 7449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 7459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 746aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik TextureLayerCombineMatricesTestRenderer renderer; 747aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 748aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik EXPECT_EQ(1, renderer.getIndex()); 749aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 750aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 75198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_reject) { 752aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100, 753aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik SkMatrix::MakeTrans(5, 5)); 75498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel EXPECT_EQ(Layer::Api::OpenGL, layerUpdater->backingLayer()->getApi()); 7558cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel 7568cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer()); 7578cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel glLayer->setRenderTarget(GL_NONE); // Should be rejected 758aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 75906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 760aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) { 761aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik canvas.drawLayer(layerUpdater.get()); 762aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik }); 7639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 7649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 7669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 7679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 768aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik FailRenderer renderer; 769aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 770aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik} 771aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik 77298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, functor_reject) { 773223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik class FunctorTestRenderer : public TestRendererBase { 774223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik public: 775223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override { 776223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(0, mIndex++); 777223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik } 778223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }; 779223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik Functor noopFunctor; 780223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 781223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik // 1 million pixel tall view, scrolled down 80% 78206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto scrolledFunctorView = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 1000000, 783223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) { 784223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik canvas.translate(0, -800000); 785cd1c3eba69d044b551cededad75474038f919890John Reck canvas.callDrawGLFunction(&noopFunctor, nullptr); 786223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik }); 787223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 7889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 7893a5811b50157e7ba50854caf957e806aee794d39Chris Craik sLightGeometry, Caches::getInstance()); 7909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(scrolledFunctorView)); 7919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 792223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik FunctorTestRenderer renderer; 793223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 794223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected"; 795223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik} 796223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik 79798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferColorOp_unbounded) { 798a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik class ColorTestRenderer : public TestRendererBase { 799a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik public: 800a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 801a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(0, mIndex++); 802a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds) 803a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik << "Color op should be expanded to bounds of surrounding"; 804a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik } 805a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }; 806a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 80706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(0, 0, 10, 10, 808a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 809a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik props.setClipToBounds(false); 810260ab726486317496bc12a57d599ea96dcde3284Mike Reed canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 811a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik }); 812a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 8139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 814a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik sLightGeometry, Caches::getInstance()); 8159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(unclippedColorView)); 8169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 817a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik ColorTestRenderer renderer; 818a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 819a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected"; 820a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik} 821a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik 822e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderNode) { 823d3daa3198e2212c985c634821682d5819346b653Chris Craik class RenderNodeTestRenderer : public TestRendererBase { 824d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 825d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 826d3daa3198e2212c985c634821682d5819346b653Chris Craik switch(mIndex++) { 827d3daa3198e2212c985c634821682d5819346b653Chris Craik case 0: 8285430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 829d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 830d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 831d3daa3198e2212c985c634821682d5819346b653Chris Craik case 1: 832d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds); 833d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 834d3daa3198e2212c985c634821682d5819346b653Chris Craik break; 835d3daa3198e2212c985c634821682d5819346b653Chris Craik default: 836d3daa3198e2212c985c634821682d5819346b653Chris Craik ADD_FAILURE(); 837d3daa3198e2212c985c634821682d5819346b653Chris Craik } 838d3daa3198e2212c985c634821682d5819346b653Chris Craik } 839d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 840d3daa3198e2212c985c634821682d5819346b653Chris Craik 84106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 8428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 843b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik SkPaint paint; 844b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik paint.setColor(SK_ColorWHITE); 845b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvas.drawRect(0, 0, 100, 100, paint); 846b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 847b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 84806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 849d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik [&child](RenderProperties& props, RecordingCanvas& canvas) { 850ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik SkPaint paint; 851ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik paint.setColor(SK_ColorDKGRAY); 852ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.drawRect(0, 0, 200, 200, paint); 853ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 854eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 855ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.translate(40, 40); 856d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik canvas.drawRenderNode(child.get()); 857ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik canvas.restore(); 858b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik }); 859b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 8609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 8619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 8639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8645854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik RenderNodeTestRenderer renderer; 865f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 866223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik EXPECT_EQ(2, renderer.getIndex()); 867b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 868b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 86998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clipped) { 870d3daa3198e2212c985c634821682d5819346b653Chris Craik class ClippedTestRenderer : public TestRendererBase { 871d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 872d3daa3198e2212c985c634821682d5819346b653Chris Craik void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override { 873d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 874d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds); 875e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect()); 876d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 877d3daa3198e2212c985c634821682d5819346b653Chris Craik } 878d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 879d3daa3198e2212c985c634821682d5819346b653Chris Craik 88006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 8818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 882aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv sk_sp<Bitmap> bitmap(TestUtils::createBitmap(200, 200)); 883aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv canvas.drawBitmap(*bitmap, 0, 0, nullptr); 884ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik }); 885ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 8869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik // clip to small area, should see in receiver 8879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200, 8889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 8899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 8909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 8915854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik ClippedTestRenderer renderer; 892f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 893ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik} 894ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik 89598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_simple) { 896d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerSimpleTestRenderer : public TestRendererBase { 897d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 898d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 899d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 900d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, width); 901d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(180u, height); 902d3daa3198e2212c985c634821682d5819346b653Chris Craik return nullptr; 903d3daa3198e2212c985c634821682d5819346b653Chris Craik } 904d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 905d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 906d3daa3198e2212c985c634821682d5819346b653Chris Craik } 907d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 908d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 909d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds); 9105430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds); 911e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(180, 180), state.computedState.clipRect()); 912d3daa3198e2212c985c634821682d5819346b653Chris Craik 913d3daa3198e2212c985c634821682d5819346b653Chris Craik Matrix4 expectedTransform; 914d3daa3198e2212c985c634821682d5819346b653Chris Craik expectedTransform.loadTranslate(-10, -10, 0); 915d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform); 916d3daa3198e2212c985c634821682d5819346b653Chris Craik } 917d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 918d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 919d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 920e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 921d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 922d3daa3198e2212c985c634821682d5819346b653Chris Craik } 92374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 92474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 92574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(nullptr, offscreenBuffer); 92674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 927d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 928d3daa3198e2212c985c634821682d5819346b653Chris Craik 92906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 9308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 931eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer); 9326fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(10, 10, 190, 190, SkPaint()); 9336fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 9346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 9359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 9369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 9379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 9389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 9399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 9405854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerSimpleTestRenderer renderer; 941f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 94274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, renderer.getIndex()); 943b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 9446fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 94598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) { 946d3daa3198e2212c985c634821682d5819346b653Chris Craik /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as: 947d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer2, rect2 endLayer2 948d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer1, rect1, drawLayer2, endLayer1 949d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, layerOp1, endFrame 950d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 951d3daa3198e2212c985c634821682d5819346b653Chris Craik class SaveLayerNestedTestRenderer : public TestRendererBase { 952d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 953d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 954d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 955d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 956d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, width); 957d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(400u, height); 958d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x400; 959d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 3) { 960d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, width); 961d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(800u, height); 962d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) 0x800; 963d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 964d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*) nullptr; 965d3daa3198e2212c985c634821682d5819346b653Chris Craik } 966d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 967d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 968d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 6); 969d3daa3198e2212c985c634821682d5819346b653Chris Craik } 97098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 971d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(7, mIndex++); 972d3daa3198e2212c985c634821682d5819346b653Chris Craik } 973e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 974d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(9, mIndex++); 975d3daa3198e2212c985c634821682d5819346b653Chris Craik } 976d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 977d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 978d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 9795430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect 980d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 4) { 9815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect 982d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 983d3daa3198e2212c985c634821682d5819346b653Chris Craik } 984d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 985d3daa3198e2212c985c634821682d5819346b653Chris Craik const int index = mIndex++; 986d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 5) { 987d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle); 9885430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer 989d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 990d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle); 9915430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer 992d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 993d3daa3198e2212c985c634821682d5819346b653Chris Craik } 99474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 99574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik const int index = mIndex++; 99674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik // order isn't important, but we need to see both 99774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik if (index == 10) { 99874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer); 99974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else if (index == 11) { 100074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer); 100174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } else { ADD_FAILURE(); } 100274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1003d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1004d3daa3198e2212c985c634821682d5819346b653Chris Craik 100506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 800, 800, 10068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1007eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer); 10086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 10096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 800, 800, SkPaint()); 1010eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer); 10116fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik { 10126fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 10136fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 10146fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 10156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik } 10166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 10176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 10186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 10199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800, 10209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 10219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 10229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 10235854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik SaveLayerNestedTestRenderer renderer; 1024f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 102574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, renderer.getIndex()); 10266fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} 10276fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 102898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_contentRejection) { 102906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 10308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1031eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 10326c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); 1033eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer); 10346fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 10356fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // draw within save layer may still be recorded, but shouldn't be drawn 10366fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.drawRect(200, 200, 400, 400, SkPaint()); 10376fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 10386fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 10396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik canvas.restore(); 10406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik }); 10419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 10429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 10439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 10449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 10456fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 10465854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik FailRenderer renderer; 10476fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik // should see no ops, even within the layer, since the layer should be rejected 1048f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1049b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} 10506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik 105198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_simple) { 1052b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase { 1053b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1054b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1055b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); 1056b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 10577435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 1058b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1059b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1060b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1061b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(1, mIndex++); 1062b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_NE(nullptr, op.paint); 1063260ab726486317496bc12a57d599ea96dcde3284Mike Reed ASSERT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint)); 1064b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1065b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1066b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(2, mIndex++); 1067b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), op.unmappedBounds); 1068b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds); 1069b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(200, 200), state.computedState.clipRect()); 1070b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1071b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1072b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1073b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 1074b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds); 10757435eb148e72382126e9073183e881357bb38a8bChris Craik EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState); 1076b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1077b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1078b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1079b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 108006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1081b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1082eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 1083b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 1084b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1085b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 10869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 10879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 10889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 10899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 10909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1091b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedSimpleTestRenderer renderer; 1092f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1093b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, renderer.getIndex()); 1094b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1095b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 109698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_round) { 1097d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik class SaveLayerUnclippedRoundTestRenderer : public TestRendererBase { 1098d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik public: 1099d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1100d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(0, mIndex++); 1101d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds) 1102d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik << "Bounds rect should round out"; 1103d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik } 1104d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {} 1105d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override {} 1106d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1107d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(1, mIndex++); 1108d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds) 1109d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik << "Bounds rect should round out"; 1110d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik } 1111d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik }; 1112d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 111306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1114d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1115d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out 1116d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 128, (SaveFlags::Flags)(0)); 1117d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 1118d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik canvas.restore(); 1119d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik }); 1120d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 1121d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 1122d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik sLightGeometry, Caches::getInstance()); 1123d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 1124d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 1125d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik SaveLayerUnclippedRoundTestRenderer renderer; 1126d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1127d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik EXPECT_EQ(2, renderer.getIndex()); 1128d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik} 1129d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik 113098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) { 1131b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase { 1132b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1133b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1134b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1135b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_GT(4, index); 1136b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getWidth()); 1137b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, op.unmappedBounds.getHeight()); 1138b87eadda1818034ce03d85f30388384d1ac65916Chris Craik if (index == 0) { 1139b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds); 1140b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 1) { 1141b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds); 1142b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 2) { 1143b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds); 1144b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } else if (index == 3) { 1145b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds); 1146b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1147b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1148b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1149b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(4, mIndex++); 1150b87eadda1818034ce03d85f30388384d1ac65916Chris Craik ASSERT_EQ(op.vertexCount, 16u); 1151b87eadda1818034ce03d85f30388384d1ac65916Chris Craik for (size_t i = 0; i < op.vertexCount; i++) { 1152b87eadda1818034ce03d85f30388384d1ac65916Chris Craik auto v = op.vertices[i]; 1153b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200); 1154b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200); 1155b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1156b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1157b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1158b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1159b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1160b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1161b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_LT(5, mIndex++); 1162b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1163b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1164b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 116506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1166b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1167b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 1168eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int restoreTo = canvas.save(SaveFlags::MatrixClip); 1169b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.scale(2, 2); 1170eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip); 1171eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip); 1172eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip); 1173eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip); 1174b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(0, 0, 100, 100, SkPaint()); 1175b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restoreToCount(restoreTo); 1176b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 11779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 11789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 11799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 11809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 11819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1182b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedMergedClearsTestRenderer renderer; 1183f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1184b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(10, renderer.getIndex()) 1185b87eadda1818034ce03d85f30388384d1ac65916Chris Craik << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect."; 1186b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1187b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 118898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_clearClip) { 11894876de16e34622634266d09522c9153c78c7c2fbChris Craik class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase { 11904876de16e34622634266d09522c9153c78c7c2fbChris Craik public: 11914876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 11924876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(0, mIndex++); 11934876de16e34622634266d09522c9153c78c7c2fbChris Craik } 11944876de16e34622634266d09522c9153c78c7c2fbChris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 11954876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(1, mIndex++); 11964876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, op.paint); 1197260ab726486317496bc12a57d599ea96dcde3284Mike Reed EXPECT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint)); 11984876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds) 11994876de16e34622634266d09522c9153c78c7c2fbChris Craik << "Expect dirty rect as clip"; 12004876de16e34622634266d09522c9153c78c7c2fbChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 12014876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect); 12024876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 12034876de16e34622634266d09522c9153c78c7c2fbChris Craik } 12044876de16e34622634266d09522c9153c78c7c2fbChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 12054876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(2, mIndex++); 12064876de16e34622634266d09522c9153c78c7c2fbChris Craik } 12074876de16e34622634266d09522c9153c78c7c2fbChris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 12084876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(3, mIndex++); 12094876de16e34622634266d09522c9153c78c7c2fbChris Craik } 12104876de16e34622634266d09522c9153c78c7c2fbChris Craik }; 12114876de16e34622634266d09522c9153c78c7c2fbChris Craik 121206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 12134876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 12144876de16e34622634266d09522c9153c78c7c2fbChris Craik // save smaller than clip, so we get unclipped behavior 12154876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0)); 12164876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(0, 0, 200, 200, SkPaint()); 12174876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 12184876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 12194876de16e34622634266d09522c9153c78c7c2fbChris Craik 12204876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty, and assert we see that rect later 12219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200, 12229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 12239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 12249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 12254876de16e34622634266d09522c9153c78c7c2fbChris Craik SaveLayerUnclippedClearClipTestRenderer renderer; 12264876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 12274876de16e34622634266d09522c9153c78c7c2fbChris Craik EXPECT_EQ(4, renderer.getIndex()); 12284876de16e34622634266d09522c9153c78c7c2fbChris Craik} 12294876de16e34622634266d09522c9153c78c7c2fbChris Craik 123098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_reject) { 123106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 12324876de16e34622634266d09522c9153c78c7c2fbChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 12334876de16e34622634266d09522c9153c78c7c2fbChris Craik // unclipped savelayer + rect both in area that won't intersect with dirty 12344876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0)); 12354876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.drawRect(100, 100, 200, 200, SkPaint()); 12364876de16e34622634266d09522c9153c78c7c2fbChris Craik canvas.restore(); 12374876de16e34622634266d09522c9153c78c7c2fbChris Craik }); 12384876de16e34622634266d09522c9153c78c7c2fbChris Craik 12394876de16e34622634266d09522c9153c78c7c2fbChris Craik // draw with partial screen dirty that doesn't intersect with savelayer 12409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, 12419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 12429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 12439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 12444876de16e34622634266d09522c9153c78c7c2fbChris Craik FailRenderer renderer; 12454876de16e34622634266d09522c9153c78c7c2fbChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 12464876de16e34622634266d09522c9153c78c7c2fbChris Craik} 12474876de16e34622634266d09522c9153c78c7c2fbChris Craik 1248b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as: 1249b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer 1250b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe 1251b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */ 125298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_complex) { 1253b87eadda1818034ce03d85f30388384d1ac65916Chris Craik class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase { 1254b87eadda1818034ce03d85f30388384d1ac65916Chris Craik public: 1255b87eadda1818034ce03d85f30388384d1ac65916Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1256b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(0, mIndex++); // savelayer first 1257b87eadda1818034ce03d85f30388384d1ac65916Chris Craik return (OffscreenBuffer*)0xabcd; 1258b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1259b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override { 1260b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1261b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 1 || index == 7); 1262b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1263b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override { 1264b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1265b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 2 || index == 8); 1266b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1267b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1268b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(3, mIndex++); 1269b87eadda1818034ce03d85f30388384d1ac65916Chris Craik Matrix4 expected; 1270b87eadda1818034ce03d85f30388384d1ac65916Chris Craik expected.loadTranslate(-100, -100, 0); 1271b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds); 1272b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform); 1273b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1274b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override { 1275b87eadda1818034ce03d85f30388384d1ac65916Chris Craik int index = mIndex++; 1276b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_TRUE(index == 4 || index == 10); 1277b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1278b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endLayer() override { 1279b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(5, mIndex++); 1280b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1281b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1282b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(6, mIndex++); 1283b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1284b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1285b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(9, mIndex++); 128674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1287b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 1288b87eadda1818034ce03d85f30388384d1ac65916Chris Craik void endFrame(const Rect& repaintRect) override { 1289b87eadda1818034ce03d85f30388384d1ac65916Chris Craik EXPECT_EQ(11, mIndex++); 1290b87eadda1818034ce03d85f30388384d1ac65916Chris Craik } 129174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 129274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(12, mIndex++); 129374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer); 129474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1295b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }; 1296b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 129706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 600, 600, // 500x500 triggers clipping 1298b87eadda1818034ce03d85f30388384d1ac65916Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1299eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped 1300eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped 1301eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped 1302b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.drawRect(200, 200, 300, 300, SkPaint()); 1303b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1304b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1305b87eadda1818034ce03d85f30388384d1ac65916Chris Craik canvas.restore(); 1306b87eadda1818034ce03d85f30388384d1ac65916Chris Craik }); 13079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 13089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600, 13099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 13109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 13119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1312b87eadda1818034ce03d85f30388384d1ac65916Chris Craik SaveLayerUnclippedComplexTestRenderer renderer; 1313f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 131474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, renderer.getIndex()); 1315b87eadda1818034ce03d85f30388384d1ac65916Chris Craik} 1316b87eadda1818034ce03d85f30388384d1ac65916Chris Craik 131798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_simple) { 1318d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerSimpleTestRenderer : public TestRendererBase { 1319d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 132098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1321d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 132298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 132398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 132498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 1325d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1326d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1327d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 13280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1329d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 1330d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Transform should be reset within layer"; 1331d3daa3198e2212c985c634821682d5819346b653Chris Craik 1332e4db79de127cfe961195f52907af8451026eaa20Chris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 1333d3daa3198e2212c985c634821682d5819346b653Chris Craik << "Damage rect should be used to clip layer content"; 1334d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1335d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1336d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(2, mIndex++); 1337d3daa3198e2212c985c634821682d5819346b653Chris Craik } 133898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1339d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); 1340d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1341d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1342d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(4, mIndex++); 1343d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1344e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1345d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(5, mIndex++); 1346d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1347d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 13480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 134906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 135016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 135116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 13520b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 13530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 13540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 135516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 135698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 13570b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 135898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would 135998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 136098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 13610b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(node); 13630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // only enqueue partial damage 136598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 13660b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 13670b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 13699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 13709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 13719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 13729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 13730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerSimpleTestRenderer renderer; 1374f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 13750b7e8245db728d127ada698be63d78b33fc6e4daChris Craik EXPECT_EQ(6, renderer.getIndex()); 13760b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 13770b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointer, so we can safely destruct RenderNode 137898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 13790b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 13800b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 138198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) { 1382d3daa3198e2212c985c634821682d5819346b653Chris Craik /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as: 1383d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(child), rect(grey), endLayer 1384d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startTemporaryLayer, drawLayer(child), endLayer 1385d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer 1386d3daa3198e2212c985c634821682d5819346b653Chris Craik * - startFrame, drawLayer(parent), endLayerb 1387d3daa3198e2212c985c634821682d5819346b653Chris Craik */ 1388d3daa3198e2212c985c634821682d5819346b653Chris Craik class HwLayerComplexTestRenderer : public TestRendererBase { 1389d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1390d3daa3198e2212c985c634821682d5819346b653Chris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) { 1391d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(3, mIndex++); // savelayer first 1392d3daa3198e2212c985c634821682d5819346b653Chris Craik return (OffscreenBuffer*)0xabcd; 1393d3daa3198e2212c985c634821682d5819346b653Chris Craik } 139498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1395d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1396d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 0) { 1397d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting inner layer 139898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 139998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 1400d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 6) { 1401d3daa3198e2212c985c634821682d5819346b653Chris Craik // starting outer layer 140298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportWidth); 140398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, offscreenBuffer->viewportHeight); 1404d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1405d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1406d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1407d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1408d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 1) { 1409d3daa3198e2212c985c634821682d5819346b653Chris Craik // inner layer's rect (white) 1410d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 1411d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 7) { 1412d3daa3198e2212c985c634821682d5819346b653Chris Craik // outer layer's rect (grey) 1413d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1414d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1415d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1416d3daa3198e2212c985c634821682d5819346b653Chris Craik void endLayer() override { 1417d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1418d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_TRUE(index == 2 || index == 5 || index == 9); 1419d3daa3198e2212c985c634821682d5819346b653Chris Craik } 142098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 1421d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(10, mIndex++); 1422d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1423d3daa3198e2212c985c634821682d5819346b653Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 142498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* layer = *op.layerHandle; 1425d3daa3198e2212c985c634821682d5819346b653Chris Craik int index = mIndex++; 1426d3daa3198e2212c985c634821682d5819346b653Chris Craik if (index == 4) { 142798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportWidth); 142898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(100u, layer->viewportHeight); 1429d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 8) { 1430d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle); 1431d3daa3198e2212c985c634821682d5819346b653Chris Craik } else if (index == 11) { 143298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportWidth); 143398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(200u, layer->viewportHeight); 1434d3daa3198e2212c985c634821682d5819346b653Chris Craik } else { ADD_FAILURE(); } 1435d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1436e4db79de127cfe961195f52907af8451026eaa20Chris Craik void endFrame(const Rect& repaintRect) override { 1437d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(12, mIndex++); 1438d3daa3198e2212c985c634821682d5819346b653Chris Craik } 143974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 144074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(13, mIndex++); 144174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 1442d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1443d3daa3198e2212c985c634821682d5819346b653Chris Craik 144406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150, 144516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 144616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 14470b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 14480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorWHITE); 14490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 100, 100, paint); 145016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 145198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100); 145298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(child->getLayerHandle()) = &childLayer; 14530b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik RenderNode* childPtr = child.get(); 145506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 145616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [childPtr](RenderProperties& props, RecordingCanvas& canvas) { 145716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 14580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik SkPaint paint; 14590b7e8245db728d127ada698be63d78b33fc6e4daChris Craik paint.setColor(SK_ColorDKGRAY); 14600b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRect(0, 0, 200, 200, paint); 14610b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 1462eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer); 14630b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.drawRenderNode(childPtr); 14640b7e8245db728d127ada698be63d78b33fc6e4daChris Craik canvas.restore(); 146516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 146698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200); 146798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *(parent->getLayerHandle()) = &parentLayer; 14680b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 14700b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 147198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 14720b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100)); 14730b7e8245db728d127ada698be63d78b33fc6e4daChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200)); 14740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 14769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 14779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 14789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 14799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 14800b7e8245db728d127ada698be63d78b33fc6e4daChris Craik HwLayerComplexTestRenderer renderer; 1481f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 148274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(14, renderer.getIndex()); 14830b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14840b7e8245db728d127ada698be63d78b33fc6e4daChris Craik // clean up layer pointers, so we can safely destruct RenderNodes 14850b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(child->getLayerHandle()) = nullptr; 14860b7e8245db728d127ada698be63d78b33fc6e4daChris Craik *(parent->getLayerHandle()) = nullptr; 14870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik} 14880b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 14896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 149098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) { 14916246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik class BuildLayerTestRenderer : public TestRendererBase { 14926246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik public: 14936246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 14946246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(0, mIndex++); 14956246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportWidth); 14966246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(100u, offscreenBuffer->viewportHeight); 14976246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect); 14986246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 14996246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 15006246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(1, mIndex++); 15016246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15026246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()) 15036246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Transform should be reset within layer"; 15046246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15056246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect()) 15066246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik << "Damage rect should be used to clip layer content"; 15076246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 15086246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endLayer() override { 15096246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(2, mIndex++); 15106246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 15116246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override { 15126246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 15136246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 15146246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik void endFrame(const Rect& repaintRect) override { 15156246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik ADD_FAILURE() << "Primary frame draw not expected in this test"; 15166246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik } 15176246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }; 15186246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 151906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110, 15206246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 15216246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik props.mutateLayerProperties().setType(LayerType::RenderLayer); 1522260ab726486317496bc12a57d599ea96dcde3284Mike Reed canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 15236246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik }); 15246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer** layerHandle = node->getLayerHandle(); 15256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // create RenderNode's layer here in same way prepareTree would 15276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 15286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = &layer; 15296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik TestUtils::syncHierarchyPropertiesAndDisplayList(node); 15316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15326246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // only enqueue partial damage 15336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 15346246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75)); 15356246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15366246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // Draw, but pass empty node list, so no work is done for primary frame 15379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(layerUpdateQueue, sLightGeometry, Caches::getInstance()); 15386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik BuildLayerTestRenderer renderer; 15396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 15406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik EXPECT_EQ(3, renderer.getIndex()); 15416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 15426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik // clean up layer pointer, so we can safely destruct RenderNode 15436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik *layerHandle = nullptr; 15446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik} 15456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik 1546db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace { 1547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 154806152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) { 1549161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik SkPaint paint; 1550814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik // order put in blue channel, transparent so overlapped content doesn't get rejected 1551814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder)); 1552161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRect(0, 0, 100, 100, paint); 1553161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 155406152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) { 155506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 15568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) { 1557161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, expectedDrawOrder); 1558161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 1559161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->mutateStagingProperties().setTranslationZ(z); 1560161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z); 1561161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1562161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik} 1563db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 1564db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, 1565db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev std::function<void(RenderProperties& props, RecordingCanvas& canvas)> setup) { 1566db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 1567db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [expectedDrawOrder, setup](RenderProperties& props, RecordingCanvas& canvas) { 1568db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedRect(&canvas, expectedDrawOrder); 1569db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev if (setup) { 1570db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev setup(props, canvas); 1571d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1572db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); 1573db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership 1574db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 1575db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 1576db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievclass ZReorderTestRenderer : public TestRendererBase { 1577db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievpublic: 1578db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev void onRectOp(const RectOp& op, const BakedOpState& state) override { 1579db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel 1580db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order"; 1581db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } 1582db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}; 1583db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 1584db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} // end anonymous namespace 1585d3daa3198e2212c985c634821682d5819346b653Chris Craik 158698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, zReorder) { 158706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 15888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 1589347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev canvas.insertReorderBarrier(true); 1590347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev canvas.insertReorderBarrier(false); 1591161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder 1592161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 1); 1593161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(true); 1594161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 6, 2.0f); 1595161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 3); 1596161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 4, 0.0f); 1597161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 5); 1598161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 2, -2.0f); 1599161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 7, 2.0f); 1600161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik canvas.insertReorderBarrier(false); 1601161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedRect(&canvas, 8); 1602161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder 160388e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op 160488e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedRect(&canvas, 11); 160588e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedNode(&canvas, 10, -1.0f); 160688e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(false); 160788e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); //test with two empty reorder sections 160888e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(true); 160988e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev canvas.insertReorderBarrier(false); 161088e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev drawOrderedRect(&canvas, 12); 1611161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik }); 16129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 16139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 16149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 16159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1616161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik ZReorderTestRenderer renderer; 1617f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 161888e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev EXPECT_EQ(13, renderer.getIndex()); 1619161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}; 1620161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 162198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorder) { 16228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollX = 5; 16238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik static const int scrollY = 10; 16248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik class ProjectionReorderTestRenderer : public TestRendererBase { 16258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik public: 16268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 16278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik const int index = mIndex++; 16288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 16298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik Matrix4 expectedMatrix; 16308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik switch (index) { 16318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 0: 16328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 100), op.unmappedBounds); 16338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorWHITE, op.paint->getColor()); 16348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadIdentity(); 1635678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 16368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 16378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 1: 16388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds); 16398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor()); 1640678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0); 1641678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1642678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-35, -30, 45, 50), 1643678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 16448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 16458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik case 2: 16468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(Rect(100, 50), op.unmappedBounds); 16478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(SK_ColorBLUE, op.paint->getColor()); 16488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0); 1649678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask); 16508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik break; 16518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik default: 16528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ADD_FAILURE(); 16538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 1654678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expectedMatrix, state.computedState.transform); 16558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik } 16568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }; 16578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 16588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 16598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C) 16608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * with a projecting child (P) of its own. P would normally draw between B and C's "background" 16618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * draw, but because it is projected backwards, it's drawn in between B and C. 16628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 16638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * The parent is scrolled by scrollX/scrollY, but this does not affect the background 16648d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * (which isn't affected by scroll). 16658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 166606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 16678d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 16688d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectionReceiver(true); 16698d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 16708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 16718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationX(scrollX); 16728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setTranslationY(scrollY); 16738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 16748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 16758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorWHITE); 16768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 100, paint); 16778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 167806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto projectingRipple = TestUtils::createNode<RecordingCanvas>(50, 0, 100, 50, 16798d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 16808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setProjectBackwards(true); 16818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik properties.setClipToBounds(false); 16828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 16838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorDKGRAY); 16848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(-10, -10, 60, 60, paint); 16858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 168606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(0, 50, 100, 100, 16878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 16888d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik SkPaint paint; 16898d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik paint.setColor(SK_ColorBLUE); 16908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRect(0, 0, 100, 50, paint); 16918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(projectingRipple.get()); 16928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 169306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 16948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1695678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1696678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f); 1697678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1698eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 16998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 17008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(receiverBackground.get()); 17018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.drawRenderNode(child.get()); 17028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik canvas.restore(); 17038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik }); 17048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 17059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 17069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 17079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 17089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 17098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik ProjectionReorderTestRenderer renderer; 1710f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 17118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik EXPECT_EQ(3, renderer.getIndex()); 17128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik} 17138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik 171498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionHwLayer) { 1715678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollX = 5; 1716678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik static const int scrollY = 10; 1717678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik class ProjectionHwLayerTestRenderer : public TestRendererBase { 1718678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik public: 1719678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 1720678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(0, mIndex++); 1721678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1722678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onArcOp(const ArcOp& op, const BakedOpState& state) override { 1723678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(1, mIndex++); 1724678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1725678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1726678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void endLayer() override { 1727678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(2, mIndex++); 1728678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1729678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1730678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(3, mIndex++); 1731678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1732678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1733678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1734678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(4, mIndex++); 1735678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_NE(nullptr, state.computedState.localProjectionPathMask); 1736678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 expected; 1737678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik expected.loadTranslate(100 - scrollX, 100 - scrollY, 0); 1738678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(expected, state.computedState.transform); 1739678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(Rect(-85, -80, 295, 300), 1740678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Rect(state.computedState.localProjectionPathMask->getBounds())); 1741678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1742678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 1743678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(5, mIndex++); 1744678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask); 1745678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik } 1746678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }; 174706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1748678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1749678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectionReceiver(true); 1750678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // scroll doesn't apply to background, so undone via translationX/Y 1751678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1752678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationX(scrollX); 1753678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setTranslationY(scrollY); 1754678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1755678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1756678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 175706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1758678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1759678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setProjectBackwards(true); 1760678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.setClipToBounds(false); 1761678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds 1762678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 176306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(100, 100, 300, 300, 1764678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1765678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutateLayerProperties().setType(LayerType::RenderLayer); 1766678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(projectingRipple.get()); 1767678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint()); 1768678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 176906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1770678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1771678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // Set a rect outline for the projecting ripple to be masked against. 1772678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f); 1773678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1774678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(receiverBackground.get()); 1775678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik canvas.drawRenderNode(child.get()); 1776678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik }); 1777678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1778678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer** layerHandle = child->getLayerHandle(); 1779678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1780678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 1781678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200); 1782678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik Matrix4 windowTransform; 1783678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin 1784678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layer.setWindowTransform(windowTransform); 1785678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = &layer; 1786678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 17879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 17889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1789678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 1790678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200)); 17919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 17929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 17939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 17949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 17959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 17969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1797678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik ProjectionHwLayerTestRenderer renderer; 1798678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1799678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik EXPECT_EQ(6, renderer.getIndex()); 1800678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 1801678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik // clean up layer pointer, so we can safely destruct RenderNode 1802678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik *layerHandle = nullptr; 1803678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik} 1804678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik 180598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionChildScroll) { 1806a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollX = 500000; 1807a748c08241e43fc68c7c34767d819aef5183936eChris Craik static const int scrollY = 0; 1808a748c08241e43fc68c7c34767d819aef5183936eChris Craik class ProjectionChildScrollTestRenderer : public TestRendererBase { 1809a748c08241e43fc68c7c34767d819aef5183936eChris Craik public: 1810a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1811a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(0, mIndex++); 1812a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1813a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1814a748c08241e43fc68c7c34767d819aef5183936eChris Craik void onOvalOp(const OvalOp& op, const BakedOpState& state) override { 1815a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(1, mIndex++); 1816a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_NE(nullptr, state.computedState.clipState); 1817a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode); 1818a748c08241e43fc68c7c34767d819aef5183936eChris Craik ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect); 1819a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_TRUE(state.computedState.transform.isIdentity()); 1820a748c08241e43fc68c7c34767d819aef5183936eChris Craik } 1821a748c08241e43fc68c7c34767d819aef5183936eChris Craik }; 182206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1823a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1824a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectionReceiver(true); 1825a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRect(0, 0, 400, 400, SkPaint()); 1826a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 182706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 1828a748c08241e43fc68c7c34767d819aef5183936eChris Craik [](RenderProperties& properties, RecordingCanvas& canvas) { 1829a748c08241e43fc68c7c34767d819aef5183936eChris Craik // scroll doesn't apply to background, so undone via translationX/Y 1830a748c08241e43fc68c7c34767d819aef5183936eChris Craik // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver! 1831a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationX(scrollX); 1832a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setTranslationY(scrollY); 1833a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setProjectBackwards(true); 1834a748c08241e43fc68c7c34767d819aef5183936eChris Craik properties.setClipToBounds(false); 1835a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawOval(0, 0, 200, 200, SkPaint()); 1836a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 183706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1838a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) { 1839a748c08241e43fc68c7c34767d819aef5183936eChris Craik // Record time clip will be ignored by projectee 18406c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect); 1841a748c08241e43fc68c7c34767d819aef5183936eChris Craik 1842a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally) 1843a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(projectingRipple.get()); 1844a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 184506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400, 1846a748c08241e43fc68c7c34767d819aef5183936eChris Craik [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) { 1847a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(receiverBackground.get()); 1848a748c08241e43fc68c7c34767d819aef5183936eChris Craik canvas.drawRenderNode(child.get()); 1849a748c08241e43fc68c7c34767d819aef5183936eChris Craik }); 1850a748c08241e43fc68c7c34767d819aef5183936eChris Craik 18519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400, 18529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 18539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 18549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 1855a748c08241e43fc68c7c34767d819aef5183936eChris Craik ProjectionChildScrollTestRenderer renderer; 1856a748c08241e43fc68c7c34767d819aef5183936eChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 1857a748c08241e43fc68c7c34767d819aef5183936eChris Craik EXPECT_EQ(2, renderer.getIndex()); 1858a748c08241e43fc68c7c34767d819aef5183936eChris Craik} 1859a748c08241e43fc68c7c34767d819aef5183936eChris Craik 186098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ 186198787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) { 186206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev return TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 18638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [translationZ](RenderProperties& properties, RecordingCanvas& canvas) { 186416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.setTranslationZ(translationZ); 186516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f); 186698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik SkPaint paint; 186798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik paint.setColor(SK_ColorWHITE); 186898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRect(0, 0, 100, 100, paint); 186998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 187098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 187198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 187298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadow) { 1873d3daa3198e2212c985c634821682d5819346b653Chris Craik class ShadowTestRenderer : public TestRendererBase { 1874d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 1875d3daa3198e2212c985c634821682d5819346b653Chris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 1876d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(0, mIndex++); 187798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_FLOAT_EQ(1.0f, op.casterAlpha); 18786e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr)); 18796e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY); 188098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 188198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 expectedZ; 188298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik expectedZ.loadTranslate(0, 0, 5); 18836e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ); 1884d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1885d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 1886d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(1, mIndex++); 1887d3daa3198e2212c985c634821682d5819346b653Chris Craik } 1888d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 1889161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 189006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 18918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 189298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 189398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 1894d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 189598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 18969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 18979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 18989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 18999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 190098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowTestRenderer renderer; 1901f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 190298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, renderer.getIndex()); 190398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 190498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 190598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowSaveLayer) { 190698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowSaveLayerTestRenderer : public TestRendererBase { 190798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 190898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 190998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 191098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik return nullptr; 191198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 191298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 191398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 19146e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 19156e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 191698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 191798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 191898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 191998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 192098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 192198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 192298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 192398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 192498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 192598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 192674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 192774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(5, mIndex++); 192874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 192998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 193098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 193106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 19328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 193398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // save/restore outside of reorderBarrier, so they don't get moved out of place 193498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 1935eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer); 1936d3daa3198e2212c985c634821682d5819346b653Chris Craik canvas.insertReorderBarrier(true); 193798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 193898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(false); 193998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restoreToCount(count); 1940d3daa3198e2212c985c634821682d5819346b653Chris Craik }); 1941d3daa3198e2212c985c634821682d5819346b653Chris Craik 19429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 19433a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 19449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 19459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 194698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowSaveLayerTestRenderer renderer; 1947f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 194874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(6, renderer.getIndex()); 194998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 1950d3daa3198e2212c985c634821682d5819346b653Chris Craik 195198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowHwLayer) { 195298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowHwLayerTestRenderer : public TestRendererBase { 195398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 195498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override { 195598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(0, mIndex++); 195698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 195798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 195898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(1, mIndex++); 19596e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x); 19606e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y); 19616e068c0182f6f85bccb855a647510724d1c65a13Chris Craik EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius); 196298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 196398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 196498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(2, mIndex++); 196598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 196698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void endLayer() override { 196798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(3, mIndex++); 196898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 196998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 197098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, mIndex++); 197198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 197298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 1973d3daa3198e2212c985c634821682d5819346b653Chris Craik 197406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(50, 60, 150, 160, 197516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [](RenderProperties& props, RecordingCanvas& canvas) { 197616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.mutateLayerProperties().setType(LayerType::RenderLayer); 197798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 1978eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita canvas.save(SaveFlags::MatrixClip); 197998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.translate(20, 10); 198098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 198198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.restore(); 198216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 198398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer** layerHandle = parent->getLayerHandle(); 198498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 198598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // create RenderNode's layer here in same way prepareTree would, setting windowTransform 198698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100); 198798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik Matrix4 windowTransform; 198898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin 198998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layer.setWindowTransform(windowTransform); 199098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = &layer; 199198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 19929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(parent); 199398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid 199498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100)); 19959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 19969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 19973a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance()); 19989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferLayers(layerUpdateQueue); 19999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 20009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 200198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowHwLayerTestRenderer renderer; 2002f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 200398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(5, renderer.getIndex()); 200498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 200598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik // clean up layer pointer, so we can safely destruct RenderNode 200698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik *layerHandle = nullptr; 2007d3daa3198e2212c985c634821682d5819346b653Chris Craik} 200876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 200998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowLayering) { 201098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik class ShadowLayeringTestRenderer : public TestRendererBase { 201198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik public: 201298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 201398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 201498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 0 || index == 1); 201598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 201698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 201798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik int index = mIndex++; 201898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_TRUE(index == 2 || index == 3); 201998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik } 202098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }; 202106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200, 20228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 202398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.insertReorderBarrier(true); 202498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 202598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get()); 202698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik }); 20279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 20283a5811b50157e7ba50854caf957e806aee794d39Chris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 20299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 20309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 203198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik ShadowLayeringTestRenderer renderer; 2032f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 203398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik EXPECT_EQ(4, renderer.getIndex()); 203498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik} 203598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 203698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowClipping) { 2037d645640180c25c2711e99aa82ec629155f8e91baChris Craik class ShadowClippingTestRenderer : public TestRendererBase { 2038d645640180c25c2711e99aa82ec629155f8e91baChris Craik public: 2039d645640180c25c2711e99aa82ec629155f8e91baChris Craik void onShadowOp(const ShadowOp& op, const BakedOpState& state) override { 2040d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(0, mIndex++); 2041d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipState->rect) 2042d645640180c25c2711e99aa82ec629155f8e91baChris Craik << "Shadow must respect pre-barrier canvas clip value."; 2043d645640180c25c2711e99aa82ec629155f8e91baChris Craik } 2044d645640180c25c2711e99aa82ec629155f8e91baChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2045d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(1, mIndex++); 2046d645640180c25c2711e99aa82ec629155f8e91baChris Craik } 2047d645640180c25c2711e99aa82ec629155f8e91baChris Craik }; 204806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2049d645640180c25c2711e99aa82ec629155f8e91baChris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 2050d645640180c25c2711e99aa82ec629155f8e91baChris Craik // Apply a clip before the reorder barrier/shadow casting child is drawn. 2051d645640180c25c2711e99aa82ec629155f8e91baChris Craik // This clip must be applied to the shadow cast by the child. 20526c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect); 2053d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.insertReorderBarrier(true); 2054d645640180c25c2711e99aa82ec629155f8e91baChris Craik canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get()); 2055d645640180c25c2711e99aa82ec629155f8e91baChris Craik }); 2056d645640180c25c2711e99aa82ec629155f8e91baChris Craik 20579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2058d645640180c25c2711e99aa82ec629155f8e91baChris Craik (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance()); 20599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent)); 20609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 2061d645640180c25c2711e99aa82ec629155f8e91baChris Craik ShadowClippingTestRenderer renderer; 2062d645640180c25c2711e99aa82ec629155f8e91baChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2063d645640180c25c2711e99aa82ec629155f8e91baChris Craik EXPECT_EQ(2, renderer.getIndex()); 2064d645640180c25c2711e99aa82ec629155f8e91baChris Craik} 2065d645640180c25c2711e99aa82ec629155f8e91baChris Craik 206616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback, 206776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) { 2068d3daa3198e2212c985c634821682d5819346b653Chris Craik class PropertyTestRenderer : public TestRendererBase { 2069d3daa3198e2212c985c634821682d5819346b653Chris Craik public: 2070d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh explicit PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback) 2071d3daa3198e2212c985c634821682d5819346b653Chris Craik : mCallback(callback) {} 2072d3daa3198e2212c985c634821682d5819346b653Chris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 2073d3daa3198e2212c985c634821682d5819346b653Chris Craik EXPECT_EQ(mIndex++, 0); 2074d3daa3198e2212c985c634821682d5819346b653Chris Craik mCallback(op, state); 2075d3daa3198e2212c985c634821682d5819346b653Chris Craik } 2076d3daa3198e2212c985c634821682d5819346b653Chris Craik std::function<void(const RectOp&, const BakedOpState&)> mCallback; 2077d3daa3198e2212c985c634821682d5819346b653Chris Craik }; 2078d3daa3198e2212c985c634821682d5819346b653Chris Craik 207906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 208016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) { 208116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(props); 208276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkPaint paint; 208376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik paint.setColor(SK_ColorWHITE); 208476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik canvas.drawRect(0, 0, 100, 100, paint); 208516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck }); 208676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 20879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200, 20889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 20899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 20909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 209176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik PropertyTestRenderer renderer(opValidateCallback); 2092f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 209376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op"; 209476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 209576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 209698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) { 209776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 209876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAlpha(0.5f); 209976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setHasOverlappingRendering(false); 210076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 210176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op"; 210276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 210376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 210476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 210598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropClipping) { 210676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 210776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipToBounds(true); 210876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setClipBounds(Rect(10, 20, 300, 400)); 210976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 211076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds) 211176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Clip rect should be intersection of node bounds and clip bounds"; 211276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 211376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 211476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 211598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropRevealClip) { 211676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 211776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableRevealClip().set(true, 50, 50, 25); 211876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 211976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 212076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_TRUE(state.roundRectClipState->highPriority); 212176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(25, state.roundRectClipState->radius); 212276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect); 212376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 212476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 212576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 212698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOutlineClip) { 212776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 212876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setShouldClip(true); 212976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f); 213076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 213176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik ASSERT_NE(nullptr, state.roundRectClipState); 213276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_FALSE(state.roundRectClipState->highPriority); 213376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(5, state.roundRectClipState->radius); 213476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect); 213576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 213676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 213776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 213898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropTransform) { 213976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik testProperty([](RenderProperties& properties) { 214076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setLeftTopRightBottom(10, 10, 110, 110); 214176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 214276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f); 214376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setStaticMatrix(&staticMatrix); 214476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 214576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignored, since static overrides animation 214676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15); 214776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setAnimationMatrix(&animationMatrix); 214876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 214976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationX(10); 215076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setTranslationY(20); 215176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleX(0.5f); 215276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik properties.setScaleY(0.7f); 215376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }, [](const RectOp& op, const BakedOpState& state) { 215476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik Matrix4 matrix; 215576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.loadTranslate(10, 10, 0); // left, top 215676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(1.2f, 1.2f, 1); // static matrix 215776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // ignore animation matrix, since static overrides it 215876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 215976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // translation xy 216076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(10, 20); 216176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 216276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // scale xy (from default pivot - center) 216376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(50, 50); 216476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.scale(0.5f, 0.7f, 1); 216576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik matrix.translate(-50, -50); 216676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform) 216776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik << "Op draw matrix must match expected combination of transformation properties"; 216876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik }); 216976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik} 2170161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 21718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData { 21728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerWidth = 0; 21738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik uint32_t layerHeight = 0; 21748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Rect rectClippedBounds; 21758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 rectMatrix; 2176c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck Matrix4 drawLayerMatrix; 21778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}; 21788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/** 21798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation: 21808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * a) 0 < alpha < 1 21818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * b) too big for layer (larger than maxTextureSize) 21828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * c) overlapping rendering content 21838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform. 21848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * 21858ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced 21868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip. 21878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */ 21888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData, 218916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck std::function<void(RenderProperties&)> propSetupCallback) { 21908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik class SaveLayerAlphaClipTestRenderer : public TestRendererBase { 21918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik public: 2192d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData) 21938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik : mOutData(outData) {} 21948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 21958ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override { 21968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(0, mIndex++); 21978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerWidth = width; 21988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->layerHeight = height; 21998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik return nullptr; 22008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 22018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onRectOp(const RectOp& op, const BakedOpState& state) override { 22028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(1, mIndex++); 22038ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 22048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectClippedBounds = state.computedState.clippedBounds; 22058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik mOutData->rectMatrix = state.computedState.transform; 22068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 22078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void endLayer() override { 22088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(2, mIndex++); 22098ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 22108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik void onLayerOp(const LayerOp& op, const BakedOpState& state) override { 22118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(3, mIndex++); 2212c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck mOutData->drawLayerMatrix = state.computedState.transform; 22138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik } 221474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override { 221574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik EXPECT_EQ(4, mIndex++); 221674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik } 22178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik private: 22188ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData* mOutData; 22198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }; 22208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 22218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize()) 22228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "Node must be bigger than max texture size to exercise saveLayer codepath"; 222306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000, 222416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) { 22258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setHasOverlappingRendering(true); 22268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer 22278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // apply other properties 222816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck propSetupCallback(properties); 222916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 223016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck SkPaint paint; 223116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck paint.setColor(SK_ColorWHITE); 223216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck canvas.drawRect(0, 0, 10000, 10000, paint); 22338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 22349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height 22359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 22369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200, 22379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 22389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*syncedNode); 22398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 22408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaClipTestRenderer renderer(outObservedData); 2241f158b49c888f722194afe5a80539a2b020c130bcChris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 22428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 22438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // assert, since output won't be valid if we haven't seen a save layer triggered 224474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior."; 22458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 224798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) { 22488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 22498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 22508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(10); // offset rendering content 22518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(-2000); // offset rendering content 22528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 22538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(190u, observedData.layerWidth); 22548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(200u, observedData.layerHeight); 22555430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds) 22568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be clipped to screen area"; 22578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik Matrix4 expected; 22588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik expected.loadTranslate(0, -2000, 0); 22598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix) 22608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik << "expect content to be translated as part of being clipped"; 2261c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck expected.loadTranslate(10, 0, 0); 2262c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix) 2263c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck << "expect drawLayer to be translated as part of being clipped"; 22648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 226698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) { 22678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 22688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 22698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // Translate and rotate the view so that the only visible part is the top left corner of 22708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik // the view. It will form an isosceles right triangle with a long side length of 200 at the 22718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // bottom of the viewport. 22728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationX(100); 22738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setTranslationY(100); 22748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 22758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 22768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setRotation(45); 22778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 22788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik // ceil(sqrt(2) / 2 * 200) = 142 22798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerWidth); 22808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(142u, observedData.layerHeight); 22815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds); 22828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 22838ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 228598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) { 22868ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik SaveLayerAlphaData observedData; 22878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) { 22888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotX(0); 22898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setPivotY(0); 22908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleX(2); 22918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik properties.setScaleY(0.5f); 22928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik }); 22938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(100u, observedData.layerWidth); 22948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_EQ(400u, observedData.layerHeight); 22955430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds); 22968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix); 22978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik} 22988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik 229998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clip_replace) { 230004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik class ClipReplaceTestRenderer : public TestRendererBase { 230104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik public: 230204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik void onColorOp(const ColorOp& op, const BakedOpState& state) override { 230304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(0, mIndex++); 230404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_TRUE(op.localClip->intersectWithRoot); 230504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect) 230604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik << "Expect resolved clip to be intersection of viewport clip and clip op"; 230704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik } 230804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }; 230906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30, 231004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik [](RenderProperties& props, RecordingCanvas& canvas) { 2311a0a74d5f8ee1dbd04772ffb1775d045ce6b5934bMike Reed canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace_deprecated); 2312260ab726486317496bc12a57d599ea96dcde3284Mike Reed canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver); 231304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik }); 231404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 23159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50, 23169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik sLightGeometry, Caches::getInstance()); 23179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node)); 23189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik 231904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik ClipReplaceTestRenderer renderer; 232004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik frameBuilder.replayBakedOps<TestDispatcher>(renderer); 232104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik EXPECT_EQ(1, renderer.getIndex()); 232204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik} 232304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik 2324e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) { 2325db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B 2326db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2327db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2328db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2329db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2330db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2331db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2332db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2333db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2334db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { 2335db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2336db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2337db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2338db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2339db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2340db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2341db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2342db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2343db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2344db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2345db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2346db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2347db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2348db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2349db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2350db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2351db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2352db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2353db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2354e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) { 2355db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on E 2356db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2357db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2358db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2359db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C E 2360db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2361db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2362db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2363db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2364db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2365db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2366db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2367db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 2 2368db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2369db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2370db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2371db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2372db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 3 2373db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2374db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeE 2375db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2376db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2377db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2378db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2379db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2380db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2381db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2382db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2383db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, renderer.getIndex()); 2384db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2385db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2386e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) { 2387db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected without receiver 2388db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2389db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2390db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2391db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2392db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2393db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2394db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2395db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2396db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2397db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2398db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { 2399db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //not having a projection receiver is an undefined behavior 2400db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2401db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2402db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2403db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2404db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2405db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2406db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2407db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2408db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2409db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2410db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2411db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2412db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, renderer.getIndex()); 2413db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2414db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2415e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) { 2416db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on C 2417db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2418db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2419db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2420db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2421db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2422db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2423db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2424db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2425db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2426db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2427db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2428db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2429db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2430db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2431db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2432db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2433db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2434db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2435db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2436db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2437db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2438db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2439db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2440db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2441db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2442db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2443db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2444e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) { 2445db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2446db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2447db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, nullptr); //nodeB 2448db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2449db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { 2450db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //having a node that is projected on itself is an undefined/unexpected behavior 2451db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2452db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2453db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2454db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2455db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2456db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2457db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2458db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2459db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2460db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2461db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2462db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2463db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2464db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(2, renderer.getIndex()); 2465db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2466db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2467e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) { 2468db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a 2469db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical 2470db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling 2471db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B. R is not expected to be drawn (see Sibling2 outcome below), 2472db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev but for some reason it is drawn. 2473db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2474db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /|\ 2475db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2476db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C R 2477db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2478db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2479db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2480db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { 2481db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2482db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2483db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2484db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2485db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2486db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2487db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2488db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2489db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2490db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2491db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2492db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2493db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2494db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2495db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2496db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2497db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2498db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2499db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2500e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) { 2501db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed. 2502db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2503db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2504db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G 2505db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /|\ 2506db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / | \ 2507db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C R 2508db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2509db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2510db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2513db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2515db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2519db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2529db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2530db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2531db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2532db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2533e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) { 2534db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* R is backward projected on B 2535db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2536db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2537db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B 2538db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2539db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev C 2540db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2541db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2542db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2543db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2544db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2545db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { 2546db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { 2548db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { 2549db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2550db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2551db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2552db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2553db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2554db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2555db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2556db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2557db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2558db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2559db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2560db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2561db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2562db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(3, renderer.getIndex()); 2563db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2564db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2565e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) { 2566db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, R is backward projected 2567db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2568db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2569db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2570db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2571db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G R 2572db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2573db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2574db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2575db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2576db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2577db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2578db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2579db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2580db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2581db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2582db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2583db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2584db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2585db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2586db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2587db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2588db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2589db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2590db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2591db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2592db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2593db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2594db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2595db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, renderer.getIndex()); 2596db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2597db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2598e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) { 2599db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, G is backward projected 2600db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2601db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2602db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2603db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2604db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G R 2605db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2606db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2607db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2608db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2609db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2610db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2611db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2612db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2613db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2614db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2615db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2616db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2617db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2618db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2619db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2620db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2621db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2622db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2623db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2624db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2625db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2626db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2627db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2628db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(4, renderer.getIndex()); 2629db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2630db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2631e681bf6b5c798cce3858e1d39e4fe629cab721f0Chris CraikRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) { 2632db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev /* B and G are receivables, R is backward projected 2633db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev A 2634db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2635db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev B C 2636db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev / \ 2637db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev G D 2638db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev | 2639db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev R 2640db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev */ 2641db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100, 2642db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev [](RenderProperties& props, RecordingCanvas& canvas) { 2643db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B 2644db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2645db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeB 2646db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //C 2647db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //G 2648db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectionReceiver(true); 2649db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeG 2650db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { //D 2651db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R 2652db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setProjectBackwards(true); 2653db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev props.setClipToBounds(false); 2654db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeR 2655db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeD 2656db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev } ); //nodeC 2657db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev }); //nodeA 2658db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2659db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100, 2660db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev sLightGeometry, Caches::getInstance()); 2661db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA)); 2662db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 2663db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev ZReorderTestRenderer renderer; 2664db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev frameBuilder.replayBakedOps<TestDispatcher>(renderer); 2665db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev EXPECT_EQ(5, renderer.getIndex()); 2666db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} 2667db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev 26686fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer 26696fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android 2670