TestUtils.h revision 500a0c30d4dcd012218c3e44a62926a1c34a259f
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>
220a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <Rect.h>
23b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RenderNode.h>
24c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h>
25500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <pipeline/skia/SkiaRecordingCanvas.h>
260a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderstate/RenderState.h>
270a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderthread/RenderThread.h>
280a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <Snapshot.h>
29b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
30161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <RecordedOp.h>
3116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <RecordingCanvas.h>
32161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
33b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <memory>
34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android {
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer {
37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#define EXPECT_MATRIX_APPROX_EQ(a, b) \
39b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
416fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik#define EXPECT_RECT_APPROX_EQ(a, b) \
42474081eee117025d343372f6cad99562914bc387Chih-Hung Hsieh    EXPECT_TRUE(MathUtils::areEqual((a).left, (b).left) \
43474081eee117025d343372f6cad99562914bc387Chih-Hung Hsieh            && MathUtils::areEqual((a).top, (b).top) \
44474081eee117025d343372f6cad99562914bc387Chih-Hung Hsieh            && MathUtils::areEqual((a).right, (b).right) \
45474081eee117025d343372f6cad99562914bc387Chih-Hung Hsieh            && MathUtils::areEqual((a).bottom, (b).bottom));
466fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
477435eb148e72382126e9073183e881357bb38a8bChris Craik#define EXPECT_CLIP_RECT(expRect, clipStatePtr) \
487435eb148e72382126e9073183e881357bb38a8bChris Craik        EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \
497435eb148e72382126e9073183e881357bb38a8bChris Craik        if ((clipStatePtr)->mode == ClipMode::Rectangle) { \
507435eb148e72382126e9073183e881357bb38a8bChris Craik            EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \
517435eb148e72382126e9073183e881357bb38a8bChris Craik        } else { \
527435eb148e72382126e9073183e881357bb38a8bChris Craik            ADD_FAILURE() << "ClipState not a rect"; \
537435eb148e72382126e9073183e881357bb38a8bChris Craik        }
5498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik/**
5598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope
5698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * (for e.g. accessing its RenderState)
5798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik */
5898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#define RENDERTHREAD_TEST(test_case_name, test_name) \
5998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class test_case_name##_##test_name##_RenderThreadTest { \
6098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public: \
6198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        static void doTheThing(renderthread::RenderThread& renderThread); \
6298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    }; \
6398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    TEST(test_case_name, test_name) { \
6498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        TestUtils::runOnRenderThread(test_case_name##_##test_name##_RenderThreadTest::doTheThing); \
6598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    }; \
6698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
6798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
6837413289478a965336239c731ebfea37ac4dde28Chris Craik/**
6937413289478a965336239c731ebfea37ac4dde28Chris Craik * Sets a property value temporarily, generally for the duration of a test, restoring the previous
7037413289478a965336239c731ebfea37ac4dde28Chris Craik * value when going out of scope.
7137413289478a965336239c731ebfea37ac4dde28Chris Craik *
7237413289478a965336239c731ebfea37ac4dde28Chris Craik * Can be used e.g. to test behavior only active while Properties::debugOverdraw is enabled.
7337413289478a965336239c731ebfea37ac4dde28Chris Craik */
7437413289478a965336239c731ebfea37ac4dde28Chris Craiktemplate <typename T>
7537413289478a965336239c731ebfea37ac4dde28Chris Craikclass ScopedProperty {
7637413289478a965336239c731ebfea37ac4dde28Chris Craikpublic:
7737413289478a965336239c731ebfea37ac4dde28Chris Craik    ScopedProperty(T& property, T newValue)
7837413289478a965336239c731ebfea37ac4dde28Chris Craik        : mPropertyPtr(&property)
7937413289478a965336239c731ebfea37ac4dde28Chris Craik        , mOldValue(property) {
8037413289478a965336239c731ebfea37ac4dde28Chris Craik        property = newValue;
8137413289478a965336239c731ebfea37ac4dde28Chris Craik    }
8237413289478a965336239c731ebfea37ac4dde28Chris Craik    ~ScopedProperty() {
8337413289478a965336239c731ebfea37ac4dde28Chris Craik        *mPropertyPtr = mOldValue;
8437413289478a965336239c731ebfea37ac4dde28Chris Craik    }
8537413289478a965336239c731ebfea37ac4dde28Chris Craikprivate:
8637413289478a965336239c731ebfea37ac4dde28Chris Craik    T* mPropertyPtr;
8737413289478a965336239c731ebfea37ac4dde28Chris Craik    T mOldValue;
8837413289478a965336239c731ebfea37ac4dde28Chris Craik};
8937413289478a965336239c731ebfea37ac4dde28Chris Craik
90b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass TestUtils {
91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic:
9276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    class SignalingDtor {
9376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    public:
9476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        SignalingDtor()
9576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                : mSignal(nullptr) {}
96a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit SignalingDtor(int* signal)
9776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                : mSignal(signal) {}
9876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        void setSignal(int* signal) {
9976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            mSignal = signal;
10076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
10176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        ~SignalingDtor() {
10276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            if (mSignal) {
10376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                (*mSignal)++;
10476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            }
10576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
10676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    private:
10776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        int* mSignal;
10876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    };
10976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
110b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) {
111b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < 16; i++) {
112b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (!MathUtils::areEqual(a[i], b[i])) {
113b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return false;
114b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
115b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
116b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return true;
117b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
118b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
119b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
120b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        std::unique_ptr<Snapshot> snapshot(new Snapshot());
121a2a70723b8cbda4354d23f901f995623e819012cChris Craik        snapshot->clip(clip, SkRegion::kReplace_Op); // store clip first, so it isn't transformed
122b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        *(snapshot->transform) = transform;
123b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return snapshot;
124b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
125b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
126aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> createBitmap(int width, int height,
127aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv            SkColorType colorType = kN32_SkColorType) {
128aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType);
129fc9999505a36c66892d7ccce85187936105f4f36sergeyv        return Bitmap::allocateHeapBitmap(info);
130aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
131aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv
132aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    static sk_sp<Bitmap> createBitmap(int width, int height, SkBitmap* outBitmap) {
133aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        SkImageInfo info = SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType);
134aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        outBitmap->setInfo(info);
135aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv        return Bitmap::allocateHeapBitmap(outBitmap, nullptr);
136aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv    }
137aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv
138d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik    static sp<DeferredLayerUpdater> createTextureLayerUpdater(
139d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik            renderthread::RenderThread& renderThread, uint32_t width, uint32_t height,
140243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik            const SkMatrix& transform);
141d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik
142b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    template<class CanvasType>
143003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    static std::unique_ptr<DisplayList> createDisplayList(int width, int height,
144b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            std::function<void(CanvasType& canvas)> canvasCallback) {
145b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        CanvasType canvas(width, height);
146b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvasCallback(canvas);
147003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        return std::unique_ptr<DisplayList>(canvas.finishRecording());
148b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
149b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
150d3daa3198e2212c985c634821682d5819346b653Chris Craik    static sp<RenderNode> createNode(int left, int top, int right, int bottom,
15106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            std::function<void(RenderProperties& props, Canvas& canvas)> setup) {
15206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev#if HWUI_NULL_GPU
15306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        // if RenderNodes are being sync'd/used, device info will be needed, since
15406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        // DeviceInfo::maxTextureSize() affects layer property
15506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        DeviceInfo::initialize();
15606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev#endif
15706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev
15806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        sp<RenderNode> node = new RenderNode();
15906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        RenderProperties& props = node->mutateStagingProperties();
16006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        props.setLeftTopRightBottom(left, top, right, bottom);
16106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        if (setup) {
16206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(props.getWidth(),
16306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev                    props.getHeight()));
16406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            setup(props, *canvas.get());
16506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            node->setStagingDisplayList(canvas->finishRecording(), nullptr);
16606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        }
16706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        node->setPropertyFieldsDirty(0xFFFFFFFF);
16806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev        return node;
16906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    }
17006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev
17106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    template<class RecordingCanvasType>
17206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev    static sp<RenderNode> createNode(int left, int top, int right, int bottom,
17306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            std::function<void(RenderProperties& props, RecordingCanvasType& canvas)> setup) {
1749fded232a9548a304e0145011df8849fba0dcda7Chris Craik#if HWUI_NULL_GPU
17576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // if RenderNodes are being sync'd/used, device info will be needed, since
17676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // DeviceInfo::maxTextureSize() affects layer property
17776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        DeviceInfo::initialize();
1789fded232a9548a304e0145011df8849fba0dcda7Chris Craik#endif
17976caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
180b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        sp<RenderNode> node = new RenderNode();
18116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        RenderProperties& props = node->mutateStagingProperties();
18216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.setLeftTopRightBottom(left, top, right, bottom);
18316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        if (setup) {
18406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            RecordingCanvasType canvas(props.getWidth(), props.getHeight());
18516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            setup(props, canvas);
18651f2d606dcbfba3cc5b03dfea37c1304b91c232fJohn Reck            node->setStagingDisplayList(canvas.finishRecording(), nullptr);
1870b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        }
18816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        node->setPropertyFieldsDirty(0xFFFFFFFF);
1890b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        return node;
1900b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    }
1910b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
19216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    static void recordNode(RenderNode& node,
19306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            std::function<void(Canvas&)> contentCallback) {
19406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev       std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas(
19506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev            node.stagingProperties().getWidth(), node.stagingProperties().getHeight()));
19606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev       contentCallback(*canvas.get());
19706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev       node.setStagingDisplayList(canvas->finishRecording(), nullptr);
198b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
199b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
200500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    static sp<RenderNode> createSkiaNode(int left, int top, int right, int bottom,
201500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)> setup,
202500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) {
203500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    #if HWUI_NULL_GPU
204500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // if RenderNodes are being sync'd/used, device info will be needed, since
205500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        // DeviceInfo::maxTextureSize() affects layer property
206500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        DeviceInfo::initialize();
207500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    #endif
208500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        sp<RenderNode> node = new RenderNode();
209500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (name) {
210500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->setName(name);
211500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
212500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        RenderProperties& props = node->mutateStagingProperties();
213500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        props.setLeftTopRightBottom(left, top, right, bottom);
214500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (displayList) {
215500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->setStagingDisplayList(displayList, nullptr);
216500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
217500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        if (setup) {
218500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas(
219500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                new skiapipeline::SkiaRecordingCanvas(nullptr,
220500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev                props.getWidth(), props.getHeight()));
221500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            setup(props, *canvas.get());
222500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev            node->setStagingDisplayList(canvas->finishRecording(), nullptr);
223500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        }
224500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        node->setPropertyFieldsDirty(0xFFFFFFFF);
225500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        TestUtils::syncHierarchyPropertiesAndDisplayList(node);
226500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev        return node;
227500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev    }
228500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev
2298d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    /**
2308d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Forces a sync of a tree of RenderNode, such that every descendant will have its staging
2318d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * properties and DisplayList moved to the render copies.
2328d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     *
2338d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Note: does not check dirtiness bits, so any non-staging DisplayLists will be discarded.
2348d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * For this reason, this should generally only be called once on a tree.
2358d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     */
236161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) {
237161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        syncHierarchyPropertiesAndDisplayListImpl(node.get());
238b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
2390a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
2409cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik    static sp<RenderNode>& getSyncedNode(sp<RenderNode>& node) {
2419cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        syncHierarchyPropertiesAndDisplayList(node);
2429cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik        return node;
2437db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck    }
2447db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck
2450b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    typedef std::function<void(renderthread::RenderThread& thread)> RtCallback;
2460a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
2470a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    class TestTask : public renderthread::RenderTask {
2480a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    public:
249a619ec70cf765d9166f0862e74653711b87307b3Chih-Hung Hsieh        explicit TestTask(RtCallback rtCallback)
2500a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik                : rtCallback(rtCallback) {}
2510a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        virtual ~TestTask() {}
252e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck        virtual void run() override;
2530a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        RtCallback rtCallback;
2540a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    };
2550a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
2560a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    /**
2570a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik     * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely.
2580a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik     */
2590a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    static void runOnRenderThread(RtCallback rtCallback) {
2600a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        TestTask task(rtCallback);
2610a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        renderthread::RenderThread::getInstance().queueAndWait(&task);
2620a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    }
26316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
26438e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck    static bool isRenderThreadRunning() {
26538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck        return renderthread::RenderThread::hasInstance();
26638e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck    }
26738e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck
26816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    static SkColor interpolateColor(float fraction, SkColor start, SkColor end);
26916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
270e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik    static void layoutTextUnscaled(const SkPaint& paint, const char* text,
271e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions,
272e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik            float* outTotalAdvance, Rect* outBounds);
273e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik
27479abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    static void drawUtf8ToCanvas(Canvas* canvas, const char* text,
27542a5407f2c6403ea7aa7a64eaf19948dc4050df5Chris Craik            const SkPaint& paint, float x, float y);
276a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
27779abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    static void drawUtf8ToCanvas(Canvas* canvas, const char* text,
278d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik            const SkPaint& paint, const SkPath& path);
279d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik
28079abbf22d4f672208327546661e694d837f564a9Derek Sollenberger    static std::unique_ptr<uint16_t[]> asciiToUtf16(const char* str);
281dccca44ffda4836b56a21da95a046c9708ffd49csergeyv
282835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger    class MockFunctor : public Functor {
283835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger     public:
284835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger         virtual status_t operator ()(int what, void* data) {
285835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger             mLastMode = what;
286835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger             return DrawGlInfo::kStatusDone;
287835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger         }
288835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger         int getLastMode() const { return mLastMode; }
289835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger     private:
290835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger         int mLastMode = -1;
291835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger     };
292835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger
293021693b967a2c5556dddd183eb0247df4079e1adStan Iliev    static SkColor getColor(const sk_sp<SkSurface>& surface, int x, int y);
294021693b967a2c5556dddd183eb0247df4079e1adStan Iliev
295161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate:
296161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
297161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        node->syncProperties();
29844b49f070aafe8ad44efae87341121cce49ff11cJohn Reck        node->syncDisplayList(nullptr);
299161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        auto displayList = node->getDisplayList();
300161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        if (displayList) {
301161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik            for (auto&& childOp : displayList->getChildren()) {
302161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik                syncHierarchyPropertiesAndDisplayListImpl(childOp->renderNode);
303161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik            }
304161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        }
305161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    }
306161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
307b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // class TestUtils
308b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
309b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace uirenderer */
310b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace android */
311