FrameBuilderTests.cpp revision 98c78dad1969e2321cfee2085faa55d95bba7e29
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
3149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(800, 600), 800, 600,
3159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
3169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNodeScene(nodes, contentDrawBounds);
3179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
3189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    DeferRenderNodeSceneTestRenderer renderer;
3199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
3209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    EXPECT_EQ(4, renderer.getIndex());
3219cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik}
3229cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
32398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_noFbo0) {
3246246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    class EmptyNoFbo0TestRenderer : public TestRendererBase {
3256246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    public:
3266246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
3276246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
3286246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3296246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endFrame(const Rect& repaintRect) override {
3306246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
3316246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3326246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    };
3336246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
3349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // Use layer update constructor, so no work is enqueued for Fbo0
3359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    LayerUpdateQueue emptyLayerUpdateQueue;
3369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(emptyLayerUpdateQueue, sLightGeometry, Caches::getInstance());
3376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EmptyNoFbo0TestRenderer renderer;
3386246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
3396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik}
3406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
34198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, empty_withFbo0) {
3426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    class EmptyWithFbo0TestRenderer : public TestRendererBase {
3436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    public:
3446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
3456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(0, mIndex++);
3466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endFrame(const Rect& repaintRect) override {
3486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(1, mIndex++);
3496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
3506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    };
35106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
3526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
3536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        // no drawn content
3546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    });
3556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
3569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // Draw, but pass node without draw content, so no work is done for primary frame
3579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
3589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
3599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
3609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
3616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EmptyWithFbo0TestRenderer renderer;
3626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
3636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EXPECT_EQ(2, renderer.getIndex()) << "No drawing content produced,"
3646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            " but fbo0 update lifecycle should still be observed";
3656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik}
3666246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
36798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_rects) {
36880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    class AvoidOverdrawRectsTestRenderer : public TestRendererBase {
36980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    public:
37080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
37180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            EXPECT_EQ(mIndex++, 0) << "Should be one rect";
37280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds)
37380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                    << "Last rect should occlude others.";
37480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        }
37580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    };
37606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
37780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
37880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
37980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
38080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(10, 10, 190, 190, SkPaint());
38180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    });
38280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
38380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    // Damage (and therefore clip) is same as last draw, subset of renderable area.
38480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    // This means last op occludes other contents, and they'll be rejected to avoid overdraw.
3859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 190, 190), 200, 200,
3869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
3879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
38880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
38980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    EXPECT_EQ(3u, node->getDisplayList()->getOps().size())
39080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            << "Recording must not have rejected ops, in order for this test to be valid";
39180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
39280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    AvoidOverdrawRectsTestRenderer renderer;
39380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
39480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    EXPECT_EQ(1, renderer.getIndex()) << "Expect exactly one op";
39580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik}
39680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
39798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, avoidOverdraw_bitmaps) {
398aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> opaqueBitmap(TestUtils::createBitmap(50, 50,
399aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv            SkColorType::kRGB_565_SkColorType));
400aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> transpBitmap(TestUtils::createBitmap(50, 50,
401aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv            SkColorType::kAlpha_8_SkColorType));
40280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    class AvoidOverdrawBitmapsTestRenderer : public TestRendererBase {
40380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    public:
40480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
40580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            switch(mIndex++) {
40680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            case 0:
407ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv                EXPECT_EQ(opaqueBitmap.get(), op.bitmap);
40880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                break;
40980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            case 1:
410ec4a4b13eae2241d1613890c1c1c096bed891845sergeyv                EXPECT_EQ(transpBitmap.get(), op.bitmap);
41180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                break;
41280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            default:
41380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik                ADD_FAILURE() << "Only two ops expected.";
41480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            }
41580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        }
41680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    };
41780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
41806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 50, 50,
41980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
42080d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 50, 50, SkPaint());
42180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        canvas.drawRect(0, 0, 50, 50, SkPaint());
422aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
42380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
42480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik        // only the below draws should remain, since they're
425aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*opaqueBitmap, 0, 0, nullptr);
426aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*transpBitmap, 0, 0, nullptr);
42780d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    });
4289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(50, 50), 50, 50,
4299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
4309cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
43180d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
43280d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    EXPECT_EQ(5u, node->getDisplayList()->getOps().size())
43380d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik            << "Recording must not have rejected ops, in order for this test to be valid";
43480d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
43580d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    AvoidOverdrawBitmapsTestRenderer renderer;
43680d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
437a82ffc549bd6dbf8cfc6f4d646d0f458dca54014sergeyv    EXPECT_EQ(2, renderer.getIndex()) << "Expect exactly two ops";
43880d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik}
43980d2ade939153da87b3cd3b0a69a713bf68b64baChris Craik
44098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clippedMerging) {
44193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    class ClippedMergingTestRenderer : public TestRendererBase {
44293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    public:
44393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        void onMergedBitmapOps(const MergedBakedOpList& opList) override {
44493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(0, mIndex);
44593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            mIndex += opList.count;
44693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(4u, opList.count);
44793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(Rect(10, 10, 90, 90), opList.clip);
44893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik            EXPECT_EQ(OpClipSideFlags::Left | OpClipSideFlags::Top | OpClipSideFlags::Right,
44993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik                    opList.clipSideFlags);
45093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        }
45193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    };
45206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
45306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
454aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(20, 20));
45593e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
45693e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // left side clipped (to inset left half)
45766b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(10, 0, 50, 100, SkClipOp::kReplace);
458aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 0, 40, nullptr);
45993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
46093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // top side clipped (to inset top half)
46166b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(0, 10, 100, 50, SkClipOp::kReplace);
462aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 40, 0, nullptr);
46393e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
46493e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // right side clipped (to inset right half)
46566b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(50, 0, 90, 100, SkClipOp::kReplace);
466aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 80, 40, nullptr);
46793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
46893e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik        // bottom not clipped, just abutting (inset bottom half)
46966b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(0, 50, 100, 90, SkClipOp::kReplace);
470aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 40, 70, nullptr);
47193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    });
47293e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
4739cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
4749cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
4759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
4769cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
47793e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    ClippedMergingTestRenderer renderer;
478f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
47993e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik    EXPECT_EQ(4, renderer.getIndex());
48093e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik}
48193e53e09dde84a5a6d6931b81198d94e2ae1c6ebChris Craik
48298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, regionClipStopsMerge) {
483f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    class RegionClipStopsMergeTestRenderer : public TestRendererBase {
484f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    public:
485f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        void onTextOp(const TextOp& op, const BakedOpState& state) override { mIndex++; }
486f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    };
487f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
488f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
489f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        SkPath path;
490f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        path.addCircle(200, 200, 200, SkPath::kCW_Direction);
491f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        canvas.save(SaveFlags::MatrixClip);
4926c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipPath(&path, SkClipOp::kIntersect);
493f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        SkPaint paint;
494f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
495f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        paint.setAntiAlias(true);
496f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        paint.setTextSize(50);
497f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
498f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 200);
499f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik        canvas.restore();
500f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    });
501f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik
502f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
503f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik            sLightGeometry, Caches::getInstance());
504f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
505f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik
506f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    RegionClipStopsMergeTestRenderer renderer;
507f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
508f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik    EXPECT_EQ(2, renderer.getIndex());
509f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik}
510f8f56cbb20817c295fe8c6f886dca5e2912e1996Chris Craik
51198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textMerging) {
512d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    class TextMergingTestRenderer : public TestRendererBase {
513d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    public:
514d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        void onMergedTextOps(const MergedBakedOpList& opList) override {
515d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(0, mIndex);
516d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            mIndex += opList.count;
517d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(2u, opList.count);
518d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(OpClipSideFlags::Top, opList.clipSideFlags);
519d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(OpClipSideFlags::Top, opList.states[0]->computedState.clipSideFlags);
520d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            EXPECT_EQ(OpClipSideFlags::None, opList.states[1]->computedState.clipSideFlags);
521d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        }
522d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    };
52306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
52406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
525d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        SkPaint paint;
526d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
527d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        paint.setAntiAlias(true);
528d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik        paint.setTextSize(50);
529dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
530dccca44ffda4836b56a21da95a046c9708ffd49csergeyv        TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
531d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    });
5329cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
5339cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
5349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
5359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
536d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    TextMergingTestRenderer renderer;
537f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
538d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik    EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops";
539d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik}
540d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
54198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStrikethrough) {
542a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    const int LOOPS = 5;
543a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    class TextStrikethroughTestRenderer : public TestRendererBase {
544a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    public:
545a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
546a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            EXPECT_TRUE(mIndex++ >= LOOPS) << "Strikethrough rects should be above all text";
547a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
54815c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik        void onMergedTextOps(const MergedBakedOpList& opList) override {
54915c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            EXPECT_EQ(0, mIndex);
55015c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            mIndex += opList.count;
55115c3f19a445b8df575911a16e8a6dba755a084b5Chris Craik            EXPECT_EQ(5u, opList.count);
552a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
553a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    };
55406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 2000,
5558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
556a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        SkPaint textPaint;
557a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        textPaint.setAntiAlias(true);
558a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        textPaint.setTextSize(20);
559a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        textPaint.setStrikeThruText(true);
56042a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik        textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
561a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        for (int i = 0; i < LOOPS; i++) {
562dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
563a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik        }
564a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    });
5659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
5669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 2000), 200, 2000,
5679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
5689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
5699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
570a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    TextStrikethroughTestRenderer renderer;
571f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
572a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    EXPECT_EQ(2 * LOOPS, renderer.getIndex())
573d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            << "Expect number of ops = 2 * loop count";
574b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
575b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
5767c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craikstatic auto styles = {
5777c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style };
5787c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
57998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textStyle) {
5807c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    class TextStyleTestRenderer : public TestRendererBase {
5817c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    public:
5827c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        void onMergedTextOps(const MergedBakedOpList& opList) override {
5837c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            ASSERT_EQ(0, mIndex);
5847c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            ASSERT_EQ(3u, opList.count);
5857c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            mIndex += opList.count;
5867c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
5877c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            int index = 0;
5887c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            for (auto style : styles) {
5897c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                auto state = opList.states[index++];
5907c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                ASSERT_EQ(style, state->op->paint->getStyle())
5917c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                        << "Remainder of validation relies upon stable merged order";
5927c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                ASSERT_EQ(0, state->computedState.clipSideFlags)
5937c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                        << "Clipped bounds validation requires unclipped ops";
5947c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            }
5957c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
5967c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            Rect fill = opList.states[0]->computedState.clippedBounds;
5977c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            Rect stroke = opList.states[1]->computedState.clippedBounds;
5987c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_EQ(stroke, opList.states[2]->computedState.clippedBounds)
5997c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik                    << "Stroke+Fill should be same as stroke";
6007c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
6017c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_TRUE(stroke.contains(fill));
6027c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_FALSE(fill.contains(stroke));
6037c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
60479abbf22d4f672208327546661e694d837f564a9Derek Sollenberger            // outset by half the stroke width
6057c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            Rect outsetFill(fill);
60679abbf22d4f672208327546661e694d837f564a9Derek Sollenberger            outsetFill.outset(5);
6077c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            EXPECT_EQ(stroke, outsetFill);
6087c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        }
6097c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    };
61006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
61106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
6127c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        SkPaint paint;
6137c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
6147c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setAntiAlias(true);
6157c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setTextSize(50);
6167c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        paint.setStrokeWidth(10);
6177c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
6187c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        // draw 3 copies of the same text overlapping, each with a different style.
6197c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        // They'll get merged, but with
6207c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        for (auto style : styles) {
6217c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik            paint.setStyle(style);
622dccca44ffda4836b56a21da95a046c9708ffd49csergeyv            TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
6237c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik        }
6247c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    });
6259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
6269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
6279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
6287c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    TextStyleTestRenderer renderer;
6297c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
6307c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik    EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops";
6317c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik}
6327c02cab0b1c7db0fb786893240ec6f00f16c2ceeChris Craik
63398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_clipLocalMatrix) {
634aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    class TextureLayerClipLocalMatrixTestRenderer : public TestRendererBase {
635d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    public:
636d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
637d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            EXPECT_EQ(0, mIndex++);
638e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipRect());
639d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            EXPECT_EQ(Rect(50, 50, 105, 105), state.computedState.clippedBounds);
640d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
641d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            Matrix4 expected;
642d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            expected.loadTranslate(5, 5, 0);
643d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
644d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        }
645d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    };
646d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
647d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
648243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik            SkMatrix::MakeTrans(5, 5));
649d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
65006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
651d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
652eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
6536c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(50, 50, 150, 150, SkClipOp::kIntersect);
654d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        canvas.drawLayer(layerUpdater.get());
655d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        canvas.restore();
656d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    });
6579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
6589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
6599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
6609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
6619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
662aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    TextureLayerClipLocalMatrixTestRenderer renderer;
663f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
664d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    EXPECT_EQ(1, renderer.getIndex());
665d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik}
666d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
66798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_combineMatrices) {
668aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    class TextureLayerCombineMatricesTestRenderer : public TestRendererBase {
669aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    public:
670aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        void onTextureLayerOp(const TextureLayerOp& op, const BakedOpState& state) override {
671aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            EXPECT_EQ(0, mIndex++);
672aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
673aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            Matrix4 expected;
674aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            expected.loadTranslate(35, 45, 0);
675aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
676aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        }
677aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    };
678aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
679aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
680aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            SkMatrix::MakeTrans(5, 5));
681aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
68206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
683aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
684aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.save(SaveFlags::MatrixClip);
685aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.translate(30, 40);
686aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.drawLayer(layerUpdater.get());
687aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.restore();
688aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    });
689aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
6909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
6919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
6929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
6939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
694aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    TextureLayerCombineMatricesTestRenderer renderer;
695aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
696aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    EXPECT_EQ(1, renderer.getIndex());
697aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik}
698aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
69998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, textureLayer_reject) {
700aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    auto layerUpdater = TestUtils::createTextureLayerUpdater(renderThread, 100, 100,
701aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            SkMatrix::MakeTrans(5, 5));
70298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel    EXPECT_EQ(Layer::Api::OpenGL, layerUpdater->backingLayer()->getApi());
7038cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel
7048cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel    GlLayer* glLayer = static_cast<GlLayer*>(layerUpdater->backingLayer());
7058cd3edfa15cc9cdbffa935d19ab894426b08d174Greg Daniel    glLayer->setRenderTarget(GL_NONE); // Should be rejected
706aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
70706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
708aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik            [&layerUpdater](RenderProperties& props, RecordingCanvas& canvas) {
709aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik        canvas.drawLayer(layerUpdater.get());
710aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    });
7119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
7129cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
7139cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
7149cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
7159cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
716aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    FailRenderer renderer;
717aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
718aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik}
719aafb01d8ade0def3f51b74ae3bbc610c4ab33044Chris Craik
72098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, functor_reject) {
721223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    class FunctorTestRenderer : public TestRendererBase {
722223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    public:
723223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik        void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override {
724223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik            EXPECT_EQ(0, mIndex++);
725223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik        }
726223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    };
727223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    Functor noopFunctor;
728223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik
729223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    // 1 million pixel tall view, scrolled down 80%
73006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto scrolledFunctorView = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 1000000,
731223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik            [&noopFunctor](RenderProperties& props, RecordingCanvas& canvas) {
732223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik        canvas.translate(0, -800000);
733cd1c3eba69d044b551cededad75474038f919890John Reck        canvas.callDrawGLFunction(&noopFunctor, nullptr);
734223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    });
735223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik
7369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
7373a5811b50157e7ba50854caf957e806aee794d39Chris Craik            sLightGeometry, Caches::getInstance());
7389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(scrolledFunctorView));
7399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
740223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    FunctorTestRenderer renderer;
741223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
742223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected";
743223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik}
744223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik
74598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, deferColorOp_unbounded) {
746a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    class ColorTestRenderer : public TestRendererBase {
747a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    public:
748a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik        void onColorOp(const ColorOp& op, const BakedOpState& state) override {
749a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            EXPECT_EQ(0, mIndex++);
750a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds)
751a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik                    << "Color op should be expanded to bounds of surrounding";
752a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik        }
753a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    };
754a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
75506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto unclippedColorView = TestUtils::createNode<RecordingCanvas>(0, 0, 10, 10,
756a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
757a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik        props.setClipToBounds(false);
758260ab726486317496bc12a57d599ea96dcde3284Mike Reed        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
759a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    });
760a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
7619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
762a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik            sLightGeometry, Caches::getInstance());
7639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(unclippedColorView));
7649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
765a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    ColorTestRenderer renderer;
766a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
767a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik    EXPECT_EQ(1, renderer.getIndex()) << "ColorOp should not be rejected";
768a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik}
769a204848b1dc63877a12e2d24108e9d8e1e691e28Chris Craik
77098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, renderNode) {
771d3daa3198e2212c985c634821682d5819346b653Chris Craik    class RenderNodeTestRenderer : public TestRendererBase {
772d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
773d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
774d3daa3198e2212c985c634821682d5819346b653Chris Craik            switch(mIndex++) {
775d3daa3198e2212c985c634821682d5819346b653Chris Craik            case 0:
7765430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds);
777d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
778d3daa3198e2212c985c634821682d5819346b653Chris Craik                break;
779d3daa3198e2212c985c634821682d5819346b653Chris Craik            case 1:
780d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds);
781d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
782d3daa3198e2212c985c634821682d5819346b653Chris Craik                break;
783d3daa3198e2212c985c634821682d5819346b653Chris Craik            default:
784d3daa3198e2212c985c634821682d5819346b653Chris Craik                ADD_FAILURE();
785d3daa3198e2212c985c634821682d5819346b653Chris Craik            }
786d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
787d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
788d3daa3198e2212c985c634821682d5819346b653Chris Craik
78906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
7908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
791b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        SkPaint paint;
792b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        paint.setColor(SK_ColorWHITE);
793b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
794b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
795b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
79606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
797d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            [&child](RenderProperties& props, RecordingCanvas& canvas) {
798ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        SkPaint paint;
799ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        paint.setColor(SK_ColorDKGRAY);
800ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        canvas.drawRect(0, 0, 200, 200, paint);
801ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
802eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
803ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        canvas.translate(40, 40);
804d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik        canvas.drawRenderNode(child.get());
805ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        canvas.restore();
806b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    });
807b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
8089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
8099cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
8109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
8119cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
8125854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    RenderNodeTestRenderer renderer;
813f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
814223e3b6c2b53a66b4efd8040edfe23ed1a5c925eChris Craik    EXPECT_EQ(2, renderer.getIndex());
815b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
816b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
81798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clipped) {
818d3daa3198e2212c985c634821682d5819346b653Chris Craik    class ClippedTestRenderer : public TestRendererBase {
819d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
820d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
821d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
822d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clippedBounds);
823e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(10, 20, 30, 40), state.computedState.clipRect());
824d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
825d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
826d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
827d3daa3198e2212c985c634821682d5819346b653Chris Craik
82806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
8298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
830aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        sk_sp<Bitmap> bitmap(TestUtils::createBitmap(200, 200));
831aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        canvas.drawBitmap(*bitmap, 0, 0, nullptr);
832ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik    });
833ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
8349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    // clip to small area, should see in receiver
8359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 20, 30, 40), 200, 200,
8369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
8379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
8389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
8395854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    ClippedTestRenderer renderer;
840f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
841ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik}
842ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
84398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_simple) {
844d3daa3198e2212c985c634821682d5819346b653Chris Craik    class SaveLayerSimpleTestRenderer : public TestRendererBase {
845d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
846d3daa3198e2212c985c634821682d5819346b653Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
847d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
848d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(180u, width);
849d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(180u, height);
850d3daa3198e2212c985c634821682d5819346b653Chris Craik            return nullptr;
851d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
852d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
853d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(2, mIndex++);
854d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
855d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
856d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(1, mIndex++);
857d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), op.unmappedBounds);
8585430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik            EXPECT_EQ(Rect(180, 180), state.computedState.clippedBounds);
859e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(180, 180), state.computedState.clipRect());
860d3daa3198e2212c985c634821682d5819346b653Chris Craik
861d3daa3198e2212c985c634821682d5819346b653Chris Craik            Matrix4 expectedTransform;
862d3daa3198e2212c985c634821682d5819346b653Chris Craik            expectedTransform.loadTranslate(-10, -10, 0);
863d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_MATRIX_APPROX_EQ(expectedTransform, state.computedState.transform);
864d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
865d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
866d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(3, mIndex++);
867d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
868e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
869d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
870d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
87174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
87274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(4, mIndex++);
87374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(nullptr, offscreenBuffer);
87474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
875d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
876d3daa3198e2212c985c634821682d5819346b653Chris Craik
87706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
8788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
879eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 10, 190, 190, 128, SaveFlags::ClipToLayer);
8806fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(10, 10, 190, 190, SkPaint());
8816fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
8826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
8839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
8849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
8859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
8869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
8879cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
8885854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    SaveLayerSimpleTestRenderer renderer;
889f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
89074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(5, renderer.getIndex());
891b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
8926fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
89398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_nested) {
894d3daa3198e2212c985c634821682d5819346b653Chris Craik    /* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as:
895d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startTemporaryLayer2, rect2 endLayer2
896d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startTemporaryLayer1, rect1, drawLayer2, endLayer1
897d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startFrame, layerOp1, endFrame
898d3daa3198e2212c985c634821682d5819346b653Chris Craik     */
899d3daa3198e2212c985c634821682d5819346b653Chris Craik    class SaveLayerNestedTestRenderer : public TestRendererBase {
900d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
901d3daa3198e2212c985c634821682d5819346b653Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
902d3daa3198e2212c985c634821682d5819346b653Chris Craik            const int index = mIndex++;
903d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 0) {
904d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(400u, width);
905d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(400u, height);
906d3daa3198e2212c985c634821682d5819346b653Chris Craik                return (OffscreenBuffer*) 0x400;
907d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 3) {
908d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(800u, width);
909d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(800u, height);
910d3daa3198e2212c985c634821682d5819346b653Chris Craik                return (OffscreenBuffer*) 0x800;
911d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
912d3daa3198e2212c985c634821682d5819346b653Chris Craik            return (OffscreenBuffer*) nullptr;
913d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
914d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
915d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
916d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(index == 2 || index == 6);
917d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
91898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
919d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(7, mIndex++);
920d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
921e4db79de127cfe961195f52907af8451026eaa20Chris Craik        void endFrame(const Rect& repaintRect) override {
922d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(9, mIndex++);
923d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
924d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
925d3daa3198e2212c985c634821682d5819346b653Chris Craik            const int index = mIndex++;
926d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 1) {
9275430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner rect
928d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 4) {
9295430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer rect
930d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
931d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
932d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
933d3daa3198e2212c985c634821682d5819346b653Chris Craik            const int index = mIndex++;
934d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 5) {
935d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x400, *op.layerHandle);
9365430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(400, 400), op.unmappedBounds); // inner layer
937d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 8) {
938d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x800, *op.layerHandle);
9395430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik                EXPECT_EQ(Rect(800, 800), op.unmappedBounds); // outer layer
940d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
941d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
94274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
94374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            const int index = mIndex++;
94474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            // order isn't important, but we need to see both
94574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            if (index == 10) {
94674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x400, offscreenBuffer);
94774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            } else if (index == 11) {
94874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik                EXPECT_EQ((OffscreenBuffer*)0x800, offscreenBuffer);
94974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            } else { ADD_FAILURE(); }
95074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
951d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
952d3daa3198e2212c985c634821682d5819346b653Chris Craik
95306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 800, 800,
9548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
955eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 800, 800, 128, SaveFlags::ClipToLayer);
9566fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        {
9576fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            canvas.drawRect(0, 0, 800, 800, SkPaint());
958eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita            canvas.saveLayerAlpha(0, 0, 400, 400, 128, SaveFlags::ClipToLayer);
9596fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            {
9606fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik                canvas.drawRect(0, 0, 400, 400, SkPaint());
9616fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            }
9626fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            canvas.restore();
9636fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        }
9646fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
9656fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
9666fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
9679cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(800, 800), 800, 800,
9689cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
9699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
9709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
9715854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    SaveLayerNestedTestRenderer renderer;
972f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
97374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(12, renderer.getIndex());
9746fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik}
9756fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
97698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayer_contentRejection) {
97706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
9788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                [](RenderProperties& props, RecordingCanvas& canvas) {
979eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
9806c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(200, 200, 400, 400, SkClipOp::kIntersect);
981eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(200, 200, 400, 400, 128, SaveFlags::ClipToLayer);
9826fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
9836fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        // draw within save layer may still be recorded, but shouldn't be drawn
9846fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.drawRect(200, 200, 400, 400, SkPaint());
9856fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
9866fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
9876fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik        canvas.restore();
9886fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    });
9899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
9909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
9919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
9929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
9936fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
9945854b34881b1a747ac80b5077869ef270a92b1f4Chris Craik    FailRenderer renderer;
9956fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    // should see no ops, even within the layer, since the layer should be rejected
996f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
997b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}
9986fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
99998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_simple) {
1000b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase {
1001b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public:
1002b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1003b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(0, mIndex++);
1004b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
10057435eb148e72382126e9073183e881357bb38a8bChris Craik            EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState);
1006b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1007b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1008b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
1009b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(1, mIndex++);
1010b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            ASSERT_NE(nullptr, op.paint);
1011260ab726486317496bc12a57d599ea96dcde3284Mike Reed            ASSERT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint));
1012b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1013b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1014b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(2, mIndex++);
1015b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(200, 200), op.unmappedBounds);
1016b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clippedBounds);
1017b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(200, 200), state.computedState.clipRect());
1018b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1019b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1020b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1021b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(3, mIndex++);
1022b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds);
10237435eb148e72382126e9073183e881357bb38a8bChris Craik            EXPECT_CLIP_RECT(Rect(200, 200), state.computedState.clipState);
1024b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1025b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1026b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    };
1027b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
102806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1029b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1030eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
1031b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
1032b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1033b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
10349cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
10359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
10369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
10379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
10389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1039b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    SaveLayerUnclippedSimpleTestRenderer renderer;
1040f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1041b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(4, renderer.getIndex());
1042b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1043b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
104498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_round) {
1045d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    class SaveLayerUnclippedRoundTestRenderer : public TestRendererBase {
1046d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    public:
1047d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1048d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(0, mIndex++);
1049d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds)
1050d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik                    << "Bounds rect should round out";
1051d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        }
1052d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {}
1053d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {}
1054d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1055d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(1, mIndex++);
1056d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            EXPECT_EQ(Rect(10, 10, 190, 190), state.computedState.clippedBounds)
1057d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik                    << "Bounds rect should round out";
1058d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        }
1059d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    };
1060d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
106106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1062d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1063d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        canvas.saveLayerAlpha(10.95f, 10.5f, 189.75f, 189.25f, // values should all round out
1064d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik                128, (SaveFlags::Flags)(0));
1065d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
1066d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik        canvas.restore();
1067d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    });
1068d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
1069d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
1070d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik            sLightGeometry, Caches::getInstance());
1071d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
1072d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
1073d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    SaveLayerUnclippedRoundTestRenderer renderer;
1074d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1075d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik    EXPECT_EQ(2, renderer.getIndex());
1076d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik}
1077d5a90114128f4d3d528f1a0e93651496c968f940Chris Craik
107898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
1079b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase {
1080b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public:
1081b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1082b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1083b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_GT(4, index);
1084b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, op.unmappedBounds.getWidth());
1085b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, op.unmappedBounds.getHeight());
1086b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            if (index == 0) {
1087b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(10, 10), state.computedState.clippedBounds);
1088b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            } else if (index == 1) {
1089b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(190, 0, 200, 10), state.computedState.clippedBounds);
1090b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            } else if (index == 2) {
1091b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(0, 190, 10, 200), state.computedState.clippedBounds);
1092b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            } else if (index == 3) {
1093b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_EQ(Rect(190, 190, 200, 200), state.computedState.clippedBounds);
1094b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            }
1095b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1096b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
1097b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(4, mIndex++);
1098b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            ASSERT_EQ(op.vertexCount, 16u);
1099b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            for (size_t i = 0; i < op.vertexCount; i++) {
1100b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                auto v = op.vertices[i];
1101b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_TRUE(v.x == 0 || v.x == 10 || v.x == 190 || v.x == 200);
1102b87eadda1818034ce03d85f30388384d1ac65916Chris Craik                EXPECT_TRUE(v.y == 0 || v.y == 10 || v.y == 190 || v.y == 200);
1103b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            }
1104b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1105b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1106b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, mIndex++);
1107b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1108b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1109b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_LT(5, mIndex++);
1110b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1111b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    };
1112b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
111306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1114b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1115b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
1116eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        int restoreTo = canvas.save(SaveFlags::MatrixClip);
1117b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.scale(2, 2);
1118eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 5, 5, 128, SaveFlags::MatrixClip);
1119eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(95, 0, 100, 5, 128, SaveFlags::MatrixClip);
1120eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 95, 5, 100, 128, SaveFlags::MatrixClip);
1121eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(95, 95, 100, 100, 128, SaveFlags::MatrixClip);
1122b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(0, 0, 100, 100, SkPaint());
1123b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restoreToCount(restoreTo);
1124b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
11259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
11269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
11279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
11289cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
11299cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1130b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    SaveLayerUnclippedMergedClearsTestRenderer renderer;
1131f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1132b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    EXPECT_EQ(10, renderer.getIndex())
1133b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            << "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect.";
1134b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1135b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
113698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
11374876de16e34622634266d09522c9153c78c7c2fbChris Craik    class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase {
11384876de16e34622634266d09522c9153c78c7c2fbChris Craik    public:
11394876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
11404876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(0, mIndex++);
11414876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11424876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
11434876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(1, mIndex++);
11444876de16e34622634266d09522c9153c78c7c2fbChris Craik            ASSERT_NE(nullptr, op.paint);
1145260ab726486317496bc12a57d599ea96dcde3284Mike Reed            EXPECT_EQ(SkBlendMode::kClear, PaintUtils::getBlendModeDirect(op.paint));
11464876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clippedBounds)
11474876de16e34622634266d09522c9153c78c7c2fbChris Craik                    << "Expect dirty rect as clip";
11484876de16e34622634266d09522c9153c78c7c2fbChris Craik            ASSERT_NE(nullptr, state.computedState.clipState);
11494876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(Rect(50, 50, 150, 150), state.computedState.clipState->rect);
11504876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
11514876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11524876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
11534876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(2, mIndex++);
11544876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11554876de16e34622634266d09522c9153c78c7c2fbChris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
11564876de16e34622634266d09522c9153c78c7c2fbChris Craik            EXPECT_EQ(3, mIndex++);
11574876de16e34622634266d09522c9153c78c7c2fbChris Craik        }
11584876de16e34622634266d09522c9153c78c7c2fbChris Craik    };
11594876de16e34622634266d09522c9153c78c7c2fbChris Craik
116006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
11614876de16e34622634266d09522c9153c78c7c2fbChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
11624876de16e34622634266d09522c9153c78c7c2fbChris Craik        // save smaller than clip, so we get unclipped behavior
11634876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.saveLayerAlpha(10, 10, 190, 190, 128, (SaveFlags::Flags)(0));
11644876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.drawRect(0, 0, 200, 200, SkPaint());
11654876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.restore();
11664876de16e34622634266d09522c9153c78c7c2fbChris Craik    });
11674876de16e34622634266d09522c9153c78c7c2fbChris Craik
11684876de16e34622634266d09522c9153c78c7c2fbChris Craik    // draw with partial screen dirty, and assert we see that rect later
11699cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(50, 50, 150, 150), 200, 200,
11709cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
11719cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
11729cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
11734876de16e34622634266d09522c9153c78c7c2fbChris Craik    SaveLayerUnclippedClearClipTestRenderer renderer;
11744876de16e34622634266d09522c9153c78c7c2fbChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
11754876de16e34622634266d09522c9153c78c7c2fbChris Craik    EXPECT_EQ(4, renderer.getIndex());
11764876de16e34622634266d09522c9153c78c7c2fbChris Craik}
11774876de16e34622634266d09522c9153c78c7c2fbChris Craik
117898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_reject) {
117906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
11804876de16e34622634266d09522c9153c78c7c2fbChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
11814876de16e34622634266d09522c9153c78c7c2fbChris Craik        // unclipped savelayer + rect both in area that won't intersect with dirty
11824876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.saveLayerAlpha(100, 100, 200, 200, 128, (SaveFlags::Flags)(0));
11834876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.drawRect(100, 100, 200, 200, SkPaint());
11844876de16e34622634266d09522c9153c78c7c2fbChris Craik        canvas.restore();
11854876de16e34622634266d09522c9153c78c7c2fbChris Craik    });
11864876de16e34622634266d09522c9153c78c7c2fbChris Craik
11874876de16e34622634266d09522c9153c78c7c2fbChris Craik    // draw with partial screen dirty that doesn't intersect with savelayer
11889cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200,
11899cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
11909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
11919cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
11924876de16e34622634266d09522c9153c78c7c2fbChris Craik    FailRenderer renderer;
11934876de16e34622634266d09522c9153c78c7c2fbChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
11944876de16e34622634266d09522c9153c78c7c2fbChris Craik}
11954876de16e34622634266d09522c9153c78c7c2fbChris Craik
1196b87eadda1818034ce03d85f30388384d1ac65916Chris Craik/* saveLayerUnclipped { saveLayer { saveLayerUnclipped { rect } } } will play back as:
1197b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer
1198b87eadda1818034ce03d85f30388384d1ac65916Chris Craik * - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe
1199b87eadda1818034ce03d85f30388384d1ac65916Chris Craik */
120098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, saveLayerUnclipped_complex) {
1201b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase {
1202b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    public:
1203b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
1204b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(0, mIndex++); // savelayer first
1205b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            return (OffscreenBuffer*)0xabcd;
1206b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1207b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
1208b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1209b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(index == 1 || index == 7);
1210b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1211b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onSimpleRectsOp(const SimpleRectsOp& op, const BakedOpState& state) override {
1212b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1213b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(index == 2 || index == 8);
1214b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1215b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1216b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(3, mIndex++);
1217b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            Matrix4 expected;
1218b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            expected.loadTranslate(-100, -100, 0);
1219b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(Rect(100, 100, 200, 200), state.computedState.clippedBounds);
1220b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_MATRIX_APPROX_EQ(expected, state.computedState.transform);
1221b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1222b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onCopyFromLayerOp(const CopyFromLayerOp& op, const BakedOpState& state) override {
1223b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            int index = mIndex++;
1224b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_TRUE(index == 4 || index == 10);
1225b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1226b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void endLayer() override {
1227b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(5, mIndex++);
1228b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1229b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
1230b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(6, mIndex++);
1231b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1232b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
1233b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(9, mIndex++);
123474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
1235b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
1236b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        void endFrame(const Rect& repaintRect) override {
1237b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            EXPECT_EQ(11, mIndex++);
1238b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        }
123974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
124074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(12, mIndex++);
124174af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ((OffscreenBuffer*)0xabcd, offscreenBuffer);
124274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
1243b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    };
1244b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
124506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 600, 600, // 500x500 triggers clipping
1246b87eadda1818034ce03d85f30388384d1ac65916Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1247eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(0, 0, 500, 500, 128, (SaveFlags::Flags)0); // unclipped
1248eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(100, 100, 400, 400, 128, SaveFlags::ClipToLayer); // clipped
1249eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(200, 200, 300, 300, 128, (SaveFlags::Flags)0); // unclipped
1250b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.drawRect(200, 200, 300, 300, SkPaint());
1251b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1252b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1253b87eadda1818034ce03d85f30388384d1ac65916Chris Craik        canvas.restore();
1254b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    });
12559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
12569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(600, 600), 600, 600,
12579cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
12589cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
12599cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1260b87eadda1818034ce03d85f30388384d1ac65916Chris Craik    SaveLayerUnclippedComplexTestRenderer renderer;
1261f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
126274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(13, renderer.getIndex());
1263b87eadda1818034ce03d85f30388384d1ac65916Chris Craik}
1264b87eadda1818034ce03d85f30388384d1ac65916Chris Craik
126598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_simple) {
1266d3daa3198e2212c985c634821682d5819346b653Chris Craik    class HwLayerSimpleTestRenderer : public TestRendererBase {
1267d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
126898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
1269d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
127098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportWidth);
127198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportHeight);
127298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect);
1273d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1274d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1275d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(1, mIndex++);
12760b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
1277d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity())
1278d3daa3198e2212c985c634821682d5819346b653Chris Craik                    << "Transform should be reset within layer";
1279d3daa3198e2212c985c634821682d5819346b653Chris Craik
1280e4db79de127cfe961195f52907af8451026eaa20Chris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect())
1281d3daa3198e2212c985c634821682d5819346b653Chris Craik                    << "Damage rect should be used to clip layer content";
1282d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1283d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
1284d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(2, mIndex++);
1285d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
128698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
1287d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(3, mIndex++);
1288d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1289d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
1290d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(4, mIndex++);
1291d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1292e4db79de127cfe961195f52907af8451026eaa20Chris Craik        void endFrame(const Rect& repaintRect) override {
1293d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(5, mIndex++);
1294d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1295d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
12960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
129706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
129816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [](RenderProperties& props, RecordingCanvas& canvas) {
129916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
13000b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        SkPaint paint;
13010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        paint.setColor(SK_ColorWHITE);
13020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
130316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
130498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer** layerHandle = node->getLayerHandle();
13050b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
130698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    // create RenderNode's layer here in same way prepareTree would
130798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
130898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = &layer;
13090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13109cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(node);
13110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    // only enqueue partial damage
131398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
13140b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
13150b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13169cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
13179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
13189cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
13199cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
13209cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
13210b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    HwLayerSimpleTestRenderer renderer;
1322f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
13230b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    EXPECT_EQ(6, renderer.getIndex());
13240b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
13250b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    // clean up layer pointer, so we can safely destruct RenderNode
132698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = nullptr;
13270b7e8245db728d127ada698be63d78b33fc6e4daChris Craik}
13280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
132998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, hwLayer_complex) {
1330d3daa3198e2212c985c634821682d5819346b653Chris Craik    /* parentLayer { greyRect, saveLayer { childLayer { whiteRect } } } will play back as:
1331d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startRepaintLayer(child), rect(grey), endLayer
1332d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startTemporaryLayer, drawLayer(child), endLayer
1333d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startRepaintLayer(parent), rect(white), drawLayer(saveLayer), endLayer
1334d3daa3198e2212c985c634821682d5819346b653Chris Craik     * - startFrame, drawLayer(parent), endLayerb
1335d3daa3198e2212c985c634821682d5819346b653Chris Craik     */
1336d3daa3198e2212c985c634821682d5819346b653Chris Craik    class HwLayerComplexTestRenderer : public TestRendererBase {
1337d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
1338d3daa3198e2212c985c634821682d5819346b653Chris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
1339d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(3, mIndex++); // savelayer first
1340d3daa3198e2212c985c634821682d5819346b653Chris Craik            return (OffscreenBuffer*)0xabcd;
1341d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
134298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
1343d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1344d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 0) {
1345d3daa3198e2212c985c634821682d5819346b653Chris Craik                // starting inner layer
134698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, offscreenBuffer->viewportWidth);
134798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, offscreenBuffer->viewportHeight);
1348d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 6) {
1349d3daa3198e2212c985c634821682d5819346b653Chris Craik                // starting outer layer
135098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, offscreenBuffer->viewportWidth);
135198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, offscreenBuffer->viewportHeight);
1352d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
1353d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1354d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1355d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1356d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 1) {
1357d3daa3198e2212c985c634821682d5819346b653Chris Craik                // inner layer's rect (white)
1358d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
1359d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 7) {
1360d3daa3198e2212c985c634821682d5819346b653Chris Craik                // outer layer's rect (grey)
1361d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
1362d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
1363d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1364d3daa3198e2212c985c634821682d5819346b653Chris Craik        void endLayer() override {
1365d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1366d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_TRUE(index == 2 || index == 5 || index == 9);
1367d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
136898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
1369d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(10, mIndex++);
1370d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1371d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
137298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            OffscreenBuffer* layer = *op.layerHandle;
1373d3daa3198e2212c985c634821682d5819346b653Chris Craik            int index = mIndex++;
1374d3daa3198e2212c985c634821682d5819346b653Chris Craik            if (index == 4) {
137598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, layer->viewportWidth);
137698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(100u, layer->viewportHeight);
1377d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 8) {
1378d3daa3198e2212c985c634821682d5819346b653Chris Craik                EXPECT_EQ((OffscreenBuffer*)0xabcd, *op.layerHandle);
1379d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else if (index == 11) {
138098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, layer->viewportWidth);
138198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik                EXPECT_EQ(200u, layer->viewportHeight);
1382d3daa3198e2212c985c634821682d5819346b653Chris Craik            } else { ADD_FAILURE(); }
1383d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1384e4db79de127cfe961195f52907af8451026eaa20Chris Craik        void endFrame(const Rect& repaintRect) override {
1385d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(12, mIndex++);
1386d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
138774af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
138874af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(13, mIndex++);
138974af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
1390d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
1391d3daa3198e2212c985c634821682d5819346b653Chris Craik
139206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(50, 50, 150, 150,
139316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [](RenderProperties& props, RecordingCanvas& canvas) {
139416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
13950b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        SkPaint paint;
13960b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        paint.setColor(SK_ColorWHITE);
13970b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
139816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
139998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer childLayer(renderThread.renderState(), Caches::getInstance(), 100, 100);
140098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *(child->getLayerHandle()) = &childLayer;
14010b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14020b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    RenderNode* childPtr = child.get();
140306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
140416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [childPtr](RenderProperties& props, RecordingCanvas& canvas) {
140516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
14060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        SkPaint paint;
14070b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        paint.setColor(SK_ColorDKGRAY);
14080b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRect(0, 0, 200, 200, paint);
14090b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
1410eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.saveLayerAlpha(50, 50, 150, 150, 128, SaveFlags::ClipToLayer);
14110b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.drawRenderNode(childPtr);
14120b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        canvas.restore();
141316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
141498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer parentLayer(renderThread.renderState(), Caches::getInstance(), 200, 200);
141598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *(parent->getLayerHandle()) = &parentLayer;
14160b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14179cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(parent);
14180b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
141998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
14200b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(100, 100));
14210b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
14220b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14239cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
14249cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
14259cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
14269cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
14279cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
14280b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    HwLayerComplexTestRenderer renderer;
1429f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
143074af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(14, renderer.getIndex());
14310b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14320b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    // clean up layer pointers, so we can safely destruct RenderNodes
14330b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    *(child->getLayerHandle()) = nullptr;
14340b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    *(parent->getLayerHandle()) = nullptr;
14350b7e8245db728d127ada698be63d78b33fc6e4daChris Craik}
14360b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14376246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
143898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, buildLayer) {
14396246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    class BuildLayerTestRenderer : public TestRendererBase {
14406246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    public:
14416246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
14426246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(0, mIndex++);
14436246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportWidth);
14446246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(100u, offscreenBuffer->viewportHeight);
14456246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), repaintRect);
14466246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14476246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void onColorOp(const ColorOp& op, const BakedOpState& state) override {
14486246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(1, mIndex++);
14496246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14506246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity())
14516246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik                    << "Transform should be reset within layer";
14526246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14536246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipRect())
14546246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik                    << "Damage rect should be used to clip layer content";
14556246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14566246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endLayer() override {
14576246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            EXPECT_EQ(2, mIndex++);
14586246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14596246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
14606246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
14616246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14626246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        void endFrame(const Rect& repaintRect) override {
14636246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            ADD_FAILURE() << "Primary frame draw not expected in this test";
14646246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        }
14656246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    };
14666246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
146706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(10, 10, 110, 110,
14686246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
14696246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik        props.mutateLayerProperties().setType(LayerType::RenderLayer);
1470260ab726486317496bc12a57d599ea96dcde3284Mike Reed        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
14716246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    });
14726246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    OffscreenBuffer** layerHandle = node->getLayerHandle();
14736246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14746246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // create RenderNode's layer here in same way prepareTree would
14756246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
14766246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    *layerHandle = &layer;
14776246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    TestUtils::syncHierarchyPropertiesAndDisplayList(node);
14796246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14806246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // only enqueue partial damage
14816246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
14826246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
14836246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14846246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // Draw, but pass empty node list, so no work is done for primary frame
14859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(layerUpdateQueue, sLightGeometry, Caches::getInstance());
14866246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    BuildLayerTestRenderer renderer;
14876246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
14886246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    EXPECT_EQ(3, renderer.getIndex());
14896246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
14906246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    // clean up layer pointer, so we can safely destruct RenderNode
14916246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik    *layerHandle = nullptr;
14926246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik}
14936246d27813f25b85f6e4b5cb1121fe8484bcce2dChris Craik
1494db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievnamespace {
1495db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
149606152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedRect(Canvas* canvas, uint8_t expectedDrawOrder) {
1497161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    SkPaint paint;
1498814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    // order put in blue channel, transparent so overlapped content doesn't get rejected
1499814ee6a9218aa339a4757b2c0ba1ad268f8dbc8aChris Craik    paint.setColor(SkColorSetARGB(1, 0, 0, expectedDrawOrder));
1500161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    canvas->drawRect(0, 0, 100, 100, paint);
1501161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}
150206152cdd06da50762716cd455dcf7ab0117f25b0Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder, float z) {
150306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
15048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [expectedDrawOrder](RenderProperties& props, RecordingCanvas& canvas) {
1505161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, expectedDrawOrder);
1506161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    });
1507161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    node->mutateStagingProperties().setTranslationZ(z);
1508161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z);
1509161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
1510161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik}
1511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
1512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievstatic void drawOrderedNode(Canvas* canvas, uint8_t expectedDrawOrder,
1513db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        std::function<void(RenderProperties& props, RecordingCanvas& canvas)> setup) {
1514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
1515db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [expectedDrawOrder, setup](RenderProperties& props, RecordingCanvas& canvas) {
1516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedRect(&canvas, expectedDrawOrder);
1517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        if (setup) {
1518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev             setup(props, canvas);
1519d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    });
1521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
1522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
1523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
1524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievclass ZReorderTestRenderer : public TestRendererBase {
1525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Ilievpublic:
1526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    void onRectOp(const RectOp& op, const BakedOpState& state) override {
1527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        int expectedOrder = SkColorGetB(op.paint->getColor()); // extract order from blue channel
1528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        EXPECT_EQ(expectedOrder, mIndex++) << "An op was drawn out of order";
1529db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }
1530db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev};
1531db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
1532db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev} // end anonymous namespace
1533d3daa3198e2212c985c634821682d5819346b653Chris Craik
153498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, zReorder) {
153506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
15368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1537347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev        canvas.insertReorderBarrier(true);
1538347691f8d87157be0eaeca26f4003d8a06a275e3Stan Iliev        canvas.insertReorderBarrier(false);
1539161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 0, 10.0f); // in reorder=false at this point, so played inorder
1540161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 1);
1541161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(true);
1542161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 6, 2.0f);
1543161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 3);
1544161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 4, 0.0f);
1545161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 5);
1546161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 2, -2.0f);
1547161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 7, 2.0f);
1548161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        canvas.insertReorderBarrier(false);
1549161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedRect(&canvas, 8);
1550161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
155188e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(true); //reorder a node ahead of drawrect op
155288e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        drawOrderedRect(&canvas, 11);
155388e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        drawOrderedNode(&canvas, 10, -1.0f);
155488e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(false);
155588e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(true); //test with two empty reorder sections
155688e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(true);
155788e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        canvas.insertReorderBarrier(false);
155888e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev        drawOrderedRect(&canvas, 12);
1559161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    });
15609cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
15619cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
15629cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
15639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1564161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    ZReorderTestRenderer renderer;
1565f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
156688e0891f6657573a5ad918c2d76d6c02bb8ceba3Stan Iliev    EXPECT_EQ(13, renderer.getIndex());
1567161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik};
1568161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
156998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionReorder) {
15708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    static const int scrollX = 5;
15718d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    static const int scrollY = 10;
15728d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    class ProjectionReorderTestRenderer : public TestRendererBase {
15738d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    public:
15748d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
15758d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            const int index = mIndex++;
15768d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
15778d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            Matrix4 expectedMatrix;
15788d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            switch (index) {
15798d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            case 0:
15808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(Rect(100, 100), op.unmappedBounds);
15818d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
15828d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                expectedMatrix.loadIdentity();
1583678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
15848d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                break;
15858d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            case 1:
15868d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(Rect(-10, -10, 60, 60), op.unmappedBounds);
15878d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(SK_ColorDKGRAY, op.paint->getColor());
1588678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                expectedMatrix.loadTranslate(50 - scrollX, 50 - scrollY, 0);
1589678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
1590678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                EXPECT_EQ(Rect(-35, -30, 45, 50),
1591678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                        Rect(state.computedState.localProjectionPathMask->getBounds()));
15928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                break;
15938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            case 2:
15948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(Rect(100, 50), op.unmappedBounds);
15958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                EXPECT_EQ(SK_ColorBLUE, op.paint->getColor());
15968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                expectedMatrix.loadTranslate(-scrollX, 50 - scrollY, 0);
1597678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                EXPECT_EQ(nullptr, state.computedState.localProjectionPathMask);
15988d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                break;
15998d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            default:
16008d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik                ADD_FAILURE();
16018d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            }
1602678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(expectedMatrix, state.computedState.transform);
16038d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        }
16048d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    };
16058d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16068d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    /**
16078d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Construct a tree of nodes, where the root (A) has a receiver background (B), and a child (C)
16088d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * with a projecting child (P) of its own. P would normally draw between B and C's "background"
16098d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * draw, but because it is projected backwards, it's drawn in between B and C.
16108d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     *
16118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * The parent is scrolled by scrollX/scrollY, but this does not affect the background
16128d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * (which isn't affected by scroll).
16138d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     */
161406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
16158d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
16168d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setProjectionReceiver(true);
16178d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // scroll doesn't apply to background, so undone via translationX/Y
16188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
16198d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setTranslationX(scrollX);
16208d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setTranslationY(scrollY);
16218d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16228d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
16238d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorWHITE);
16248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(0, 0, 100, 100, paint);
16258d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
162606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto projectingRipple = TestUtils::createNode<RecordingCanvas>(50, 0, 100, 50,
16278d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
16288d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setProjectBackwards(true);
16298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        properties.setClipToBounds(false);
16308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
16318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorDKGRAY);
16328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(-10, -10, 60, 60, paint);
16338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
163406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(0, 50, 100, 100,
16358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
16368d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        SkPaint paint;
16378d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        paint.setColor(SK_ColorBLUE);
16388d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRect(0, 0, 100, 50, paint);
16398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRenderNode(projectingRipple.get());
16408d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
164106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
16428d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
1643678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // Set a rect outline for the projecting ripple to be masked against.
1644678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.mutableOutline().setRoundRect(10, 10, 90, 90, 5, 1.0f);
1645678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1646eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
16478d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
16488d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRenderNode(receiverBackground.get());
16498d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.drawRenderNode(child.get());
16508d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        canvas.restore();
16518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    });
16528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
16539cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
16549cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
16559cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
16569cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
16578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    ProjectionReorderTestRenderer renderer;
1658f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
16598d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    EXPECT_EQ(3, renderer.getIndex());
16608d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik}
16618d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik
166298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionHwLayer) {
1663678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    static const int scrollX = 5;
1664678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    static const int scrollY = 10;
1665678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    class ProjectionHwLayerTestRenderer : public TestRendererBase {
1666678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    public:
1667678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
1668678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(0, mIndex++);
1669678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1670678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onArcOp(const ArcOp& op, const BakedOpState& state) override {
1671678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(1, mIndex++);
1672678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
1673678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1674678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void endLayer() override {
1675678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(2, mIndex++);
1676678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1677678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1678678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(3, mIndex++);
1679678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
1680678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1681678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
1682678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(4, mIndex++);
1683678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_NE(nullptr, state.computedState.localProjectionPathMask);
1684678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            Matrix4 expected;
1685678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            expected.loadTranslate(100 - scrollX, 100 - scrollY, 0);
1686678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(expected, state.computedState.transform);
1687678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(Rect(-85, -80, 295, 300),
1688678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik                    Rect(state.computedState.localProjectionPathMask->getBounds()));
1689678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1690678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
1691678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            EXPECT_EQ(5, mIndex++);
1692678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            ASSERT_EQ(nullptr, state.computedState.localProjectionPathMask);
1693678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        }
1694678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    };
169506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1696678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1697678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setProjectionReceiver(true);
1698678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // scroll doesn't apply to background, so undone via translationX/Y
1699678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
1700678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setTranslationX(scrollX);
1701678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setTranslationY(scrollY);
1702678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1703678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
1704678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
170506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1706678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1707678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setProjectBackwards(true);
1708678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.setClipToBounds(false);
1709678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawOval(100, 100, 300, 300, SkPaint()); // drawn mostly out of layer bounds
1710678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
171106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(100, 100, 300, 300,
1712678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
1713678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.mutateLayerProperties().setType(LayerType::RenderLayer);
1714678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRenderNode(projectingRipple.get());
1715678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawArc(0, 0, 200, 200, 0.0f, 280.0f, true, SkPaint());
1716678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
171706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1718678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
1719678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        // Set a rect outline for the projecting ripple to be masked against.
1720678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        properties.mutableOutline().setRoundRect(10, 10, 390, 390, 0, 1.0f);
1721678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
1722678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRenderNode(receiverBackground.get());
1723678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik        canvas.drawRenderNode(child.get());
1724678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    });
1725678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1726678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    OffscreenBuffer** layerHandle = child->getLayerHandle();
1727678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1728678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    // create RenderNode's layer here in same way prepareTree would, setting windowTransform
1729678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 200, 200);
1730678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    Matrix4 windowTransform;
1731678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    windowTransform.loadTranslate(100, 100, 0); // total transform of layer's origin
1732678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    layer.setWindowTransform(windowTransform);
1733678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    *layerHandle = &layer;
1734678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
17359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(parent);
17369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1737678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
1738678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
17399cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
17409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
17419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
17429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
17439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
17449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1745678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    ProjectionHwLayerTestRenderer renderer;
1746678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1747678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    EXPECT_EQ(6, renderer.getIndex());
1748678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
1749678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    // clean up layer pointer, so we can safely destruct RenderNode
1750678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik    *layerHandle = nullptr;
1751678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik}
1752678ff81105753656aa4822f4f675ef96dc9d2b83Chris Craik
175398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, projectionChildScroll) {
1754a748c08241e43fc68c7c34767d819aef5183936eChris Craik    static const int scrollX = 500000;
1755a748c08241e43fc68c7c34767d819aef5183936eChris Craik    static const int scrollY = 0;
1756a748c08241e43fc68c7c34767d819aef5183936eChris Craik    class ProjectionChildScrollTestRenderer : public TestRendererBase {
1757a748c08241e43fc68c7c34767d819aef5183936eChris Craik    public:
1758a748c08241e43fc68c7c34767d819aef5183936eChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1759a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_EQ(0, mIndex++);
1760a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1761a748c08241e43fc68c7c34767d819aef5183936eChris Craik        }
1762a748c08241e43fc68c7c34767d819aef5183936eChris Craik        void onOvalOp(const OvalOp& op, const BakedOpState& state) override {
1763a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_EQ(1, mIndex++);
1764a748c08241e43fc68c7c34767d819aef5183936eChris Craik            ASSERT_NE(nullptr, state.computedState.clipState);
1765a748c08241e43fc68c7c34767d819aef5183936eChris Craik            ASSERT_EQ(ClipMode::Rectangle, state.computedState.clipState->mode);
1766a748c08241e43fc68c7c34767d819aef5183936eChris Craik            ASSERT_EQ(Rect(400, 400), state.computedState.clipState->rect);
1767a748c08241e43fc68c7c34767d819aef5183936eChris Craik            EXPECT_TRUE(state.computedState.transform.isIdentity());
1768a748c08241e43fc68c7c34767d819aef5183936eChris Craik        }
1769a748c08241e43fc68c7c34767d819aef5183936eChris Craik    };
177006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto receiverBackground = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1771a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1772a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setProjectionReceiver(true);
1773a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRect(0, 0, 400, 400, SkPaint());
1774a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
177506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto projectingRipple = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
1776a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [](RenderProperties& properties, RecordingCanvas& canvas) {
1777a748c08241e43fc68c7c34767d819aef5183936eChris Craik        // scroll doesn't apply to background, so undone via translationX/Y
1778a748c08241e43fc68c7c34767d819aef5183936eChris Craik        // NOTE: translationX/Y only! no other transform properties may be set for a proj receiver!
1779a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setTranslationX(scrollX);
1780a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setTranslationY(scrollY);
1781a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setProjectBackwards(true);
1782a748c08241e43fc68c7c34767d819aef5183936eChris Craik        properties.setClipToBounds(false);
1783a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawOval(0, 0, 200, 200, SkPaint());
1784a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
178506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto child = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1786a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [&projectingRipple](RenderProperties& properties, RecordingCanvas& canvas) {
1787a748c08241e43fc68c7c34767d819aef5183936eChris Craik        // Record time clip will be ignored by projectee
17886c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(100, 100, 300, 300, SkClipOp::kIntersect);
1789a748c08241e43fc68c7c34767d819aef5183936eChris Craik
1790a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.translate(-scrollX, -scrollY); // Apply scroll (note: bg undoes this internally)
1791a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRenderNode(projectingRipple.get());
1792a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
179306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 400, 400,
1794a748c08241e43fc68c7c34767d819aef5183936eChris Craik            [&receiverBackground, &child](RenderProperties& properties, RecordingCanvas& canvas) {
1795a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRenderNode(receiverBackground.get());
1796a748c08241e43fc68c7c34767d819aef5183936eChris Craik        canvas.drawRenderNode(child.get());
1797a748c08241e43fc68c7c34767d819aef5183936eChris Craik    });
1798a748c08241e43fc68c7c34767d819aef5183936eChris Craik
17999cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(400, 400), 400, 400,
18009cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
18019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
18029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
1803a748c08241e43fc68c7c34767d819aef5183936eChris Craik    ProjectionChildScrollTestRenderer renderer;
1804a748c08241e43fc68c7c34767d819aef5183936eChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
1805a748c08241e43fc68c7c34767d819aef5183936eChris Craik    EXPECT_EQ(2, renderer.getIndex());
1806a748c08241e43fc68c7c34767d819aef5183936eChris Craik}
1807a748c08241e43fc68c7c34767d819aef5183936eChris Craik
180898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik// creates a 100x100 shadow casting node with provided translationZ
180998787e6c9b2c10b1ab7820bdac168686025b924aChris Craikstatic sp<RenderNode> createWhiteRectShadowCaster(float translationZ) {
181006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    return TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
18118d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [translationZ](RenderProperties& properties, RecordingCanvas& canvas) {
181216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        properties.setTranslationZ(translationZ);
181316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        properties.mutableOutline().setRoundRect(0, 0, 100, 100, 0.0f, 1.0f);
181498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        SkPaint paint;
181598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        paint.setColor(SK_ColorWHITE);
181698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
181798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    });
181898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
181998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
182098c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadow) {
1821d3daa3198e2212c985c634821682d5819346b653Chris Craik    class ShadowTestRenderer : public TestRendererBase {
1822d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
1823d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
1824d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(0, mIndex++);
182598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_FLOAT_EQ(1.0f, op.casterAlpha);
18266e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_TRUE(op.shadowTask->casterPerimeter.isRect(nullptr));
18276e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), op.shadowTask->transformXY);
182898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
182998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            Matrix4 expectedZ;
183098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            expectedZ.loadTranslate(0, 0, 5);
18316e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_MATRIX_APPROX_EQ(expectedZ, op.shadowTask->transformZ);
1832d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1833d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1834d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(1, mIndex++);
1835d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
1836d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
1837161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
183806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
18398d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
184098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(true);
184198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
1842d3daa3198e2212c985c634821682d5819346b653Chris Craik    });
184398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
18449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
18459cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
18469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
18479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
184898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowTestRenderer renderer;
1849f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
185098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    EXPECT_EQ(2, renderer.getIndex());
185198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
185298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
185398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowSaveLayer) {
185498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class ShadowSaveLayerTestRenderer : public TestRendererBase {
185598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public:
185698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
185798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(0, mIndex++);
185898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            return nullptr;
185998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
186098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
186198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(1, mIndex++);
18626e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
18636e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
186498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
186598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
186698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(2, mIndex++);
186798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
186898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void endLayer() override {
186998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(3, mIndex++);
187098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
187198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
187298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(4, mIndex++);
187398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
187474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
187574af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(5, mIndex++);
187674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
187798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    };
187898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
187906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
18808d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
188198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        // save/restore outside of reorderBarrier, so they don't get moved out of place
188298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.translate(20, 10);
1883eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        int count = canvas.saveLayerAlpha(30, 50, 130, 150, 128, SaveFlags::ClipToLayer);
1884d3daa3198e2212c985c634821682d5819346b653Chris Craik        canvas.insertReorderBarrier(true);
188598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
188698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(false);
188798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.restoreToCount(count);
1888d3daa3198e2212c985c634821682d5819346b653Chris Craik    });
1889d3daa3198e2212c985c634821682d5819346b653Chris Craik
18909cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
18913a5811b50157e7ba50854caf957e806aee794d39Chris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
18929cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
18939cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
189498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowSaveLayerTestRenderer renderer;
1895f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
189674af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    EXPECT_EQ(6, renderer.getIndex());
189798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
1898d3daa3198e2212c985c634821682d5819346b653Chris Craik
189998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowHwLayer) {
190098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class ShadowHwLayerTestRenderer : public TestRendererBase {
190198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public:
190298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void startRepaintLayer(OffscreenBuffer* offscreenBuffer, const Rect& repaintRect) override {
190398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(0, mIndex++);
190498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
190598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
190698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(1, mIndex++);
19076e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(50, op.shadowTask->lightCenter.x);
19086e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(40, op.shadowTask->lightCenter.y);
19096e068c0182f6f85bccb855a647510724d1c65a13Chris Craik            EXPECT_FLOAT_EQ(30, op.shadowTask->lightRadius);
191098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
191198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
191298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(2, mIndex++);
191398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
191498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void endLayer() override {
191598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(3, mIndex++);
191698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
191798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
191898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_EQ(4, mIndex++);
191998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
192098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    };
1921d3daa3198e2212c985c634821682d5819346b653Chris Craik
192206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(50, 60, 150, 160,
192316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [](RenderProperties& props, RecordingCanvas& canvas) {
192416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.mutateLayerProperties().setType(LayerType::RenderLayer);
192598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(true);
1926eecff56fed5dd5206acfbc5007b4912081b36d3bFlorin Malita        canvas.save(SaveFlags::MatrixClip);
192798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.translate(20, 10);
192898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
192998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.restore();
193016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
193198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer** layerHandle = parent->getLayerHandle();
193298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
193398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    // create RenderNode's layer here in same way prepareTree would, setting windowTransform
193498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    OffscreenBuffer layer(renderThread.renderState(), Caches::getInstance(), 100, 100);
193598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    Matrix4 windowTransform;
193698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    windowTransform.loadTranslate(50, 60, 0); // total transform of layer's origin
193798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    layer.setWindowTransform(windowTransform);
193898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = &layer;
193998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
19409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(parent);
194198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
194298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
19439cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
19449cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
19453a5811b50157e7ba50854caf957e806aee794d39Chris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance());
19469cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferLayers(layerUpdateQueue);
19479cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
19489cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
194998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowHwLayerTestRenderer renderer;
1950f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
195198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    EXPECT_EQ(5, renderer.getIndex());
195298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
195398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    // clean up layer pointer, so we can safely destruct RenderNode
195498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    *layerHandle = nullptr;
1955d3daa3198e2212c985c634821682d5819346b653Chris Craik}
195676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
195798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowLayering) {
195898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class ShadowLayeringTestRenderer : public TestRendererBase {
195998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public:
196098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
196198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            int index = mIndex++;
196298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_TRUE(index == 0 || index == 1);
196398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
196498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
196598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            int index = mIndex++;
196698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik            EXPECT_TRUE(index == 2 || index == 3);
196798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        }
196898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    };
196906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 200, 200,
19708d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
197198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.insertReorderBarrier(true);
197298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
197398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0001f).get());
197498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    });
19759cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
19763a5811b50157e7ba50854caf957e806aee794d39Chris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
19779cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
19789cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
197998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    ShadowLayeringTestRenderer renderer;
1980f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
198198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    EXPECT_EQ(4, renderer.getIndex());
198298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik}
198398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
198498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, shadowClipping) {
1985d645640180c25c2711e99aa82ec629155f8e91baChris Craik    class ShadowClippingTestRenderer : public TestRendererBase {
1986d645640180c25c2711e99aa82ec629155f8e91baChris Craik    public:
1987d645640180c25c2711e99aa82ec629155f8e91baChris Craik        void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
1988d645640180c25c2711e99aa82ec629155f8e91baChris Craik            EXPECT_EQ(0, mIndex++);
1989d645640180c25c2711e99aa82ec629155f8e91baChris Craik            EXPECT_EQ(Rect(25, 25, 75, 75), state.computedState.clipState->rect)
1990d645640180c25c2711e99aa82ec629155f8e91baChris Craik                    << "Shadow must respect pre-barrier canvas clip value.";
1991d645640180c25c2711e99aa82ec629155f8e91baChris Craik        }
1992d645640180c25c2711e99aa82ec629155f8e91baChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
1993d645640180c25c2711e99aa82ec629155f8e91baChris Craik            EXPECT_EQ(1, mIndex++);
1994d645640180c25c2711e99aa82ec629155f8e91baChris Craik        }
1995d645640180c25c2711e99aa82ec629155f8e91baChris Craik    };
199606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto parent = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
1997d645640180c25c2711e99aa82ec629155f8e91baChris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
1998d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // Apply a clip before the reorder barrier/shadow casting child is drawn.
1999d645640180c25c2711e99aa82ec629155f8e91baChris Craik        // This clip must be applied to the shadow cast by the child.
20006c67f1d04591f44bccb476d715a005ad5bbdf840Mike Reed        canvas.clipRect(25, 25, 75, 75, SkClipOp::kIntersect);
2001d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.insertReorderBarrier(true);
2002d645640180c25c2711e99aa82ec629155f8e91baChris Craik        canvas.drawRenderNode(createWhiteRectShadowCaster(5.0f).get());
2003d645640180c25c2711e99aa82ec629155f8e91baChris Craik    });
2004d645640180c25c2711e99aa82ec629155f8e91baChris Craik
20059cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2006d645640180c25c2711e99aa82ec629155f8e91baChris Craik            (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
20079cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(parent));
20089cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
2009d645640180c25c2711e99aa82ec629155f8e91baChris Craik    ShadowClippingTestRenderer renderer;
2010d645640180c25c2711e99aa82ec629155f8e91baChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2011d645640180c25c2711e99aa82ec629155f8e91baChris Craik    EXPECT_EQ(2, renderer.getIndex());
2012d645640180c25c2711e99aa82ec629155f8e91baChris Craik}
2013d645640180c25c2711e99aa82ec629155f8e91baChris Craik
201416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reckstatic void testProperty(std::function<void(RenderProperties&)> propSetupCallback,
201576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        std::function<void(const RectOp&, const BakedOpState&)> opValidateCallback) {
2016d3daa3198e2212c985c634821682d5819346b653Chris Craik    class PropertyTestRenderer : public TestRendererBase {
2017d3daa3198e2212c985c634821682d5819346b653Chris Craik    public:
2018d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh        explicit PropertyTestRenderer(std::function<void(const RectOp&, const BakedOpState&)> callback)
2019d3daa3198e2212c985c634821682d5819346b653Chris Craik                : mCallback(callback) {}
2020d3daa3198e2212c985c634821682d5819346b653Chris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
2021d3daa3198e2212c985c634821682d5819346b653Chris Craik            EXPECT_EQ(mIndex++, 0);
2022d3daa3198e2212c985c634821682d5819346b653Chris Craik            mCallback(op, state);
2023d3daa3198e2212c985c634821682d5819346b653Chris Craik        }
2024d3daa3198e2212c985c634821682d5819346b653Chris Craik        std::function<void(const RectOp&, const BakedOpState&)> mCallback;
2025d3daa3198e2212c985c634821682d5819346b653Chris Craik    };
2026d3daa3198e2212c985c634821682d5819346b653Chris Craik
202706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
202816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [propSetupCallback](RenderProperties& props, RecordingCanvas& canvas) {
202916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        propSetupCallback(props);
203076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        SkPaint paint;
203176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        paint.setColor(SK_ColorWHITE);
203276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        canvas.drawRect(0, 0, 100, 100, paint);
203316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    });
203476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
20359cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 200, 200,
20369cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
20379cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
20389cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
203976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    PropertyTestRenderer renderer(opValidateCallback);
2040f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
204176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
204276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
204376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
204498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
204576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
204676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setAlpha(0.5f);
204776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setHasOverlappingRendering(false);
204876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
204976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(0.5f, state.alpha) << "Alpha should be applied directly to op";
205076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
205176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
205276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
205398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropClipping) {
205476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
205576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setClipToBounds(true);
205676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setClipBounds(Rect(10, 20, 300, 400));
205776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
205876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(Rect(10, 20, 100, 100), state.computedState.clippedBounds)
205976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik                << "Clip rect should be intersection of node bounds and clip bounds";
206076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
206176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
206276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
206398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropRevealClip) {
206476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
206576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.mutableRevealClip().set(true, 50, 50, 25);
206676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
206776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        ASSERT_NE(nullptr, state.roundRectClipState);
206876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_TRUE(state.roundRectClipState->highPriority);
206976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(25, state.roundRectClipState->radius);
207076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(Rect(50, 50, 50, 50), state.roundRectClipState->innerRect);
207176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
207276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
207376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
207498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropOutlineClip) {
207576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
207676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.mutableOutline().setShouldClip(true);
207776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
207876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
207976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        ASSERT_NE(nullptr, state.roundRectClipState);
208076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_FALSE(state.roundRectClipState->highPriority);
208176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(5, state.roundRectClipState->radius);
208276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_EQ(Rect(15, 25, 25, 35), state.roundRectClipState->innerRect);
208376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
208476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
208576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
208698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropTransform) {
208776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    testProperty([](RenderProperties& properties) {
208876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setLeftTopRightBottom(10, 10, 110, 110);
208976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
209076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        SkMatrix staticMatrix = SkMatrix::MakeScale(1.2f, 1.2f);
209176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setStaticMatrix(&staticMatrix);
209276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
209376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // ignored, since static overrides animation
209476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        SkMatrix animationMatrix = SkMatrix::MakeTrans(15, 15);
209576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setAnimationMatrix(&animationMatrix);
209676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
209776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setTranslationX(10);
209876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setTranslationY(20);
209976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setScaleX(0.5f);
210076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        properties.setScaleY(0.7f);
210176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    }, [](const RectOp& op, const BakedOpState& state) {
210276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        Matrix4 matrix;
210376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.loadTranslate(10, 10, 0); // left, top
210476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.scale(1.2f, 1.2f, 1); // static matrix
210576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // ignore animation matrix, since static overrides it
210676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
210776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // translation xy
210876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.translate(10, 20);
210976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
211076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // scale xy (from default pivot - center)
211176caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.translate(50, 50);
211276caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.scale(0.5f, 0.7f, 1);
211376caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        matrix.translate(-50, -50);
211476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        EXPECT_MATRIX_APPROX_EQ(matrix, state.computedState.transform)
211576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik                << "Op draw matrix must match expected combination of transformation properties";
211676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik    });
211776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik}
2118161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
21198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikstruct SaveLayerAlphaData {
21208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    uint32_t layerWidth = 0;
21218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    uint32_t layerHeight = 0;
21228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    Rect rectClippedBounds;
21238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    Matrix4 rectMatrix;
2124c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck    Matrix4 drawLayerMatrix;
21258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik};
21268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik/**
21278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Constructs a view to hit the temporary layer alpha property implementation:
21288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *     a) 0 < alpha < 1
21298ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *     b) too big for layer (larger than maxTextureSize)
21308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *     c) overlapping rendering content
21318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * returning observed data about layer size and content clip/transform.
21328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik *
21338ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * Used to validate clipping behavior of temporary layer, where requested layer size is reduced
21348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik * (for efficiency, and to fit in layer size constraints) based on parent clip.
21358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik */
21368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craikvoid testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
213716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        std::function<void(RenderProperties&)> propSetupCallback) {
21388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    class SaveLayerAlphaClipTestRenderer : public TestRendererBase {
21398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    public:
2140d53e3bed1ca4a14b2a86d53eaef6969bd043176eChih-Hung Hsieh        explicit SaveLayerAlphaClipTestRenderer(SaveLayerAlphaData* outData)
21418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik                : mOutData(outData) {}
21428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21438ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
21448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(0, mIndex++);
21458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->layerWidth = width;
21468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->layerHeight = height;
21478ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            return nullptr;
21488ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
21498ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        void onRectOp(const RectOp& op, const BakedOpState& state) override {
21508ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(1, mIndex++);
21518ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21528ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->rectClippedBounds = state.computedState.clippedBounds;
21538ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            mOutData->rectMatrix = state.computedState.transform;
21548ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
21558ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        void endLayer() override {
21568ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(2, mIndex++);
21578ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
21588ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
21598ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            EXPECT_EQ(3, mIndex++);
2160c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck            mOutData->drawLayerMatrix = state.computedState.transform;
21618ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        }
216274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
216374af6e282f8a8f75928a071e8200039517cf5c12Chris Craik            EXPECT_EQ(4, mIndex++);
216474af6e282f8a8f75928a071e8200039517cf5c12Chris Craik        }
21658ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    private:
21668ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        SaveLayerAlphaData* mOutData;
21678ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    };
21688ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21698ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    ASSERT_GT(10000, DeviceInfo::get()->maxTextureSize())
21708ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            << "Node must be bigger than max texture size to exercise saveLayer codepath";
217106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(0, 0, 10000, 10000,
217216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            [&propSetupCallback](RenderProperties& properties, RecordingCanvas& canvas) {
21738ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setHasOverlappingRendering(true);
21748ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setAlpha(0.5f); // force saveLayer, since too big for HW layer
21758ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        // apply other properties
217616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        propSetupCallback(properties);
217716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
217816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        SkPaint paint;
217916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        paint.setColor(SK_ColorWHITE);
218016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        canvas.drawRect(0, 0, 10000, 10000, paint);
21818ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
21829cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    auto syncedNode = TestUtils::getSyncedNode(node); // sync before querying height
21839cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
21849cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeWH(200, 200), 200, 200,
21859cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik                sLightGeometry, Caches::getInstance());
21869cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*syncedNode);
21878ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21888ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaClipTestRenderer renderer(outObservedData);
2189f158b49c888f722194afe5a80539a2b020c130bcChris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
21908ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
21918ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    // assert, since output won't be valid if we haven't seen a save layer triggered
219274af6e282f8a8f75928a071e8200039517cf5c12Chris Craik    ASSERT_EQ(5, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
21938ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
21948ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
219598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
21968ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaData observedData;
21978ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
21988ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationX(10); // offset rendering content
21998ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationY(-2000); // offset rendering content
22008ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22018ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(190u, observedData.layerWidth);
22028ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(200u, observedData.layerHeight);
22035430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(190, 200), observedData.rectClippedBounds)
22048ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            << "expect content to be clipped to screen area";
22058ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    Matrix4 expected;
22068ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    expected.loadTranslate(0, -2000, 0);
22078ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
22088ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik            << "expect content to be translated as part of being clipped";
2209c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck    expected.loadTranslate(10, 0, 0);
2210c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck    EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
2211c9bb1a38d356087a4e5578307a6839eac0a1e6eeJohn Reck                << "expect drawLayer to be translated as part of being clipped";
22128ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22138ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
221498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
22158ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaData observedData;
22168ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
22178ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        // Translate and rotate the view so that the only visible part is the top left corner of
22188d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik        // the view. It will form an isosceles right triangle with a long side length of 200 at the
22198ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        // bottom of the viewport.
22208ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationX(100);
22218ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setTranslationY(100);
22228ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotX(0);
22238ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotY(0);
22248ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setRotation(45);
22258ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22268ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    // ceil(sqrt(2) / 2 * 200) = 142
22278ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(142u, observedData.layerWidth);
22288ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(142u, observedData.layerHeight);
22295430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(142, 142), observedData.rectClippedBounds);
22308ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
22318ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22328ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
223398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) {
22348ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    SaveLayerAlphaData observedData;
22358ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
22368ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotX(0);
22378ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setPivotY(0);
22388ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setScaleX(2);
22398ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik        properties.setScaleY(0.5f);
22408ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    });
22418ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(100u, observedData.layerWidth);
22428ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_EQ(400u, observedData.layerHeight);
22435430ab220b231a96b71c3e030d0303d9ce008b05Chris Craik    EXPECT_EQ(Rect(100, 400), observedData.rectClippedBounds);
22448ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik    EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
22458ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik}
22468ecf41c61a5185207a21d64681e8ebc2502b7b2aChris Craik
224798c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielRENDERTHREAD_OPENGL_PIPELINE_TEST(FrameBuilder, clip_replace) {
224804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    class ClipReplaceTestRenderer : public TestRendererBase {
224904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    public:
225004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        void onColorOp(const ColorOp& op, const BakedOpState& state) override {
225104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            EXPECT_EQ(0, mIndex++);
225204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            EXPECT_TRUE(op.localClip->intersectWithRoot);
225304d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            EXPECT_EQ(Rect(20, 10, 30, 40), state.computedState.clipState->rect)
225404d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik                    << "Expect resolved clip to be intersection of viewport clip and clip op";
225504d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik        }
225604d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    };
225706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    auto node = TestUtils::createNode<RecordingCanvas>(20, 20, 30, 30,
225804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik            [](RenderProperties& props, RecordingCanvas& canvas) {
225966b9d4486abb9e6d1edc624cd9ff522b12acece0Chris Craik        canvas.clipRect(0, -20, 10, 30, SkClipOp::kReplace);
2260260ab726486317496bc12a57d599ea96dcde3284Mike Reed        canvas.drawColor(SK_ColorWHITE, SkBlendMode::kSrcOver);
226104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    });
226204d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
22639cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    FrameBuilder frameBuilder(SkRect::MakeLTRB(10, 10, 40, 40), 50, 50,
22649cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik            sLightGeometry, Caches::getInstance());
22659cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(node));
22669cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik
226704d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    ClipReplaceTestRenderer renderer;
226804d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
226904d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik    EXPECT_EQ(1, renderer.getIndex());
227004d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik}
227104d46eb69fb4f4c4c332c36c6ae845da3b2ae848Chris Craik
227298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedInMiddle) {
2273db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on B
2274db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2275db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2276db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2277db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2278db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2279db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2280db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2281db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2282db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
2283db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2284db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2285db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2286db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2287db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2288db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2289db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2290db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2291db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2292db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2293db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2294db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2295db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2296db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2297db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2298db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2299db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2300db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2301db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
230298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectLast) {
2303db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on E
2304db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  A
2305db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                / | \
2306db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               /  |  \
2307db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C   E
2308db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2309db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2310db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2311db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2312db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2313db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0,  nullptr); //nodeB
2314db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2315db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 2
2316db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2317db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2318db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2319db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2320db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //drawn as 3
2321db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2322db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeE
2323db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2324db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2325db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2326db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2327db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2328db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2329db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2330db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2331db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(4, renderer.getIndex());
2332db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2333db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
233498c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderNoReceivable) {
2335db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected without receiver
2336db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2337db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2338db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2339db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2340db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2341db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2342db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2343db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2344db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, nullptr); //nodeB
2345db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2346db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 255,  [](RenderProperties& props, RecordingCanvas& canvas) {
2347db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                //not having a projection receiver is an undefined behavior
2348db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2349db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2350db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2351db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2352db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2353db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2354db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2355db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2356db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2357db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2358db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2359db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2360db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(2, renderer.getIndex());
2361db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2362db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
236398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderParentReceivable) {
2364db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on C
2365db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2366db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2367db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2368db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  |
2369db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                  R
2370db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2371db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2372db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2373db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, nullptr); //nodeB
2374db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2375db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2376db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2377db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2378db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2379db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2380db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2381db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2382db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2383db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2384db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2385db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2386db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2387db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2388db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2389db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2390db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2391db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
239298c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderSameNodeReceivable) {
2393db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev     auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2394db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2395db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, nullptr); //nodeB
2396db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2397db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) {
2398db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                //having a node that is projected on itself is an undefined/unexpected behavior
2399db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2400db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2401db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2402db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2403db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2404db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2405db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2406db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2407db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2408db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2409db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2410db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2411db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2412db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(2, renderer.getIndex());
2413db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2414db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
241598c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling) {
2416db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    //TODO: this test together with the next "projectionReorderProjectedSibling2" likely expose a
2417db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    //bug in HWUI. First test draws R, while the second test does not draw R for a nearly identical
2418db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    //tree setup. The correct behaviour is to not draw R, because the receiver cannot be a sibling
2419db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on B. R is not expected to be drawn (see Sibling2 outcome below),
2420db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev       but for some reason it is drawn.
2421db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2422db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               /|\
2423db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              / | \
2424db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev             B  C  R
2425db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2426db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2427db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2428db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
2429db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2430db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2431db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2432db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2433db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2434db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectBackwards(true);
2435db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setClipToBounds(false);
2436db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeR
2437db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2438db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2439db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2440db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2441db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2442db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2443db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2444db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2445db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2446db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2447db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
244898c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderProjectedSibling2) {
2449db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is set to project on B, but R is not drawn because projecting on a sibling is not allowed.
2450db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2451db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2452db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G
2453db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               /|\
2454db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              / | \
2455db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev             B  C  R
2456db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2457db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2458db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2459db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2460db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2461db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2462db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeB
2463db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2464db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeC
2465db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 255, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2466db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2467db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2468db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2469db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeG
2470db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2471db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2472db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2473db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2474db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2475db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2476db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2477db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2478db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2479db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2480db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
248198c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderGrandparentReceivable) {
2482db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* R is backward projected on B
2483db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2484db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2485db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                B
2486db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2487db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                C
2488db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                |
2489db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                R
2490db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2491db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2492db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2493db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) {
2494db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2495db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) {
2496db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) {
2497db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setProjectBackwards(true);
2498db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setClipToBounds(false);
2499db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                } ); //nodeR
2500db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeC
2501db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2502db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2503db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2504db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2505db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2506db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2507db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2508db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2509db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2510db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(3, renderer.getIndex());
2511db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2512db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
251398c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivables) {
2514db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* B and G are receivables, R is backward projected
2515db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2516db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2517db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2518db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                 / \
2519db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G   R
2520db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2521db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2522db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2523db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2524db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2525db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2526db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2527db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2528db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2529db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeG
2530db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2531db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2532db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2533db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2534db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2535db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2536db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2537db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2538db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2539db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2540db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2541db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2542db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2543db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(4, renderer.getIndex());
2544db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2545db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
254698c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesLikelyScenario) {
2547db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* B and G are receivables, G is backward projected
2548db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2549db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2550db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2551db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                 / \
2552db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G   R
2553db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2554db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2555db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2556db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2557db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2558db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2559db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2560db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2561db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2562db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectBackwards(true);
2563db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setClipToBounds(false);
2564db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeG
2565db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2566db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeR
2567db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2568db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2569db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2570db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2571db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2572db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2573db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2574db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2575db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2576db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(4, renderer.getIndex());
2577db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2578db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
257998c78dad1969e2321cfee2085faa55d95bba7e29Greg DanielOPENGL_PIPELINE_TEST(FrameBuilder, projectionReorderTwoReceivablesDeeper) {
2580db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    /* B and G are receivables, R is backward projected
2581db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                A
2582db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev               / \
2583db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev              B   C
2584db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                 / \
2585db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                G   D
2586db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    |
2587db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    R
2588db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    */
2589db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    auto nodeA = TestUtils::createNode<RecordingCanvas>(0, 0, 100, 100,
2590db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            [](RenderProperties& props, RecordingCanvas& canvas) {
2591db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 0, [](RenderProperties& props, RecordingCanvas& canvas) { //B
2592db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            props.setProjectionReceiver(true);
2593db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeB
2594db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        drawOrderedNode(&canvas, 1, [](RenderProperties& props, RecordingCanvas& canvas) { //C
2595db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 2, [](RenderProperties& props, RecordingCanvas& canvas) { //G
2596db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                props.setProjectionReceiver(true);
2597db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeG
2598db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            drawOrderedNode(&canvas, 4, [](RenderProperties& props, RecordingCanvas& canvas) { //D
2599db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                drawOrderedNode(&canvas, 3, [](RenderProperties& props, RecordingCanvas& canvas) { //R
2600db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setProjectBackwards(true);
2601db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                    props.setClipToBounds(false);
2602db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev                } ); //nodeR
2603db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            } ); //nodeD
2604db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev        } ); //nodeC
2605db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    }); //nodeA
2606db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2607db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    FrameBuilder frameBuilder(SkRect::MakeWH(100, 100), 100, 100,
2608db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev            sLightGeometry, Caches::getInstance());
2609db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.deferRenderNode(*TestUtils::getSyncedNode(nodeA));
2610db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
2611db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    ZReorderTestRenderer renderer;
2612db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    frameBuilder.replayBakedOps<TestDispatcher>(renderer);
2613db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev    EXPECT_EQ(5, renderer.getIndex());
2614db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev}
2615db45a4bfaff1120a9b23073e46a0cc6d39f56023Stan Iliev
26166fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace uirenderer
26176fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik} // namespace android
2618