1b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik/*
2b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik * Copyright (C) 2015 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 */
165e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik
175e00c7ce063116c11315639f0035aca8ad73e8ccChris Craik#pragma once
18b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
1976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik#include <DeviceInfo.h>
20161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <DisplayList.h>
21b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <Matrix.h>
2298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#include <Properties.h>
230a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <Rect.h>
24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RenderNode.h>
251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <Snapshot.h>
26c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h>
27500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <pipeline/skia/SkiaRecordingCanvas.h>
280a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderstate/RenderState.h>
290a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderthread/RenderThread.h>
30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
31161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <RecordedOp.h>
3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <RecordingCanvas.h>
33161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <memory>
35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android {
37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer {
38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define EXPECT_MATRIX_APPROX_EQ(a, b) EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define EXPECT_RECT_APPROX_EQ(a, b)                          \
421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    EXPECT_TRUE(MathUtils::areEqual((a).left, (b).left) &&   \
431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                MathUtils::areEqual((a).top, (b).top) &&     \
441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                MathUtils::areEqual((a).right, (b).right) && \
451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                MathUtils::areEqual((a).bottom, (b).bottom));
461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define EXPECT_CLIP_RECT(expRect, clipStatePtr)                                      \
481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped";                         \
491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    if ((clipStatePtr)->mode == ClipMode::Rectangle) {                               \
501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \
511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    } else {                                                                         \
521bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        ADD_FAILURE() << "ClipState not a rect";                                     \
531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    }
5498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
5598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#define INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, functionCall) \
561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    TEST(test_case_name, test_name##_##pipeline) {                             \
571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        RenderPipelineType oldType = Properties::getRenderPipelineType();      \
581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        Properties::overrideRenderPipelineType(RenderPipelineType::pipeline);  \
591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        functionCall;                                                          \
601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        Properties::overrideRenderPipelineType(oldType);                       \
6198c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel    };
6298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
6398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel/**
6498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel * Like gtests' TEST, but only runs with the OpenGL RenderPipelineType
6598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel */
661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define OPENGL_PIPELINE_TEST(test_case_name, test_name)                        \
671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    class test_case_name##_##test_name##_HwuiTest {                            \
681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    public:                                                                    \
691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        static void doTheThing();                                              \
701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    };                                                                         \
711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    INNER_PIPELINE_TEST(test_case_name, test_name, OpenGL,                     \
721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        test_case_name##_##test_name##_HwuiTest::doTheThing()) \
7398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel    void test_case_name##_##test_name##_HwuiTest::doTheThing()
7498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
7598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#define INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, pipeline) \
761bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    INNER_PIPELINE_TEST(test_case_name, test_name, pipeline,                  \
771bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                        TestUtils::runOnRenderThread(                         \
781bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                test_case_name##_##test_name##_RenderThreadTest::doTheThing))
7998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
8098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik/**
8198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope
8298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * (for e.g. accessing its RenderState)
8398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik */
841bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDERTHREAD_TEST(test_case_name, test_name)                                        \
851bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    class test_case_name##_##test_name##_RenderThreadTest {                                 \
861bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    public:                                                                                 \
871bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        static void doTheThing(renderthread::RenderThread& renderThread);                   \
881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    };                                                                                      \
891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL);                    \
901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL);                    \
910f89539de6df6ebe991ae29510e55867317389c0Derek Sollenberger    /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */          \
931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void test_case_name##_##test_name##_RenderThreadTest::doTheThing(                       \
941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            renderthread::RenderThread& renderThread)
9598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
9698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel/**
9798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel * Like RENDERTHREAD_TEST, but only runs with the OpenGL RenderPipelineType
9898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel */
991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDERTHREAD_OPENGL_PIPELINE_TEST(test_case_name, test_name)      \
1001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    class test_case_name##_##test_name##_RenderThreadTest {               \
1011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    public:                                                               \
10298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel        static void doTheThing(renderthread::RenderThread& renderThread); \
1031bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    };                                                                    \
1041bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL);  \
1051bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void test_case_name##_##test_name##_RenderThreadTest::doTheThing(     \
1061bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            renderthread::RenderThread& renderThread)
10798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
10898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel/**
10998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel * Like RENDERTHREAD_TEST, but only runs with the Skia RenderPipelineTypes
11098c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel */
1111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDERTHREAD_SKIA_PIPELINE_TEST(test_case_name, test_name)                          \
1121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    class test_case_name##_##test_name##_RenderThreadTest {                                 \
1131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    public:                                                                                 \
1141bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        static void doTheThing(renderthread::RenderThread& renderThread);                   \
1151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    };                                                                                      \
1161bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL);                    \
1170f89539de6df6ebe991ae29510e55867317389c0Derek Sollenberger    /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \
1181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */          \
1191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    void test_case_name##_##test_name##_RenderThreadTest::doTheThing(                       \
1201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            renderthread::RenderThread& renderThread)
12198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
12237413289478a965336239c731ebfea37ac4dde28Chris Craik/**
12337413289478a965336239c731ebfea37ac4dde28Chris Craik * Sets a property value temporarily, generally for the duration of a test, restoring the previous
12437413289478a965336239c731ebfea37ac4dde28Chris Craik * value when going out of scope.
12537413289478a965336239c731ebfea37ac4dde28Chris Craik *
12637413289478a965336239c731ebfea37ac4dde28Chris Craik * Can be used e.g. to test behavior only active while Properties::debugOverdraw is enabled.
12737413289478a965336239c731ebfea37ac4dde28Chris Craik */
12837413289478a965336239c731ebfea37ac4dde28Chris Craiktemplate <typename T>
12937413289478a965336239c731ebfea37ac4dde28Chris Craikclass ScopedProperty {
13037413289478a965336239c731ebfea37ac4dde28Chris Craikpublic:
1311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    ScopedProperty(T& property, T newValue) : mPropertyPtr(&property), mOldValue(property) {
13237413289478a965336239c731ebfea37ac4dde28Chris Craik        property = newValue;
13337413289478a965336239c731ebfea37ac4dde28Chris Craik    }
1341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    ~ScopedProperty() { *mPropertyPtr = mOldValue; }
1351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
13637413289478a965336239c731ebfea37ac4dde28Chris Craikprivate:
13737413289478a965336239c731ebfea37ac4dde28Chris Craik    T* mPropertyPtr;
13837413289478a965336239c731ebfea37ac4dde28Chris Craik    T mOldValue;
13937413289478a965336239c731ebfea37ac4dde28Chris Craik};
14037413289478a965336239c731ebfea37ac4dde28Chris Craik
141b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass TestUtils {
142b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic:
14376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    class SignalingDtor {
14476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    public:
1451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        SignalingDtor() : mSignal(nullptr) {}
1461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        explicit SignalingDtor(int* signal) : mSignal(signal) {}
1471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        void setSignal(int* signal) { mSignal = signal; }
14876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        ~SignalingDtor() {
14976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            if (mSignal) {
15076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                (*mSignal)++;
15176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            }
15276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
1531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
15476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    private:
15576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        int* mSignal;
15676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    };
15776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
1582de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck    class MockTreeObserver : public TreeObserver {
1592de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck    public:
1602de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        virtual void onMaybeRemovedFromTree(RenderNode* node) {}
1612de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck    };
1622de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck
163b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) {
164b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < 16; i++) {
165b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (!MathUtils::areEqual(a[i], b[i])) {
166b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return false;
167b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
168b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
169b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return true;
170b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
171b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
172b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        std::unique_ptr<Snapshot> snapshot(new Snapshot());
1746e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed        // store clip first, so it isn't transformed
1756e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed        snapshot->setClip(clip.left, clip.top, clip.right, clip.bottom);
176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        *(snapshot->transform) = transform;
177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return snapshot;
178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
179b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
180aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> createBitmap(int width, int height,
1811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                      SkColorType colorType = kN32_SkColorType) {
182aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
183fc9999505a36c66892d7ccce85187936105f4f36sergeyv        return Bitmap::allocateHeapBitmap(info);
184aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
185aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv
186aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> createBitmap(int width, int height, SkBitmap* outBitmap) {
187aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        SkImageInfo info = SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
188aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        outBitmap->setInfo(info);
189f51a80d2b074d1971b11b19e890c936af5aa57a3Leon Scroggins III        return Bitmap::allocateHeapBitmap(outBitmap);
190aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
191aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv
192d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    static sp<DeferredLayerUpdater> createTextureLayerUpdater(
19398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel            renderthread::RenderThread& renderThread);
19498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel
19598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel    static sp<DeferredLayerUpdater> createTextureLayerUpdater(
196d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
197243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik            const SkMatrix& transform);
198d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
1991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    template <class CanvasType>
2001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static std::unique_ptr<DisplayList> createDisplayList(
2011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            int width, int height, std::function<void(CanvasType& canvas)> canvasCallback) {
202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        CanvasType canvas(width, height);
203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvasCallback(canvas);
204003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        return std::unique_ptr<DisplayList>(canvas.finishRecording());
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
2071bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static sp<RenderNode> createNode(
2081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            int left, int top, int right, int bottom,
20906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            std::function<void(RenderProperties& props, Canvas& canvas)> setup) {
21006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev#if HWUI_NULL_GPU
21106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        // if RenderNodes are being sync'd/used, device info will be needed, since
21206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        // DeviceInfo::maxTextureSize() affects layer property
21306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        DeviceInfo::initialize();
21406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev#endif
21506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev
21606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        sp<RenderNode> node = new RenderNode();
21706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        RenderProperties& props = node->mutateStagingProperties();
21806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        props.setLeftTopRightBottom(left, top, right, bottom);
21906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        if (setup) {
2201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            std::unique_ptr<Canvas> canvas(
2211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    Canvas::create_recording_canvas(props.getWidth(), props.getHeight()));
22206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            setup(props, *canvas.get());
2232de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck            node->setStagingDisplayList(canvas->finishRecording());
22406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        }
22506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        node->setPropertyFieldsDirty(0xFFFFFFFF);
22606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        return node;
22706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    }
22806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev
2291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    template <class RecordingCanvasType>
2301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static sp<RenderNode> createNode(
2311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            int left, int top, int right, int bottom,
23206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            std::function<void(RenderProperties& props, RecordingCanvasType& canvas)> setup) {
2339fded232a9548a304e0145011df8849fba0dcda7Chris Craik#if HWUI_NULL_GPU
23476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // if RenderNodes are being sync'd/used, device info will be needed, since
23576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // DeviceInfo::maxTextureSize() affects layer property
23676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        DeviceInfo::initialize();
2379fded232a9548a304e0145011df8849fba0dcda7Chris Craik#endif
23876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        sp<RenderNode> node = new RenderNode();
24016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        RenderProperties& props = node->mutateStagingProperties();
24116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.setLeftTopRightBottom(left, top, right, bottom);
24216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        if (setup) {
24306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            RecordingCanvasType canvas(props.getWidth(), props.getHeight());
24416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            setup(props, canvas);
2452de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck            node->setStagingDisplayList(canvas.finishRecording());
2460b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        }
24716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        node->setPropertyFieldsDirty(0xFFFFFFFF);
2480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        return node;
2490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    }
2500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
2511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static void recordNode(RenderNode& node, std::function<void(Canvas&)> contentCallback) {
2521bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
2534f901c8cec76780264021167210f90dcbe6f0d03Stan Iliev                node.stagingProperties().getWidth(), node.stagingProperties().getHeight(),
2544f901c8cec76780264021167210f90dcbe6f0d03Stan Iliev                &node));
2551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        contentCallback(*canvas.get());
2561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        node.setStagingDisplayList(canvas->finishRecording());
257b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
2591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static sp<RenderNode> createSkiaNode(
2601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            int left, int top, int right, int bottom,
2611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)>
2621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    setup,
263500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
2641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#if HWUI_NULL_GPU
265500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // if RenderNodes are being sync'd/used, device info will be needed, since
266500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // DeviceInfo::maxTextureSize() affects layer property
267500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        DeviceInfo::initialize();
2681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#endif
269500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sp<RenderNode> node = new RenderNode();
270500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (name) {
271500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->setName(name);
272500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
273500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        RenderProperties& props = node->mutateStagingProperties();
274500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        props.setLeftTopRightBottom(left, top, right, bottom);
275500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (displayList) {
2762de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck            node->setStagingDisplayList(displayList);
277500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
278500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (setup) {
279500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
2801bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                    new skiapipeline::SkiaRecordingCanvas(nullptr, props.getWidth(),
2811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                                          props.getHeight()));
282500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            setup(props, *canvas.get());
2832de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck            node->setStagingDisplayList(canvas->finishRecording());
284500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
285500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        node->setPropertyFieldsDirty(0xFFFFFFFF);
286500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        TestUtils::syncHierarchyPropertiesAndDisplayList(node);
287500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        return node;
288500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
289500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
2908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    /**
2918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Forces a sync of a tree of RenderNode, such that every descendant will have its staging
2928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * properties and DisplayList moved to the render copies.
2938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     *
2948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Note: does not check dirtiness bits, so any non-staging DisplayLists will be discarded.
2958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * For this reason, this should generally only be called once on a tree.
2968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     */
297161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) {
298161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        syncHierarchyPropertiesAndDisplayListImpl(node.get());
299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
3000a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
3019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    static sp<RenderNode>& getSyncedNode(sp<RenderNode>& node) {
3029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        syncHierarchyPropertiesAndDisplayList(node);
3039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        return node;
3047db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck    }
3057db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck
3060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    typedef std::function<void(renderthread::RenderThread& thread)> RtCallback;
3070a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
3080a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    class TestTask : public renderthread::RenderTask {
3090a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    public:
3101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        explicit TestTask(RtCallback rtCallback) : rtCallback(rtCallback) {}
3110a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        virtual ~TestTask() {}
312e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck        virtual void run() override;
3130a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        RtCallback rtCallback;
3140a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    };
3150a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
3160a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    /**
3170a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik     * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely.
3180a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik     */
3190a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    static void runOnRenderThread(RtCallback rtCallback) {
3200a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        TestTask task(rtCallback);
3211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        renderthread::RenderThread::getInstance().queue().runSync([&]() { task.run(); });
3220a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    }
32316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
3241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static bool isRenderThreadRunning() { return renderthread::RenderThread::hasInstance(); }
32538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck
32616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    static SkColor interpolateColor(float fraction, SkColor start, SkColor end);
32716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
328e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    static void layoutTextUnscaled(const SkPaint& paint, const char* text,
3291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                   std::vector<glyph_t>* outGlyphs,
3301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                   std::vector<float>* outPositions, float* outTotalAdvance,
3311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                   Rect* outBounds);
332e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik
3331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, float x,
3341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                 float y);
335a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
3361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint,
3371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                 const SkPath& path);
338d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
33979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    static std::unique_ptr<uint16_t[]> asciiToUtf16(const char* str);
340dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
341835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger    class MockFunctor : public Functor {
3421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    public:
3431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        virtual status_t operator()(int what, void* data) {
3441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            mLastMode = what;
3451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck            return DrawGlInfo::kStatusDone;
3461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        }
3471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        int getLastMode() const { return mLastMode; }
3481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck
3491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    private:
3501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck        int mLastMode = -1;
3511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck    };
352835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger
353021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    static SkColor getColor(const sk_sp<SkSurface>& surface, int x, int y);
354021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
35552771272f4f018f4fc6846224bf047497e784af1Stan Iliev    static SkRect getClipBounds(const SkCanvas* canvas);
35652771272f4f018f4fc6846224bf047497e784af1Stan Iliev    static SkRect getLocalClipBounds(const SkCanvas* canvas);
35752771272f4f018f4fc6846224bf047497e784af1Stan Iliev
358161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate:
359161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
3602de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck        MarkAndSweepRemoved observer(nullptr);
361161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        node->syncProperties();
3623afd63778e401651a7a6fd721d6d795690916ab8John Reck        if (node->mNeedsDisplayListSync) {
3633afd63778e401651a7a6fd721d6d795690916ab8John Reck            node->mNeedsDisplayListSync = false;
3643afd63778e401651a7a6fd721d6d795690916ab8John Reck            node->syncDisplayList(observer, nullptr);
3653afd63778e401651a7a6fd721d6d795690916ab8John Reck        }
366161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        auto displayList = node->getDisplayList();
367161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        if (displayList) {
36825912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev            if (displayList->isSkiaDL()) {
36925912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev                for (auto&& childDr : static_cast<skiapipeline::SkiaDisplayList*>(
3701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                              const_cast<DisplayList*>(displayList))
3711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck                                              ->mChildNodes) {
37225912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev                    syncHierarchyPropertiesAndDisplayListImpl(childDr.getRenderNode());
37325912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev                }
37425912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev            } else {
37525912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev                for (auto&& childOp : displayList->getChildren()) {
37625912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev                    syncHierarchyPropertiesAndDisplayListImpl(childOp->renderNode);
37725912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev                }
378161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik            }
379161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        }
380161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    }
381161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
3821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck};  // class TestUtils
383b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
384b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace uirenderer */
385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace android */
386