FrameBuilderTests.cpp revision f77ca0872102116f58693d26703af8279573d014
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
17498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleRejection) {
17506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
177eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
1786c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect); // intersection should be empty
1796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
1806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
1816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
1829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
1839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
1849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
185b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
1865854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    FailRenderer renderer;
187f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
188b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
189b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
19098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, simpleBatching) {
191a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    const int LOOPS = 5;
192d3daa3198e2212c985c634821682d5819346b653Chris Craik    class SimpleBatchingTestRenderer : public TestRendererBase {
193d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
194d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
195a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            EXPECT_TRUE(mIndex++ >= LOOPS) << "Bitmaps should be above all rects";
196d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
197d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
198a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            EXPECT_TRUE(mIndex++ < LOOPS) << "Rects should be below all bitmaps";
199d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
200d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
201d3daa3198e2212c985c634821682d5819346b653Chris Craik
20206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
2038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
204aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv
205aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(10, 10,
206aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv                kAlpha_8_SkColorType)); // Disable merging by using alpha 8 bitmap
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects.
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group.
210eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
211a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        for (int i = 0; i < LOOPS; i++) {
212b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.translate(0, 10);
213b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            canvas.drawRect(0, 0, 10, 10, SkPaint());
214aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv            canvas.drawBitmap(*bitmap, 5, 0, nullptr);
215b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
216b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvas.restore();
217b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
2189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
2199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
2209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
221b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
2225854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    SimpleBatchingTestRenderer renderer;
223f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
224a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(2 * LOOPS, renderer.getIndex())
22515c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            << "Expect number of ops = 2 * loop count";
226a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik}
227a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
22898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNode_translateClip) {
2299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    class DeferRenderNodeTranslateClipTestRenderer : public TestRendererBase {
2309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    public:
2319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
2329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            EXPECT_EQ(0, mIndex++);
2339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            EXPECT_EQ(Rect(5, 10, 55, 60), state.computedState.clippedBounds);
2349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            EXPECT_EQ(OpClipSideFlags::Right | OpClipSideFlags::Bottom,
2359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                    state.computedState.clipSideFlags);
2369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        }
2379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    };
2389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
23906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
2419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        canvas.drawRect(0, 0, 100, 100, SkPaint());
2429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    });
2439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
2469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(5, 10, Rect(50, 50), // translate + clip node
2479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            *TestUtils::getSyncedNode(node));
2489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    DeferRenderNodeTranslateClipTestRenderer renderer;
2509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    EXPECT_EQ(1, renderer.getIndex());
2529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik}
2539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
25498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferRenderNodeScene) {
2559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    class DeferRenderNodeSceneTestRenderer : public TestRendererBase {
2569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    public:
2579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
2589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            const Rect& clippedBounds = state.computedState.clippedBounds;
2599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            Matrix4 expected;
2609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            switch (mIndex++) {
2619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            case 0:
2629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                // background - left side
2639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                EXPECT_EQ(Rect(600, 100, 700, 500), clippedBounds);
2649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                expected.loadTranslate(100, 100, 0);
2659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                break;
2669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            case 1:
2679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                // background - top side
2689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                EXPECT_EQ(Rect(100, 400, 600, 500), clippedBounds);
2699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                expected.loadTranslate(100, 100, 0);
2709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                break;
2719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            case 2:
2729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                // content
2739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                EXPECT_EQ(Rect(100, 100, 700, 500), clippedBounds);
2749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                expected.loadTranslate(-50, -50, 0);
2759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                break;
2769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            case 3:
2779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                // overlay
2789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                EXPECT_EQ(Rect(0, 0, 800, 200), clippedBounds);
2799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                break;
2809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            default:
2819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                ADD_FAILURE() << "Too many rects observed";
2829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            }
2839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            EXPECT_EQ(expected, state.computedState.transform);
2849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        }
2859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    };
2869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    std::vector<sp<RenderNode>> nodes;
2889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    SkPaint transparentPaint;
2899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    transparentPaint.setAlpha(128);
2909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // backdrop
29206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    nodes.push_back(TestUtils::createNode<RecordingCanvas>(100, 100, 700, 500, // 600x400
2939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
2949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        canvas.drawRect(0, 0, 600, 400, transparentPaint);
2959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    }));
2969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // content
2989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    Rect contentDrawBounds(150, 150, 650, 450); // 500x300
29906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600,
3009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
3019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        canvas.drawRect(0, 0, 800, 600, transparentPaint);
3029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    }));
3039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
3049cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // overlay
30506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    nodes.push_back(TestUtils::createNode<RecordingCanvas>(0, 0, 800, 600,
3069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            [&transparentPaint](RenderProperties& props, RecordingCanvas& canvas) {
3079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        canvas.drawRect(0, 0, 800, 200, transparentPaint);
3089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    }));
3099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
3109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    for (auto& node : nodes) {
3119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        TestUtils::syncHierarchyPropertiesAndDisplayList(node);
3129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    }
3139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
31447aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck    {
31547aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
31647aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck                sLightGeometry, Caches::getInstance());
31747aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
31847aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck
31947aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        DeferRenderNodeSceneTestRenderer renderer;
32047aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        frameBuilder.replayBakedOps<TestDispatcher>(renderer);
32147aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        EXPECT_EQ(4, renderer.getIndex());
32247aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck    }
3239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
32447aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck    for (auto& node : nodes) {
3252de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        EXPECT_TRUE(node->isValid());
32647aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        EXPECT_FALSE(node->nothingToDraw());
3272de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        node->setStagingDisplayList(nullptr);
3282de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        EXPECT_FALSE(node->isValid());
3292de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        EXPECT_FALSE(node->nothingToDraw());
3302de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        node->destroyHardwareResources();
33147aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        EXPECT_TRUE(node->nothingToDraw());
3322de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        EXPECT_FALSE(node->isValid());
33347aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck    }
33447aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck
33547aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck    {
33647aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        // Validate no crashes if any nodes are missing DisplayLists
33747aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
33847aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck                sLightGeometry, Caches::getInstance());
33947aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
34047aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck
34147aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        FailRenderer renderer;
34247aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck        frameBuilder.replayBakedOps<TestDispatcher>(renderer);
34347aa8d1477d1bacdb3b45e0463ef99dcf5c9cc09John Reck    }
3449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik}
3459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
34698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_noFbo0) {
3476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    class EmptyNoFbo0TestRenderer : public TestRendererBase {
3486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    public:
3496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
3506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
3516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endFrame(const Rect& repaintRect) override {
3536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
3546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    };
3566246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
3579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // Use layer update constructor, so no work is enqueued for Fbo0
3589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    LayerUpdateQueue emptyLayerUpdateQueue;
3599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(emptyLayerUpdateQueue, sLightGeometry, Caches::getInstance());
3606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EmptyNoFbo0TestRenderer renderer;
3616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
3626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik}
3636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
36498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_withFbo0) {
3656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    class EmptyWithFbo0TestRenderer : public TestRendererBase {
3666246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    public:
3676246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
3686246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(0, mIndex++);
3696246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3706246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endFrame(const Rect& repaintRect) override {
3716246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(1, mIndex++);
3726246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3736246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    };
37406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
3756246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
3766246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        // no drawn content
3776246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    });
3786246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
3799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // Draw, but pass node without draw content, so no work is done for primary frame
3809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
3819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
3829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
3839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
3846246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EmptyWithFbo0TestRenderer renderer;
3856246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
3866246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced,"
3876246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            " but fbo0 update lifecycle should still be observed";
3886246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik}
3896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
39098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_rects) {
39180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    class AvoidOverdrawRectsTestRenderer : public TestRendererBase {
39280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    public:
39380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
39480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            EXPECT_EQ(mIndex++, 0) << "Should be one rect";
39580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds)
39680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                    << "Last rect should occlude others.";
39780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        }
39880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    };
39906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
40080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
40180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
40280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
40380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(10, 10, 190, 190, SkPaint());
40480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    });
40580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
40680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    // Damage (and therefore clip) is same as last draw, subset of renderable area.
40780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    // This means last op occludes other contents, and they'll be rejected to avoid overdraw.
4089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200,
4099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
4109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
41180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
41280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    EXPECT_EQ(3u, node->getDisplayList()->getOps().size())
41380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            << "Recording must not have rejected ops, in order for this test to be valid";
41480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
41580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    AvoidOverdrawRectsTestRenderer renderer;
41680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
41780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op";
41880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik}
41980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
42098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_bitmaps) {
421aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> opaqueBitmap(TestUtils::createBitmap(50, 50,
422aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv            SkColorType::kRGB_565_SkColorType));
423aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> transpBitmap(TestUtils::createBitmap(50, 50,
424aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv            SkColorType::kAlpha_8_SkColorType));
42580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase {
42680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    public:
42780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
42880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            switch(mIndex++) {
42980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            case 0:
430ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv                EXPECT_EQ(opaqueBitmap.get(), op.bitmap);
43180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                break;
43280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            case 1:
433ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv                EXPECT_EQ(transpBitmap.get(), op.bitmap);
43480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                break;
43580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            default:
43680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                ADD_FAILURE() << "Only two ops expected.";
43780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            }
43880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        }
43980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    };
44080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
44106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 50, 50,
44280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
44380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 50, 50, SkPaint());
44480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 50, 50, SkPaint());
445aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
44680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
44780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        // only the below draws should remain, since they're
448aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*opaqueBitmap, 0, 0, nullptr);
449aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
45080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    });
4519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50,
4529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
4539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
45480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
45580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    EXPECT_EQ(5u, node->getDisplayList()->getOps().size())
45680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            << "Recording must not have rejected ops, in order for this test to be valid";
45780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
45880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    AvoidOverdrawBitmapsTestRenderer renderer;
45980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
460a82ffc549bd6dbf8cfc6f4d646d0f458dca54014sergeyv    EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops";
46180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik}
46280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
46398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clippedMerging) {
46493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    class ClippedMergingTestRenderer : public TestRendererBase {
46593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    public:
46693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        void onMergedBitmapOps(const MergedBakedOpList& opList) override {
46793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(0, mIndex);
46893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            mIndex += opList.count;
46993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(4u, opList.count);
47093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip);
47193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right,
47293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik                    opList.clipSideFlags);
47393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        }
47493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    };
47506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
47606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
477aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20));
47893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
47993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // left side clipped (to inset left half)
48066b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace);
481aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 0, 40, nullptr);
48293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
48393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // top side clipped (to inset top half)
48466b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace);
485aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 40, 0, nullptr);
48693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
48793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // right side clipped (to inset right half)
48866b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace);
489aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 80, 40, nullptr);
49093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
49193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // bottom not clipped, just abutting (inset bottom half)
49266b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace);
493aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 40, 70, nullptr);
49493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    });
49593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
4969cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
4979cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
4989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
4999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
50093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    ClippedMergingTestRenderer renderer;
501f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
50293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    EXPECT_EQ(4, renderer.getIndex());
50393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik}
50493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
50598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, regionClipStopsMerge) {
506f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    class RegionClipStopsMergeTestRenderer : public TestRendererBase {
507f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    public:
508f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; }
509f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    };
510f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
511f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
512f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        SkPath path;
513f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        path.addCircle(200, 200, 200, SkPath::kCW_Direction);
514f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        canvas.save(SaveFlags::MatrixClip);
5156c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipPath(&path, SkClipOp::kIntersect);
516f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        SkPaint paint;
517f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
518f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        paint.setAntiAlias(true);
519f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        paint.setTextSize(50);
520f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
521f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200);
522f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        canvas.restore();
523f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    });
524f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik
525f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
526f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik            sLightGeometry, Caches::getInstance());
527f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
528f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik
529f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    RegionClipStopsMergeTestRenderer renderer;
530f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
531f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    EXPECT_EQ(2, renderer.getIndex());
532f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik}
533f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik
53498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textMerging) {
535d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    class TextMergingTestRenderer : public TestRendererBase {
536d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    public:
537d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        void onMergedTextOps(const MergedBakedOpList& opList) override {
538d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(0, mIndex);
539d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            mIndex += opList.count;
540d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(2u, opList.count);
541d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags);
542d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags);
543d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags);
544d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        }
545d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    };
54606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
54706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
548d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        SkPaint paint;
549d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
550d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        paint.setAntiAlias(true);
551d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        paint.setTextSize(50);
552dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
553dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
554d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    });
5559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
5569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
5579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
5589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
559d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    TextMergingTestRenderer renderer;
560f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
561d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops";
562d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik}
563d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
56498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStrikethrough) {
565a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    const int LOOPS = 5;
566a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    class TextStrikethroughTestRenderer : public TestRendererBase {
567a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    public:
568a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
569a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text";
570a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
57115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik        void onMergedTextOps(const MergedBakedOpList& opList) override {
57215c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            EXPECT_EQ(0, mIndex);
57315c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            mIndex += opList.count;
57415c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            EXPECT_EQ(5u, opList.count);
575a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
576a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    };
57706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 2000,
5788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
579a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        SkPaint textPaint;
580a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        textPaint.setAntiAlias(true);
581a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        textPaint.setTextSize(20);
582f77ca0872102116f58693d26703af8279573d014Derek Sollenberger        textPaint.setFlags(textPaint.getFlags() | SkPaint::kStrikeThruText_ReserveFlag);
58342a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
584a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        for (int i = 0; i < LOOPS; i++) {
585dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
586a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
587a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
5889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
5899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000,
5909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
5919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
5929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
593a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    TextStrikethroughTestRenderer renderer;
594f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
595a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(2 * LOOPS, renderer.getIndex())
596d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            << "Expect number of ops = 2 * loop count";
597b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
598b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
5997c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = {
6007c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style };
6017c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
60298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStyle) {
6037c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    class TextStyleTestRenderer : public TestRendererBase {
6047c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    public:
6057c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        void onMergedTextOps(const MergedBakedOpList& opList) override {
6067c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            ASSERT_EQ(0, mIndex);
6077c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            ASSERT_EQ(3u, opList.count);
6087c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            mIndex += opList.count;
6097c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
6107c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            int index = 0;
6117c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            for (auto style : styles) {
6127c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                auto state = opList.states[index++];
6137c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                ASSERT_EQ(style, state->op->paint->getStyle())
6147c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                        << "Remainder of validation relies upon stable merged order";
6157c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                ASSERT_EQ(0, state->computedState.clipSideFlags)
6167c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                        << "Clipped bounds validation requires unclipped ops";
6177c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            }
6187c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
6197c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            Rect fill = opList.states[0]->computedState.clippedBounds;
6207c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            Rect stroke = opList.states[1]->computedState.clippedBounds;
6217c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds)
6227c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                    << "Stroke+Fill should be same as stroke";
6237c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
6247c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_TRUE(stroke.contains(fill));
6257c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_FALSE(fill.contains(stroke));
6267c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
62779abbf22d4f672208327546661e694d837f564a9Derek Sollenberger            // outset by half the stroke width
6287c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            Rect outsetFill(fill);
62979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger            outsetFill.outset(5);
6307c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_EQ(stroke, outsetFill);
6317c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        }
6327c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    };
63306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
63406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
6357c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        SkPaint paint;
6367c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
6377c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setAntiAlias(true);
6387c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setTextSize(50);
6397c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setStrokeWidth(10);
6407c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
6417c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        // draw 3 copies of the same text overlapping, each with a different style.
6427c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        // They'll get merged, but with
6437c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        for (auto style : styles) {
6447c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            paint.setStyle(style);
645dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
6467c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        }
6477c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    });
6489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
6499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
6509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
6517c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    TextStyleTestRenderer renderer;
6527c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
6537c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops";
6547c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik}
6557c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
65698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_clipLocalMatrix) {
657aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase {
658d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    public:
659d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
660d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            EXPECT_EQ(0, mIndex++);
661e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect());
662d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds);
663d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
664d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            Matrix4 expected;
665d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            expected.loadTranslate(5, 5, 0);
666d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
667d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        }
668d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    };
669d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
670d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
671243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik            SkMatrix::MakeTrans(5, 5));
672d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
67306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
674d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
675eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
6766c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect);
677d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        canvas.drawLayer(layerUpdater.get());
678d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        canvas.restore();
679d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    });
6809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
6819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
6829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
6839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
6849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
685aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    TextureLayerClipLocalMatrixTestRenderer renderer;
686f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
687d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    EXPECT_EQ(1, renderer.getIndex());
688d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik}
689d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
69098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_combineMatrices) {
691aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    class TextureLayerCombineMatricesTestRenderer : public TestRendererBase {
692aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    public:
693aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
694aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            EXPECT_EQ(0, mIndex++);
695aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
696aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            Matrix4 expected;
697aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            expected.loadTranslate(35, 45, 0);
698aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
699aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        }
700aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    };
701aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
702aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
703aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            SkMatrix::MakeTrans(5, 5));
704aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
70506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
706aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
707aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.save(SaveFlags::MatrixClip);
708aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.translate(30, 40);
709aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.drawLayer(layerUpdater.get());
710aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.restore();
711aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    });
712aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
7139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
7149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
7159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
7169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
717aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    TextureLayerCombineMatricesTestRenderer renderer;
718aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
719aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    EXPECT_EQ(1, renderer.getIndex());
720aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik}
721aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
72298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_reject) {
723aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
724aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            SkMatrix::MakeTrans(5, 5));
72598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel    EXPECT_EQ(Layer::Api::OpenGL, layerUpdater->backingLayer()->getApi());
7268cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel
7278cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel    GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
7288cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel    glLayer->setRenderTarget(GL_NONE); // Should be rejected
729aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
73006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
731aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
732aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.drawLayer(layerUpdater.get());
733aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    });
7349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
7359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
7369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
7379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
7389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
739aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    FailRenderer renderer;
740aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
741aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik}
742aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
74398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, functor_reject) {
744223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    class FunctorTestRenderer : public TestRendererBase {
745223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    public:
746223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik        void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override {
747223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik            EXPECT_EQ(0, mIndex++);
748223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik        }
749223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    };
750223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    Functor noopFunctor;
751223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik
752223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    // 1 million pixel tall view, scrolled down 80%
75306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto scrolledFunctorView = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 1000000,
754223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik            [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
755223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik        canvas.translate(0, -800000);
756cd1c3eba69d044b551cededad75474038f919890John Reck        canvas.callDrawGLFunction(&noopFunctor, nullptr);
757223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    });
758223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik
7599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
7603a5811b50157e7ba50854caf957e806aee794d39Chris Craik            sLightGeometry, Caches::getInstance());
7619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(scrolledFunctorView));
7629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
763223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    FunctorTestRenderer renderer;
764223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
765223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected";
766223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik}
767223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik
76898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferColorOp_unbounded) {
769a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    class ColorTestRenderer : public TestRendererBase {
770a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    public:
771a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik        void onColorOp(const ColorOp& op, const BakedOpState& state) override {
772a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            EXPECT_EQ(0, mIndex++);
773a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds)
774a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik                    << "Color op should be expanded to bounds of surrounding";
775a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik        }
776a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    };
777a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
77806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(0, 0, 10, 10,
779a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
780a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik        props.setClipToBounds(false);
781260ab726486317496bc12a57d599ea96dcde3284Mike Reed        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
782a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    });
783a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
7849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
785a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            sLightGeometry, Caches::getInstance());
7869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(unclippedColorView));
7879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
788a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    ColorTestRenderer renderer;
789a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
790a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected";
791a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik}
792a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
79398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
794d3daa3198e2212c985c634821682d5819346b653Chris Craik    class RenderNodeTestRenderer : public TestRendererBase {
795d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
796d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
797d3daa3198e2212c985c634821682d5819346b653Chris Craik            switch(mIndex++) {
798d3daa3198e2212c985c634821682d5819346b653Chris Craik            case 0:
7995430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds);
800d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
801d3daa3198e2212c985c634821682d5819346b653Chris Craik                break;
802d3daa3198e2212c985c634821682d5819346b653Chris Craik            case 1:
803d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds);
804d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
805d3daa3198e2212c985c634821682d5819346b653Chris Craik                break;
806d3daa3198e2212c985c634821682d5819346b653Chris Craik            default:
807d3daa3198e2212c985c634821682d5819346b653Chris Craik                ADD_FAILURE();
808d3daa3198e2212c985c634821682d5819346b653Chris Craik            }
809d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
810d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
811d3daa3198e2212c985c634821682d5819346b653Chris Craik
81206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
8138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
814b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkPaint paint;
815b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        paint.setColor(SK_ColorWHITE);
816b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
817b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
818b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
81906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
820d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            [&child](RenderProperties& props, RecordingCanvas& canvas) {
821ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        SkPaint paint;
822ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        paint.setColor(SK_ColorDKGRAY);
823ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        canvas.drawRect(0, 0, 200, 200, paint);
824ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
825eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
826ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        canvas.translate(40, 40);
827d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        canvas.drawRenderNode(child.get());
828ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        canvas.restore();
829b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
830b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
8319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
8329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
8339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
8349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
8355854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    RenderNodeTestRenderer renderer;
836f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
837223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    EXPECT_EQ(2, renderer.getIndex());
838b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
839b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
84098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clipped) {
841d3daa3198e2212c985c634821682d5819346b653Chris Craik    class ClippedTestRenderer : public TestRendererBase {
842d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
843d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
844d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
845d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds);
846e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect());
847d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
848d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
849d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
850d3daa3198e2212c985c634821682d5819346b653Chris Craik
85106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
8528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
853aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(200, 200));
854aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 0, 0, nullptr);
855ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik    });
856ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
8579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // clip to small area, should see in receiver
8589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200,
8599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
8609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
8619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
8625854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    ClippedTestRenderer renderer;
863f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
864ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik}
865ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
86698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_simple) {
867d3daa3198e2212c985c634821682d5819346b653Chris Craik    class SaveLayerSimpleTestRenderer : public TestRendererBase {
868d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
869d3daa3198e2212c985c634821682d5819346b653Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
870d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
871d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(180u, width);
872d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(180u, height);
873d3daa3198e2212c985c634821682d5819346b653Chris Craik            return nullptr;
874d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
875d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
876d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(2, mIndex++);
877d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
878d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
879d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(1, mIndex++);
880d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds);
8815430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds);
882e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(180, 180), state.computedState.clipRect());
883d3daa3198e2212c985c634821682d5819346b653Chris Craik
884d3daa3198e2212c985c634821682d5819346b653Chris Craik            Matrix4 expectedTransform;
885d3daa3198e2212c985c634821682d5819346b653Chris Craik            expectedTransform.loadTranslate(-10, -10, 0);
886d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform);
887d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
888d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
889d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(3, mIndex++);
890d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
891e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
892d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
893d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
89474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
89574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(4, mIndex++);
89674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(nullptr, offscreenBuffer);
89774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
898d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
899d3daa3198e2212c985c634821682d5819346b653Chris Craik
90006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
9018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
902eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer);
9036fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(10, 10, 190, 190, SkPaint());
9046fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
9056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
9069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
9079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
9089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
9099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
9109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
9115854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    SaveLayerSimpleTestRenderer renderer;
912f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
91374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(5, renderer.getIndex());
914b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
9156fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
91698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) {
917d3daa3198e2212c985c634821682d5819346b653Chris Craik    /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as:
918d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startTemporaryLayer2, rect2 endLayer2
919d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startTemporaryLayer1, rect1, drawLayer2, endLayer1
920d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startFrame, layerOp1, endFrame
921d3daa3198e2212c985c634821682d5819346b653Chris Craik     */
922d3daa3198e2212c985c634821682d5819346b653Chris Craik    class SaveLayerNestedTestRenderer : public TestRendererBase {
923d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
924d3daa3198e2212c985c634821682d5819346b653Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
925d3daa3198e2212c985c634821682d5819346b653Chris Craik            const int index = mIndex++;
926d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 0) {
927d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(400u, width);
928d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(400u, height);
929d3daa3198e2212c985c634821682d5819346b653Chris Craik                return (OffscreenBuffer*) 0x400;
930d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 3) {
931d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(800u, width);
932d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(800u, height);
933d3daa3198e2212c985c634821682d5819346b653Chris Craik                return (OffscreenBuffer*) 0x800;
934d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
935d3daa3198e2212c985c634821682d5819346b653Chris Craik            return (OffscreenBuffer*) nullptr;
936d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
937d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
938d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
939d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(index == 2 || index == 6);
940d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
94198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
942d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(7, mIndex++);
943d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
944e4db79de127cfe961195f52907af8451026eaa20Chris Craik        void endFrame(const Rect& repaintRect) override {
945d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(9, mIndex++);
946d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
947d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
948d3daa3198e2212c985c634821682d5819346b653Chris Craik            const int index = mIndex++;
949d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 1) {
9505430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect
951d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 4) {
9525430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect
953d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
954d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
955d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
956d3daa3198e2212c985c634821682d5819346b653Chris Craik            const int index = mIndex++;
957d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 5) {
958d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle);
9595430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer
960d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 8) {
961d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle);
9625430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
963d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
964d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
96574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
96674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            const int index = mIndex++;
96774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            // order isn't important, but we need to see both
96874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            if (index == 10) {
96974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer);
97074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            } else if (index == 11) {
97174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer);
97274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            } else { ADD_FAILURE(); }
97374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
974d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
975d3daa3198e2212c985c634821682d5819346b653Chris Craik
97606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 800, 800,
9778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
978eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer);
9796fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        {
9806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            canvas.drawRect(0, 0, 800, 800, SkPaint());
981eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita            canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer);
9826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            {
9836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik                canvas.drawRect(0, 0, 400, 400, SkPaint());
9846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            }
9856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            canvas.restore();
9866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
9876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
9886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
9896fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
9909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800,
9919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
9929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
9939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
9945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    SaveLayerNestedTestRenderer renderer;
995f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
99674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(12, renderer.getIndex());
9976fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
9986fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
99998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_contentRejection) {
100006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
10018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                [](RenderProperties& props, RecordingCanvas& canvas) {
1002eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
10036c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect);
1004eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer);
10056fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
10066fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        // draw within save layer may still be recorded, but shouldn't be drawn
10076fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(200, 200, 400, 400, SkPaint());
10086fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
10096fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
10106fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
10116fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
10129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
10139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
10149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
10159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
10166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
10175854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    FailRenderer renderer;
10186fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // should see no ops, even within the layer, since the layer should be rejected
1019f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1020b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
10216fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
102298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_simple) {
1023b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase {
1024b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public:
1025b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1026b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(0, mIndex++);
1027b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
10287435eb148e72382126e9073183e881357bb38a8bChris Craik            EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState);
1029b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1030b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1031b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
1032b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(1, mIndex++);
1033b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            ASSERT_NE(nullptr, op.paint);
1034260ab726486317496bc12a57d599ea96dcde3284Mike Reed            ASSERT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint));
1035b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1036b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1037b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(2, mIndex++);
1038b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(200, 200), op.unmappedBounds);
1039b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds);
1040b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
1041b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1042b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1043b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1044b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(3, mIndex++);
1045b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
10467435eb148e72382126e9073183e881357bb38a8bChris Craik            EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState);
1047b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1048b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1049b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    };
1050b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
105106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1052b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1053eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
1054b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
1055b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1056b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
10579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
10589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
10599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
10609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
10619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1062b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    SaveLayerUnclippedSimpleTestRenderer renderer;
1063f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1064b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(4, renderer.getIndex());
1065b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1066b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
106798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_round) {
1068d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    class SaveLayerUnclippedRoundTestRenderer : public TestRendererBase {
1069d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    public:
1070d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1071d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(0, mIndex++);
1072d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds)
1073d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik                    << "Bounds rect should round out";
1074d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        }
1075d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {}
1076d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {}
1077d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1078d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(1, mIndex++);
1079d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds)
1080d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik                    << "Bounds rect should round out";
1081d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        }
1082d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    };
1083d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
108406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1085d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1086d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out
1087d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik                128, (SaveFlags::Flags)(0));
1088d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
1089d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        canvas.restore();
1090d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    });
1091d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
1092d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
1093d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            sLightGeometry, Caches::getInstance());
1094d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
1095d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
1096d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    SaveLayerUnclippedRoundTestRenderer renderer;
1097d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1098d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    EXPECT_EQ(2, renderer.getIndex());
1099d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik}
1100d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
110198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
1102b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase {
1103b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public:
1104b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1105b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1106b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_GT(4, index);
1107b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, op.unmappedBounds.getWidth());
1108b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, op.unmappedBounds.getHeight());
1109b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            if (index == 0) {
1110b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds);
1111b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            } else if (index == 1) {
1112b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds);
1113b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            } else if (index == 2) {
1114b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds);
1115b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            } else if (index == 3) {
1116b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds);
1117b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            }
1118b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1119b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
1120b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(4, mIndex++);
1121b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            ASSERT_EQ(op.vertexCount, 16u);
1122b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            for (size_t i = 0; i < op.vertexCount; i++) {
1123b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                auto v = op.vertices[i];
1124b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200);
1125b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200);
1126b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            }
1127b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1128b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1129b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, mIndex++);
1130b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1131b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1132b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_LT(5, mIndex++);
1133b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1134b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    };
1135b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
113606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1137b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1138b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
1139eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        int restoreTo = canvas.save(SaveFlags::MatrixClip);
1140b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.scale(2, 2);
1141eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip);
1142eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip);
1143eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip);
1144eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip);
1145b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(0, 0, 100, 100, SkPaint());
1146b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restoreToCount(restoreTo);
1147b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
11489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
11499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
11509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
11519cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
11529cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1153b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    SaveLayerUnclippedMergedClearsTestRenderer renderer;
1154f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1155b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(10, renderer.getIndex())
1156b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect.";
1157b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1158b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
115998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
11604876de16e34622634266d09522c9153c78c7c2fbChris Craik    class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase {
11614876de16e34622634266d09522c9153c78c7c2fbChris Craik    public:
11624876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
11634876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(0, mIndex++);
11644876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11654876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
11664876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(1, mIndex++);
11674876de16e34622634266d09522c9153c78c7c2fbChris Craik            ASSERT_NE(nullptr, op.paint);
1168260ab726486317496bc12a57d599ea96dcde3284Mike Reed            EXPECT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint));
11694876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds)
11704876de16e34622634266d09522c9153c78c7c2fbChris Craik                    << "Expect dirty rect as clip";
11714876de16e34622634266d09522c9153c78c7c2fbChris Craik            ASSERT_NE(nullptr, state.computedState.clipState);
11724876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect);
11734876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
11744876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11754876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
11764876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(2, mIndex++);
11774876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11784876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
11794876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(3, mIndex++);
11804876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11814876de16e34622634266d09522c9153c78c7c2fbChris Craik    };
11824876de16e34622634266d09522c9153c78c7c2fbChris Craik
118306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
11844876de16e34622634266d09522c9153c78c7c2fbChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
11854876de16e34622634266d09522c9153c78c7c2fbChris Craik        // save smaller than clip, so we get unclipped behavior
11864876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
11874876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
11884876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.restore();
11894876de16e34622634266d09522c9153c78c7c2fbChris Craik    });
11904876de16e34622634266d09522c9153c78c7c2fbChris Craik
11914876de16e34622634266d09522c9153c78c7c2fbChris Craik    // draw with partial screen dirty, and assert we see that rect later
11929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200,
11939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
11949cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
11959cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
11964876de16e34622634266d09522c9153c78c7c2fbChris Craik    SaveLayerUnclippedClearClipTestRenderer renderer;
11974876de16e34622634266d09522c9153c78c7c2fbChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
11984876de16e34622634266d09522c9153c78c7c2fbChris Craik    EXPECT_EQ(4, renderer.getIndex());
11994876de16e34622634266d09522c9153c78c7c2fbChris Craik}
12004876de16e34622634266d09522c9153c78c7c2fbChris Craik
120198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_reject) {
120206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
12034876de16e34622634266d09522c9153c78c7c2fbChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
12044876de16e34622634266d09522c9153c78c7c2fbChris Craik        // unclipped savelayer + rect both in area that won't intersect with dirty
12054876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0));
12064876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.drawRect(100, 100, 200, 200, SkPaint());
12074876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.restore();
12084876de16e34622634266d09522c9153c78c7c2fbChris Craik    });
12094876de16e34622634266d09522c9153c78c7c2fbChris Craik
12104876de16e34622634266d09522c9153c78c7c2fbChris Craik    // draw with partial screen dirty that doesn't intersect with savelayer
12119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200,
12129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
12139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
12149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
12154876de16e34622634266d09522c9153c78c7c2fbChris Craik    FailRenderer renderer;
12164876de16e34622634266d09522c9153c78c7c2fbChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
12174876de16e34622634266d09522c9153c78c7c2fbChris Craik}
12184876de16e34622634266d09522c9153c78c7c2fbChris Craik
1219b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as:
1220b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer
1221b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe
1222b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */
122398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_complex) {
1224b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase {
1225b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public:
1226b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
1227b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(0, mIndex++); // savelayer first
1228b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            return (OffscreenBuffer*)0xabcd;
1229b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1230b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1231b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1232b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(index == 1 || index == 7);
1233b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1234b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
1235b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1236b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(index == 2 || index == 8);
1237b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1238b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1239b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(3, mIndex++);
1240b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            Matrix4 expected;
1241b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            expected.loadTranslate(-100, -100, 0);
1242b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds);
1243b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
1244b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1245b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1246b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1247b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(index == 4 || index == 10);
1248b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1249b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void endLayer() override {
1250b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, mIndex++);
1251b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1252b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
1253b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(6, mIndex++);
1254b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1255b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
1256b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(9, mIndex++);
125774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
1258b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1259b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void endFrame(const Rect& repaintRect) override {
1260b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(11, mIndex++);
1261b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
126274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
126374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(12, mIndex++);
126474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer);
126574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
1266b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    };
1267b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
126806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 600, 600, // 500x500 triggers clipping
1269b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1270eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped
1271eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped
1272eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped
1273b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(200, 200, 300, 300, SkPaint());
1274b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1275b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1276b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1277b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
12789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
12799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600,
12809cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
12819cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
12829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1283b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    SaveLayerUnclippedComplexTestRenderer renderer;
1284f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
128574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(13, renderer.getIndex());
1286b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1287b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
128898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_simple) {
1289d3daa3198e2212c985c634821682d5819346b653Chris Craik    class HwLayerSimpleTestRenderer : public TestRendererBase {
1290d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
129198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
1292d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
129398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportWidth);
129498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportHeight);
129598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect);
1296d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1297d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1298d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(1, mIndex++);
12990b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
1300d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity())
1301d3daa3198e2212c985c634821682d5819346b653Chris Craik                    << "Transform should be reset within layer";
1302d3daa3198e2212c985c634821682d5819346b653Chris Craik
1303e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect())
1304d3daa3198e2212c985c634821682d5819346b653Chris Craik                    << "Damage rect should be used to clip layer content";
1305d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1306d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
1307d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(2, mIndex++);
1308d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
130998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
1310d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(3, mIndex++);
1311d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1312d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
1313d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(4, mIndex++);
1314d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1315e4db79de127cfe961195f52907af8451026eaa20Chris Craik        void endFrame(const Rect& repaintRect) override {
1316d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(5, mIndex++);
1317d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1318d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
13190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
132006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
132116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [](RenderProperties& props, RecordingCanvas& canvas) {
132216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
13230b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        SkPaint paint;
13240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        paint.setColor(SK_ColorWHITE);
13250b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
132616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
132798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer** layerHandle = node->getLayerHandle();
13280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
132998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    // create RenderNode's layer here in same way prepareTree would
133098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
133198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = &layer;
13320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(node);
13340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    // only enqueue partial damage
133698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
13370b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
13380b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
13409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
13419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
13429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
13439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
13440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    HwLayerSimpleTestRenderer renderer;
1345f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
13460b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    EXPECT_EQ(6, renderer.getIndex());
13470b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    // clean up layer pointer, so we can safely destruct RenderNode
134998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = nullptr;
13500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik}
13510b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
135298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
1353d3daa3198e2212c985c634821682d5819346b653Chris Craik    /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as:
1354d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startRepaintLayer(child), rect(grey), endLayer
1355d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startTemporaryLayer, drawLayer(child), endLayer
1356d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer
1357d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startFrame, drawLayer(parent), endLayerb
1358d3daa3198e2212c985c634821682d5819346b653Chris Craik     */
1359d3daa3198e2212c985c634821682d5819346b653Chris Craik    class HwLayerComplexTestRenderer : public TestRendererBase {
1360d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
1361d3daa3198e2212c985c634821682d5819346b653Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
1362d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(3, mIndex++); // savelayer first
1363d3daa3198e2212c985c634821682d5819346b653Chris Craik            return (OffscreenBuffer*)0xabcd;
1364d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
136598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
1366d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1367d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 0) {
1368d3daa3198e2212c985c634821682d5819346b653Chris Craik                // starting inner layer
136998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, offscreenBuffer->viewportWidth);
137098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, offscreenBuffer->viewportHeight);
1371d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 6) {
1372d3daa3198e2212c985c634821682d5819346b653Chris Craik                // starting outer layer
137398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, offscreenBuffer->viewportWidth);
137498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, offscreenBuffer->viewportHeight);
1375d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
1376d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1377d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1378d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1379d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 1) {
1380d3daa3198e2212c985c634821682d5819346b653Chris Craik                // inner layer's rect (white)
1381d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
1382d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 7) {
1383d3daa3198e2212c985c634821682d5819346b653Chris Craik                // outer layer's rect (grey)
1384d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
1385d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
1386d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1387d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
1388d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1389d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(index == 2 || index == 5 || index == 9);
1390d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
139198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
1392d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(10, mIndex++);
1393d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1394d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
139598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            OffscreenBuffer* layer = *op.layerHandle;
1396d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1397d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 4) {
139898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, layer->viewportWidth);
139998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, layer->viewportHeight);
1400d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 8) {
1401d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
1402d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 11) {
140398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, layer->viewportWidth);
140498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, layer->viewportHeight);
1405d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
1406d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1407e4db79de127cfe961195f52907af8451026eaa20Chris Craik        void endFrame(const Rect& repaintRect) override {
1408d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(12, mIndex++);
1409d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
141074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
141174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(13, mIndex++);
141274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
1413d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
1414d3daa3198e2212c985c634821682d5819346b653Chris Craik
141506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150,
141616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [](RenderProperties& props, RecordingCanvas& canvas) {
141716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
14180b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        SkPaint paint;
14190b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        paint.setColor(SK_ColorWHITE);
14200b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
142116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
142298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100);
142398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *(child->getLayerHandle()) = &childLayer;
14240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14250b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    RenderNode* childPtr = child.get();
142606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
142716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
142816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
14290b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        SkPaint paint;
14300b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        paint.setColor(SK_ColorDKGRAY);
14310b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRect(0, 0, 200, 200, paint);
14320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
1433eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer);
14340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRenderNode(childPtr);
14350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.restore();
143616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
143798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200);
143898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *(parent->getLayerHandle()) = &parentLayer;
14390b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(parent);
14410b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
144298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
14430b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100));
14440b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
14450b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
14479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
14489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
14499cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
14509cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
14510b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    HwLayerComplexTestRenderer renderer;
1452f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
145374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(14, renderer.getIndex());
14540b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14550b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    // clean up layer pointers, so we can safely destruct RenderNodes
14560b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    *(child->getLayerHandle()) = nullptr;
14570b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    *(parent->getLayerHandle()) = nullptr;
14580b7e8245db728d127ada698be63d78b33fc6e4daChris Craik}
14590b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
146198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) {
14626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    class BuildLayerTestRenderer : public TestRendererBase {
14636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    public:
14646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
14656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(0, mIndex++);
14666246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportWidth);
14676246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportHeight);
14686246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect);
14696246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14706246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void onColorOp(const ColorOp& op, const BakedOpState& state) override {
14716246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(1, mIndex++);
14726246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14736246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity())
14746246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik                    << "Transform should be reset within layer";
14756246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14766246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect())
14776246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik                    << "Damage rect should be used to clip layer content";
14786246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14796246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endLayer() override {
14806246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(2, mIndex++);
14816246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14826246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
14836246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
14846246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14856246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endFrame(const Rect& repaintRect) override {
14866246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
14876246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14886246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    };
14896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
149006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
14916246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
14926246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        props.mutateLayerProperties().setType(LayerType::RenderLayer);
1493260ab726486317496bc12a57d599ea96dcde3284Mike Reed        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
14946246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    });
14956246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    OffscreenBuffer** layerHandle = node->getLayerHandle();
14966246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14976246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // create RenderNode's layer here in same way prepareTree would
14986246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
14996246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    *layerHandle = &layer;
15006246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
15019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
15026246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
15036246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // only enqueue partial damage
15046246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
15056246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
15066246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
15076246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // Draw, but pass empty node list, so no work is done for primary frame
15089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(layerUpdateQueue, sLightGeometry, Caches::getInstance());
15096246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    BuildLayerTestRenderer renderer;
15106246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
15116246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EXPECT_EQ(3, renderer.getIndex());
15126246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
15136246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // clean up layer pointer, so we can safely destruct RenderNode
15146246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    *layerHandle = nullptr;
15156246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik}
15166246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
1517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace {
1518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
151906152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
1520161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    SkPaint paint;
1521814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    // order put in blue channel, transparent so overlapped content doesn't get rejected
1522814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder));
1523161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    canvas->drawRect(0, 0, 100, 100, paint);
1524161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}
152506152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) {
152606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
15278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) {
1528161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, expectedDrawOrder);
1529161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    });
1530161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    node->mutateStagingProperties().setTranslationZ(z);
1531161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z);
1532161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
1533161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}
1534db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
1535db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder,
1536db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        std::function<void(RenderProperties& props, RecordingCanvas& canvas)> setup) {
1537db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
1538db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [expectedDrawOrder, setup](RenderProperties& props, RecordingCanvas& canvas) {
1539db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedRect(&canvas, expectedDrawOrder);
1540db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        if (setup) {
1541db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev             setup(props, canvas);
1542d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1543db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    });
1544db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
1545db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
1546db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
1547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievclass ZReorderTestRenderer : public TestRendererBase {
1548db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievpublic:
1549db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    void onRectOp(const RectOp& op, const BakedOpState& state) override {
1550db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel
1551db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
1552db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }
1553db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev};
1554db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
1555db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} // end anonymous namespace
1556d3daa3198e2212c985c634821682d5819346b653Chris Craik
155798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, zReorder) {
155806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
15598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1560347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev        canvas.insertReorderBarrier(true);
1561347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev        canvas.insertReorderBarrier(false);
1562161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
1563161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 1);
1564161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(true);
1565161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 6, 2.0f);
1566161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 3);
1567161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 4, 0.0f);
1568161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 5);
1569161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 2, -2.0f);
1570161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 7, 2.0f);
1571161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(false);
1572161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 8);
1573161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
157488e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op
157588e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        drawOrderedRect(&canvas, 11);
157688e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        drawOrderedNode(&canvas, 10, -1.0f);
157788e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(false);
157888e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(true); //test with two empty reorder sections
157988e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(true);
158088e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(false);
158188e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        drawOrderedRect(&canvas, 12);
1582161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    });
15839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
15849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
15859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
15869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1587161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    ZReorderTestRenderer renderer;
1588f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
158988e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev    EXPECT_EQ(13, renderer.getIndex());
1590161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik};
1591161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
159298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorder) {
15938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    static const int scrollX = 5;
15948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    static const int scrollY = 10;
15958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    class ProjectionReorderTestRenderer : public TestRendererBase {
15968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    public:
15978d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
15988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            const int index = mIndex++;
15998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            Matrix4 expectedMatrix;
16018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            switch (index) {
16028d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            case 0:
16038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
16048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
16058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                expectedMatrix.loadIdentity();
1606678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
16078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                break;
16088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            case 1:
16098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
16108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
1611678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
1612678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
1613678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                EXPECT_EQ(Rect(-35, -30, 45, 50),
1614678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                        Rect(state.computedState.localProjectionPathMask->getBounds()));
16158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                break;
16168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            case 2:
16178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
16188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
16198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
1620678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
16218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                break;
16228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            default:
16238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                ADD_FAILURE();
16248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            }
1625678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(expectedMatrix, state.computedState.transform);
16268d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        }
16278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    };
16288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    /**
16308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C)
16318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * with a projecting child (P) of its own. P would normally draw between B and C's "background"
16328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * draw, but because it is projected backwards, it's drawn in between B and C.
16338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     *
16348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * The parent is scrolled by scrollX/scrollY, but this does not affect the background
16358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * (which isn't affected by scroll).
16368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     */
163706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
16388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
16398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setProjectionReceiver(true);
16408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // scroll doesn't apply to background, so undone via translationX/Y
16418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
16428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setTranslationX(scrollX);
16438d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setTranslationY(scrollY);
16448d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16458d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
16468d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorWHITE);
16478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(0, 0, 100, 100, paint);
16488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
164906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto projectingRipple = TestUtils::createNode<RecordingCanvas>(50, 0, 100, 50,
16508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
16518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setProjectBackwards(true);
16528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setClipToBounds(false);
16538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
16548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorDKGRAY);
16558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(-10, -10, 60, 60, paint);
16568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
165706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(0, 50, 100, 100,
16588d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
16598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
16608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorBLUE);
16618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(0, 0, 100, 50, paint);
16628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRenderNode(projectingRipple.get());
16638d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
166406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
16658d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
1666678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // Set a rect outline for the projecting ripple to be masked against.
1667678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
1668678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1669eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
16708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
16718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRenderNode(receiverBackground.get());
16728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRenderNode(child.get());
16738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.restore();
16748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
16758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
16779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
16789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
16799cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
16808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    ProjectionReorderTestRenderer renderer;
1681f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
16828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    EXPECT_EQ(3, renderer.getIndex());
16838d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik}
16848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
168598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionHwLayer) {
1686678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    static const int scrollX = 5;
1687678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    static const int scrollY = 10;
1688678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    class ProjectionHwLayerTestRenderer : public TestRendererBase {
1689678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    public:
1690678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
1691678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(0, mIndex++);
1692678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1693678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onArcOp(const ArcOp& op, const BakedOpState& state) override {
1694678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(1, mIndex++);
1695678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
1696678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1697678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void endLayer() override {
1698678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(2, mIndex++);
1699678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1700678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1701678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(3, mIndex++);
1702678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
1703678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1704678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
1705678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(4, mIndex++);
1706678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
1707678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            Matrix4 expected;
1708678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            expected.loadTranslate(100 - scrollX, 100 - scrollY, 0);
1709678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(expected, state.computedState.transform);
1710678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(Rect(-85, -80, 295, 300),
1711678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                    Rect(state.computedState.localProjectionPathMask->getBounds()));
1712678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1713678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
1714678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(5, mIndex++);
1715678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
1716678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1717678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    };
171806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1719678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1720678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setProjectionReceiver(true);
1721678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // scroll doesn't apply to background, so undone via translationX/Y
1722678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
1723678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setTranslationX(scrollX);
1724678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setTranslationY(scrollY);
1725678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1726678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
1727678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
172806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1729678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1730678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setProjectBackwards(true);
1731678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setClipToBounds(false);
1732678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
1733678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
173406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(100, 100, 300, 300,
1735678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
1736678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.mutateLayerProperties().setType(LayerType::RenderLayer);
1737678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRenderNode(projectingRipple.get());
1738678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
1739678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
174006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1741678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
1742678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // Set a rect outline for the projecting ripple to be masked against.
1743678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
1744678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
1745678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRenderNode(receiverBackground.get());
1746678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRenderNode(child.get());
1747678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
1748678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1749678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    OffscreenBuffer** layerHandle = child->getLayerHandle();
1750678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1751678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    // create RenderNode's layer here in same way prepareTree would, setting windowTransform
1752678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200);
1753678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    Matrix4 windowTransform;
1754678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
1755678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    layer.setWindowTransform(windowTransform);
1756678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    *layerHandle = &layer;
1757678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
17589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(parent);
17599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1760678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
1761678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
17629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
17639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
17649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
17659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
17669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
17679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1768678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    ProjectionHwLayerTestRenderer renderer;
1769678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1770678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    EXPECT_EQ(6, renderer.getIndex());
1771678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1772678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    // clean up layer pointer, so we can safely destruct RenderNode
1773678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    *layerHandle = nullptr;
1774678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik}
1775678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
177698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionChildScroll) {
1777a748c08241e43fc68c7c34767d819aef5183936eChris Craik    static const int scrollX = 500000;
1778a748c08241e43fc68c7c34767d819aef5183936eChris Craik    static const int scrollY = 0;
1779a748c08241e43fc68c7c34767d819aef5183936eChris Craik    class ProjectionChildScrollTestRenderer : public TestRendererBase {
1780a748c08241e43fc68c7c34767d819aef5183936eChris Craik    public:
1781a748c08241e43fc68c7c34767d819aef5183936eChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1782a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_EQ(0, mIndex++);
1783a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1784a748c08241e43fc68c7c34767d819aef5183936eChris Craik        }
1785a748c08241e43fc68c7c34767d819aef5183936eChris Craik        void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
1786a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_EQ(1, mIndex++);
1787a748c08241e43fc68c7c34767d819aef5183936eChris Craik            ASSERT_NE(nullptr, state.computedState.clipState);
1788a748c08241e43fc68c7c34767d819aef5183936eChris Craik            ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
1789a748c08241e43fc68c7c34767d819aef5183936eChris Craik            ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect);
1790a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1791a748c08241e43fc68c7c34767d819aef5183936eChris Craik        }
1792a748c08241e43fc68c7c34767d819aef5183936eChris Craik    };
179306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1794a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1795a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setProjectionReceiver(true);
1796a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
1797a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
179806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1799a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1800a748c08241e43fc68c7c34767d819aef5183936eChris Craik        // scroll doesn't apply to background, so undone via translationX/Y
1801a748c08241e43fc68c7c34767d819aef5183936eChris Craik        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
1802a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setTranslationX(scrollX);
1803a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setTranslationY(scrollY);
1804a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setProjectBackwards(true);
1805a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setClipToBounds(false);
1806a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawOval(0, 0, 200, 200, SkPaint());
1807a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
180806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1809a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
1810a748c08241e43fc68c7c34767d819aef5183936eChris Craik        // Record time clip will be ignored by projectee
18116c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
1812a748c08241e43fc68c7c34767d819aef5183936eChris Craik
1813a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
1814a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRenderNode(projectingRipple.get());
1815a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
181606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1817a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
1818a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRenderNode(receiverBackground.get());
1819a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRenderNode(child.get());
1820a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
1821a748c08241e43fc68c7c34767d819aef5183936eChris Craik
18229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
18239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
18249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
18259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1826a748c08241e43fc68c7c34767d819aef5183936eChris Craik    ProjectionChildScrollTestRenderer renderer;
1827a748c08241e43fc68c7c34767d819aef5183936eChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1828a748c08241e43fc68c7c34767d819aef5183936eChris Craik    EXPECT_EQ(2, renderer.getIndex());
1829a748c08241e43fc68c7c34767d819aef5183936eChris Craik}
1830a748c08241e43fc68c7c34767d819aef5183936eChris Craik
183198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ
183298787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
183306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    return TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
18348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [translationZ](RenderProperties& properties, RecordingCanvas& canvas) {
183516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        properties.setTranslationZ(translationZ);
183616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f);
183798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        SkPaint paint;
183898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        paint.setColor(SK_ColorWHITE);
183998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
184098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    });
184198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
184298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
184398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadow) {
1844d3daa3198e2212c985c634821682d5819346b653Chris Craik    class ShadowTestRenderer : public TestRendererBase {
1845d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
1846d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
1847d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
184898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_FLOAT_EQ(1.0f, op.casterAlpha);
18496e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr));
18506e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY);
185198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
185298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            Matrix4 expectedZ;
185398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            expectedZ.loadTranslate(0, 0, 5);
18546e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ);
1855d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1856d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1857d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(1, mIndex++);
1858d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1859d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
1860161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
186106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
18628d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
186398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(true);
186498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
1865d3daa3198e2212c985c634821682d5819346b653Chris Craik    });
186698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
18679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
18689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
18699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
18709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
187198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowTestRenderer renderer;
1872f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
187398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    EXPECT_EQ(2, renderer.getIndex());
187498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
187598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
187698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowSaveLayer) {
187798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class ShadowSaveLayerTestRenderer : public TestRendererBase {
187898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public:
187998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
188098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(0, mIndex++);
188198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            return nullptr;
188298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
188398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
188498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(1, mIndex++);
18856e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
18866e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
188798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
188898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
188998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(2, mIndex++);
189098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
189198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void endLayer() override {
189298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(3, mIndex++);
189398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
189498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
189598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(4, mIndex++);
189698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
189774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
189874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(5, mIndex++);
189974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
190098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    };
190198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
190206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
19038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
190498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        // save/restore outside of reorderBarrier, so they don't get moved out of place
190598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.translate(20, 10);
1906eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer);
1907d3daa3198e2212c985c634821682d5819346b653Chris Craik        canvas.insertReorderBarrier(true);
190898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
190998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(false);
191098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.restoreToCount(count);
1911d3daa3198e2212c985c634821682d5819346b653Chris Craik    });
1912d3daa3198e2212c985c634821682d5819346b653Chris Craik
19139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
19143a5811b50157e7ba50854caf957e806aee794d39Chris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
19159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
19169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
191798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowSaveLayerTestRenderer renderer;
1918f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
191974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(6, renderer.getIndex());
192098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
1921d3daa3198e2212c985c634821682d5819346b653Chris Craik
192298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowHwLayer) {
192398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class ShadowHwLayerTestRenderer : public TestRendererBase {
192498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public:
192598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
192698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(0, mIndex++);
192798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
192898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
192998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(1, mIndex++);
19306e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
19316e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
19326e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius);
193398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
193498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
193598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(2, mIndex++);
193698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
193798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void endLayer() override {
193898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(3, mIndex++);
193998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
194098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
194198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(4, mIndex++);
194298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
194398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    };
1944d3daa3198e2212c985c634821682d5819346b653Chris Craik
194506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(50, 60, 150, 160,
194616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [](RenderProperties& props, RecordingCanvas& canvas) {
194716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
194898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(true);
1949eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
195098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.translate(20, 10);
195198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
195298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.restore();
195316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
195498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer** layerHandle = parent->getLayerHandle();
195598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
195698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    // create RenderNode's layer here in same way prepareTree would, setting windowTransform
195798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
195898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    Matrix4 windowTransform;
195998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin
196098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    layer.setWindowTransform(windowTransform);
196198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = &layer;
196298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
19639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(parent);
196498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
196598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
19669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
19679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
19683a5811b50157e7ba50854caf957e806aee794d39Chris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance());
19699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
19709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
19719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
197298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowHwLayerTestRenderer renderer;
1973f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
197498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    EXPECT_EQ(5, renderer.getIndex());
197598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
197698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    // clean up layer pointer, so we can safely destruct RenderNode
197798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = nullptr;
1978d3daa3198e2212c985c634821682d5819346b653Chris Craik}
197976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
198098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowLayering) {
198198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class ShadowLayeringTestRenderer : public TestRendererBase {
198298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public:
198398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
198498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            int index = mIndex++;
198598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_TRUE(index == 0 || index == 1);
198698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
198798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
198898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            int index = mIndex++;
198998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_TRUE(index == 2 || index == 3);
199098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
199198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    };
199206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
19938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
199498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(true);
199598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
199698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get());
199798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    });
19989cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
19993a5811b50157e7ba50854caf957e806aee794d39Chris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
20009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
20019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
200298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowLayeringTestRenderer renderer;
2003f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
200498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    EXPECT_EQ(4, renderer.getIndex());
200598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
200698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
200798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowClipping) {
2008d645640180c25c2711e99aa82ec629155f8e91baChris Craik    class ShadowClippingTestRenderer : public TestRendererBase {
2009d645640180c25c2711e99aa82ec629155f8e91baChris Craik    public:
2010d645640180c25c2711e99aa82ec629155f8e91baChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
2011d645640180c25c2711e99aa82ec629155f8e91baChris Craik            EXPECT_EQ(0, mIndex++);
2012d645640180c25c2711e99aa82ec629155f8e91baChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipState->rect)
2013d645640180c25c2711e99aa82ec629155f8e91baChris Craik                    << "Shadow must respect pre-barrier canvas clip value.";
2014d645640180c25c2711e99aa82ec629155f8e91baChris Craik        }
2015d645640180c25c2711e99aa82ec629155f8e91baChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
2016d645640180c25c2711e99aa82ec629155f8e91baChris Craik            EXPECT_EQ(1, mIndex++);
2017d645640180c25c2711e99aa82ec629155f8e91baChris Craik        }
2018d645640180c25c2711e99aa82ec629155f8e91baChris Craik    };
201906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2020d645640180c25c2711e99aa82ec629155f8e91baChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
2021d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // Apply a clip before the reorder barrier/shadow casting child is drawn.
2022d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // This clip must be applied to the shadow cast by the child.
20236c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect);
2024d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.insertReorderBarrier(true);
2025d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
2026d645640180c25c2711e99aa82ec629155f8e91baChris Craik    });
2027d645640180c25c2711e99aa82ec629155f8e91baChris Craik
20289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2029d645640180c25c2711e99aa82ec629155f8e91baChris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
20309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
20319cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2032d645640180c25c2711e99aa82ec629155f8e91baChris Craik    ShadowClippingTestRenderer renderer;
2033d645640180c25c2711e99aa82ec629155f8e91baChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2034d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_EQ(2, renderer.getIndex());
2035d645640180c25c2711e99aa82ec629155f8e91baChris Craik}
2036d645640180c25c2711e99aa82ec629155f8e91baChris Craik
203716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
203876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
2039d3daa3198e2212c985c634821682d5819346b653Chris Craik    class PropertyTestRenderer : public TestRendererBase {
2040d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
2041d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh        explicit PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback)
2042d3daa3198e2212c985c634821682d5819346b653Chris Craik                : mCallback(callback) {}
2043d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
2044d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(mIndex++, 0);
2045d3daa3198e2212c985c634821682d5819346b653Chris Craik            mCallback(op, state);
2046d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
2047d3daa3198e2212c985c634821682d5819346b653Chris Craik        std::function<void(const RectOp&, const BakedOpState&)> mCallback;
2048d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
2049d3daa3198e2212c985c634821682d5819346b653Chris Craik
205006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
205116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) {
205216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        propSetupCallback(props);
205376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        SkPaint paint;
205476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        paint.setColor(SK_ColorWHITE);
205576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
205616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
205776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
20589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200,
20599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
20609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
20619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
206276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    PropertyTestRenderer renderer(opValidateCallback);
2063f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
206476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
206576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
206676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
206798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
206876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
206976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setAlpha(0.5f);
207076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setHasOverlappingRendering(false);
207176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
207276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op";
207376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
207476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
207576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
207698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropClipping) {
207776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
207876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setClipToBounds(true);
207976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setClipBounds(Rect(10, 20, 300, 400));
208076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
208176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds)
208276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik                << "Clip rect should be intersection of node bounds and clip bounds";
208376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
208476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
208576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
208698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropRevealClip) {
208776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
208876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.mutableRevealClip().set(true, 50, 50, 25);
208976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
209076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        ASSERT_NE(nullptr, state.roundRectClipState);
209176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_TRUE(state.roundRectClipState->highPriority);
209276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(25, state.roundRectClipState->radius);
209376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect);
209476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
209576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
209676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
209798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOutlineClip) {
209876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
209976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.mutableOutline().setShouldClip(true);
210076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
210176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
210276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        ASSERT_NE(nullptr, state.roundRectClipState);
210376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_FALSE(state.roundRectClipState->highPriority);
210476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(5, state.roundRectClipState->radius);
210576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect);
210676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
210776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
210876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
210998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropTransform) {
211076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
211176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setLeftTopRightBottom(10, 10, 110, 110);
211276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
211376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
211476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setStaticMatrix(&staticMatrix);
211576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
211676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // ignored, since static overrides animation
211776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
211876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setAnimationMatrix(&animationMatrix);
211976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
212076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setTranslationX(10);
212176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setTranslationY(20);
212276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setScaleX(0.5f);
212376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setScaleY(0.7f);
212476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
212576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        Matrix4 matrix;
212676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.loadTranslate(10, 10, 0); // left, top
212776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.scale(1.2f, 1.2f, 1); // static matrix
212876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // ignore animation matrix, since static overrides it
212976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
213076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // translation xy
213176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.translate(10, 20);
213276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
213376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // scale xy (from default pivot - center)
213476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.translate(50, 50);
213576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.scale(0.5f, 0.7f, 1);
213676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.translate(-50, -50);
213776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform)
213876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik                << "Op draw matrix must match expected combination of transformation properties";
213976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
214076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
2141161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
21428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData {
21438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    uint32_t layerWidth = 0;
21448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    uint32_t layerHeight = 0;
21458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    Rect rectClippedBounds;
21468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    Matrix4 rectMatrix;
2147c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck    Matrix4 drawLayerMatrix;
21488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik};
21498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/**
21508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation:
21518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *     a) 0 < alpha < 1
21528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *     b) too big for layer (larger than maxTextureSize)
21538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *     c) overlapping rendering content
21548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform.
21558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *
21568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced
21578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip.
21588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */
21598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
216016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        std::function<void(RenderProperties&)> propSetupCallback) {
21618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    class SaveLayerAlphaClipTestRenderer : public TestRendererBase {
21628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    public:
2163d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh        explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
21648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik                : mOutData(outData) {}
21658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
21678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(0, mIndex++);
21688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->layerWidth = width;
21698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->layerHeight = height;
21708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            return nullptr;
21718ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
21728ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
21738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(1, mIndex++);
21748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->rectClippedBounds = state.computedState.clippedBounds;
21768ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->rectMatrix = state.computedState.transform;
21778ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
21788ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        void endLayer() override {
21798ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(2, mIndex++);
21808ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
21818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
21828ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(3, mIndex++);
2183c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck            mOutData->drawLayerMatrix = state.computedState.transform;
21848ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
218574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
218674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(4, mIndex++);
218774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
21888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    private:
21898ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        SaveLayerAlphaData* mOutData;
21908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    };
21918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21928ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize())
21938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            << "Node must be bigger than max texture size to exercise saveLayer codepath";
219406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000,
219516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) {
21968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setHasOverlappingRendering(true);
21978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
21988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        // apply other properties
219916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        propSetupCallback(properties);
220016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
220116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        SkPaint paint;
220216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        paint.setColor(SK_ColorWHITE);
220316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        canvas.drawRect(0, 0, 10000, 10000, paint);
22048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height
22069cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
22079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
22089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                sLightGeometry, Caches::getInstance());
22099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
22108ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
22118ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaClipTestRenderer renderer(outObservedData);
2212f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
22138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
22148ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    // assert, since output won't be valid if we haven't seen a save layer triggered
221574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
22168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
221898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
22198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaData observedData;
22208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
22218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationX(10); // offset rendering content
22228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationY(-2000); // offset rendering content
22238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(190u, observedData.layerWidth);
22258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(200u, observedData.layerHeight);
22265430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds)
22278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            << "expect content to be clipped to screen area";
22288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    Matrix4 expected;
22298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    expected.loadTranslate(0, -2000, 0);
22308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
22318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            << "expect content to be translated as part of being clipped";
2232c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck    expected.loadTranslate(10, 0, 0);
2233c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck    EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
2234c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck                << "expect drawLayer to be translated as part of being clipped";
22358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
223798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
22388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaData observedData;
22398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
22408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        // Translate and rotate the view so that the only visible part is the top left corner of
22418d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // the view. It will form an isosceles right triangle with a long side length of 200 at the
22428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        // bottom of the viewport.
22438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationX(100);
22448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationY(100);
22458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotX(0);
22468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotY(0);
22478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setRotation(45);
22488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    // ceil(sqrt(2) / 2 * 200) = 142
22508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(142u, observedData.layerWidth);
22518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(142u, observedData.layerHeight);
22525430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds);
22538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
22548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
225698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) {
22578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaData observedData;
22588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
22598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotX(0);
22608ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotY(0);
22618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setScaleX(2);
22628ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setScaleY(0.5f);
22638ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22648ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(100u, observedData.layerWidth);
22658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(400u, observedData.layerHeight);
22665430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds);
22678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
22688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
227098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clip_replace) {
227104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    class ClipReplaceTestRenderer : public TestRendererBase {
227204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    public:
227304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        void onColorOp(const ColorOp& op, const BakedOpState& state) override {
227404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            EXPECT_EQ(0, mIndex++);
227504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            EXPECT_TRUE(op.localClip->intersectWithRoot);
227604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect)
227704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik                    << "Expect resolved clip to be intersection of viewport clip and clip op";
227804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        }
227904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    };
228006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30,
228104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
228266b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace);
2283260ab726486317496bc12a57d599ea96dcde3284Mike Reed        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
228404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    });
228504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
22869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50,
22879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
22889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
22899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
229004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    ClipReplaceTestRenderer renderer;
229104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
229204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    EXPECT_EQ(1, renderer.getIndex());
229304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik}
229404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
229598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
2296db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on B
2297db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2298db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2299db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2300db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2301db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2302db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2303db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2304db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2305db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
2306db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2307db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2308db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2309db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2310db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2311db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2312db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2313db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2314db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2315db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2316db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2317db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2318db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2319db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2320db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2321db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2322db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2323db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2324db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
232598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
2326db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on E
2327db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  A
2328db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                / | \
2329db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               /  |  \
2330db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C   E
2331db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2332db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2333db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2334db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2335db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2336db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0,  nullptr); //nodeB
2337db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2338db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 2
2339db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2340db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2341db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2342db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2343db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 3
2344db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2345db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeE
2346db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2347db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2348db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2349db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2350db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2351db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2352db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2353db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2354db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(4, renderer.getIndex());
2355db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2356db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
235798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
2358db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected without receiver
2359db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2360db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2361db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2362db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2363db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2364db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2365db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2366db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2367db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, nullptr); //nodeB
2368db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2369db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 255,  [](RenderProperties& props, RecordingCanvas& canvas) {
2370db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                //not having a projection receiver is an undefined behavior
2371db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2372db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2373db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2374db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
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(2, renderer.getIndex());
2384db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2385db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
238698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
2387db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on C
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            props.setProjectionReceiver(true);
2399db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
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(3, renderer.getIndex());
2413db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2414db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
241598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
2416db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2417db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2418db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, nullptr); //nodeB
2419db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2420db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) {
2421db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                //having a node that is projected on itself is an undefined/unexpected behavior
2422db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2423db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2424db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2425db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2426db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2427db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2428db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2429db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2430db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2431db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2432db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2433db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2434db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2435db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(2, renderer.getIndex());
2436db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2437db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
243898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
2439db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
2440db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
2441db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
2442db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on B. R is not expected to be drawn (see Sibling2 outcome below),
2443db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev       but for some reason it is drawn.
2444db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2445db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               /|\
2446db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              / | \
2447db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev             B  C  R
2448db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2449db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2450db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2451db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
2452db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2453db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2454db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2455db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2456db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2457db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectBackwards(true);
2458db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setClipToBounds(false);
2459db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeR
2460db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2461db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2462db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2463db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2464db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2465db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2466db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2467db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2468db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2469db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2470db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
247198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
2472db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
2473db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2474db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2475db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G
2476db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               /|\
2477db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              / | \
2478db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev             B  C  R
2479db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2480db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2481db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2482db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2483db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2484db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2485db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeB
2486db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2487db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeC
2488db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2489db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2490db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2491db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2492db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeG
2493db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2494db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2495db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2496db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2497db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2498db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2499db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2500db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2501db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2502db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2503db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
250498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
2505db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on B
2506db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2507db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2508db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                B
2509db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2510db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                C
2511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                R
2513db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2515db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
2517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2519db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setProjectBackwards(true);
2521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setClipToBounds(false);
2522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                } ); //nodeR
2523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeC
2524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2529db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2530db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2531db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2532db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2533db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2534db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2535db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
253698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
2537db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* B and G are receivables, R is backward projected
2538db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2539db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2540db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2541db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                 / \
2542db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G   R
2543db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2544db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2545db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2546db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2548db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2549db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2550db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2551db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2552db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeG
2553db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2554db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2555db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2556db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2557db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2558db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2559db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2560db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2561db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2562db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2563db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2564db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2565db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2566db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(4, renderer.getIndex());
2567db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2568db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
256998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
2570db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* B and G are receivables, G is backward projected
2571db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2572db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2573db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2574db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                 / \
2575db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G   R
2576db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2577db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2578db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2579db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2580db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2581db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2582db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2583db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2584db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2585db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2586db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2587db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeG
2588db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2589db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2590db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2591db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2592db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2593db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2594db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2595db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2596db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2597db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2598db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2599db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(4, renderer.getIndex());
2600db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2601db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
260298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
2603db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* B and G are receivables, R is backward projected
2604db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2605db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2606db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2607db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                 / \
2608db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G   D
2609db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    |
2610db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    R
2611db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2612db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2613db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2614db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2615db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2616db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2617db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2618db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2619db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2620db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeG
2621db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { //D
2622db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2623db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setProjectBackwards(true);
2624db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setClipToBounds(false);
2625db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                } ); //nodeR
2626db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeD
2627db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2628db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2629db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2630db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2631db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2632db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2633db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2634db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2635db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2636db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(5, renderer.getIndex());
2637db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2638db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
26396fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer
26406fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android
2641