TestUtils.h revision 8d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7
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 */
16b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#ifndef TEST_UTILS_H
17b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#define TEST_UTILS_H
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>
240a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderstate/RenderState.h>
250a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderthread/RenderThread.h>
260a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <Snapshot.h>
27b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
28161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#if HWUI_NEW_OPS
29161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <RecordedOp.h>
3016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <RecordingCanvas.h>
31161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#else
32161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <DisplayListOp.h>
3316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <DisplayListCanvas.h>
34161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#endif
35161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <memory>
37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android {
39b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer {
40b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
4116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#if HWUI_NEW_OPS
4216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recktypedef RecordingCanvas TestCanvas;
4316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#else
4416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Recktypedef DisplayListCanvas TestCanvas;
4516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#endif
4616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
47b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#define EXPECT_MATRIX_APPROX_EQ(a, b) \
48b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b))
49b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
506fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik#define EXPECT_RECT_APPROX_EQ(a, b) \
516fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik    EXPECT_TRUE(MathUtils::areEqual(a.left, b.left) \
526fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            && MathUtils::areEqual(a.top, b.top) \
536fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            && MathUtils::areEqual(a.right, b.right) \
546fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik            && MathUtils::areEqual(a.bottom, b.bottom));
556fe991e5e76f9af9dab960100d5768d96d5f4daaChris Craik
5698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik/**
5798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope
5898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * (for e.g. accessing its RenderState)
5998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik */
6098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik#define RENDERTHREAD_TEST(test_case_name, test_name) \
6198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    class test_case_name##_##test_name##_RenderThreadTest { \
6298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    public: \
6398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        static void doTheThing(renderthread::RenderThread& renderThread); \
6498787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    }; \
6598787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    TEST(test_case_name, test_name) { \
6698787e6c9b2c10b1ab7820bdac168686025b924aChris Craik        TestUtils::runOnRenderThread(test_case_name##_##test_name##_RenderThreadTest::doTheThing); \
6798787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    }; \
6898787e6c9b2c10b1ab7820bdac168686025b924aChris Craik    void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread)
6998787e6c9b2c10b1ab7820bdac168686025b924aChris Craik
70b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass TestUtils {
71b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic:
7276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    class SignalingDtor {
7376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    public:
7476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        SignalingDtor()
7576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                : mSignal(nullptr) {}
7676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        SignalingDtor(int* signal)
7776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                : mSignal(signal) {}
7876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        void setSignal(int* signal) {
7976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            mSignal = signal;
8076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
8176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        ~SignalingDtor() {
8276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            if (mSignal) {
8376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik                (*mSignal)++;
8476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik            }
8576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        }
8676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    private:
8776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik        int* mSignal;
8876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik    };
8976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik
90b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) {
91b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        for (int i = 0; i < 16; i++) {
92b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            if (!MathUtils::areEqual(a[i], b[i])) {
93b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik                return false;
94b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            }
95b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        }
96b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return true;
97b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
98b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
99b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) {
100b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        std::unique_ptr<Snapshot> snapshot(new Snapshot());
101b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        snapshot->clip(clip.left, clip.top, clip.right, clip.bottom, SkRegion::kReplace_Op);
102b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        *(snapshot->transform) = transform;
103b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        return snapshot;
104b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
105b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
106ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik    static SkBitmap createSkBitmap(int width, int height) {
107ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        SkBitmap bitmap;
10816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        SkImageInfo info = SkImageInfo::Make(width, height,
10916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck                kN32_SkColorType, kPremul_SkAlphaType);
1100a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        bitmap.setInfo(info);
1110a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        bitmap.allocPixels(info);
112ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik        return bitmap;
113ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik    }
114ddf2215d9807b641dbcb304779ef6b530f876ac7Chris Craik
115b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    template<class CanvasType>
116003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik    static std::unique_ptr<DisplayList> createDisplayList(int width, int height,
117b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik            std::function<void(CanvasType& canvas)> canvasCallback) {
118b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        CanvasType canvas(width, height);
119b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        canvasCallback(canvas);
120003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik        return std::unique_ptr<DisplayList>(canvas.finishRecording());
121b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
122b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
123d3daa3198e2212c985c634821682d5819346b653Chris Craik    static sp<RenderNode> createNode(int left, int top, int right, int bottom,
1248d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik            std::function<void(RenderProperties& props, TestCanvas& canvas)> setup) {
1259fded232a9548a304e0145011df8849fba0dcda7Chris Craik#if HWUI_NULL_GPU
12676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // if RenderNodes are being sync'd/used, device info will be needed, since
12776caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        // DeviceInfo::maxTextureSize() affects layer property
12876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik        DeviceInfo::initialize();
1299fded232a9548a304e0145011df8849fba0dcda7Chris Craik#endif
13076caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik
131b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik        sp<RenderNode> node = new RenderNode();
13216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        RenderProperties& props = node->mutateStagingProperties();
13316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        props.setLeftTopRightBottom(left, top, right, bottom);
13416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        if (setup) {
13516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            TestCanvas canvas(props.getWidth(), props.getHeight());
13616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            setup(props, canvas);
13716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            node->setStagingDisplayList(canvas.finishRecording());
1380b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        }
13916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck        node->setPropertyFieldsDirty(0xFFFFFFFF);
1400b7e8245db728d127ada698be63d78b33fc6e4daChris Craik        return node;
1410b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    }
1420b7e8245db728d127ada698be63d78b33fc6e4daChris Craik
14316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    static void recordNode(RenderNode& node,
14416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck            std::function<void(TestCanvas&)> contentCallback) {
14516c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck       TestCanvas canvas(node.stagingProperties().getWidth(),
14616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck               node.stagingProperties().getHeight());
14716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck       contentCallback(canvas);
14816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck       node.setStagingDisplayList(canvas.finishRecording());
149b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
150b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
1518d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik    /**
1528d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Forces a sync of a tree of RenderNode, such that every descendant will have its staging
1538d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * properties and DisplayList moved to the render copies.
1548d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     *
1558d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * Note: does not check dirtiness bits, so any non-staging DisplayLists will be discarded.
1568d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     * For this reason, this should generally only be called once on a tree.
1578d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik     */
158161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) {
159161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        syncHierarchyPropertiesAndDisplayListImpl(node.get());
160b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik    }
1610a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
1620b7e8245db728d127ada698be63d78b33fc6e4daChris Craik    typedef std::function<void(renderthread::RenderThread& thread)> RtCallback;
1630a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
1640a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    class TestTask : public renderthread::RenderTask {
1650a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    public:
1660a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        TestTask(RtCallback rtCallback)
1670a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik                : rtCallback(rtCallback) {}
1680a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        virtual ~TestTask() {}
1690a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        virtual void run() override {
1700a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik            // RenderState only valid once RenderThread is running, so queried here
1710a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik            RenderState& renderState = renderthread::RenderThread::getInstance().renderState();
1720a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
1730a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik            renderState.onGLContextCreated();
1740b7e8245db728d127ada698be63d78b33fc6e4daChris Craik            rtCallback(renderthread::RenderThread::getInstance());
1750a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik            renderState.onGLContextDestroyed();
1760a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        };
1770a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        RtCallback rtCallback;
1780a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    };
1790a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik
1800a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    /**
1810a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik     * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely.
1820a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik     */
1830a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    static void runOnRenderThread(RtCallback rtCallback) {
1840a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        TestTask task(rtCallback);
1850a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik        renderthread::RenderThread::getInstance().queueAndWait(&task);
1860a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik    }
18716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
18816c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck    static SkColor interpolateColor(float fraction, SkColor start, SkColor end);
18916c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck
190a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik    static void drawTextToCanvas(TestCanvas* canvas, const char* text,
191a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik            const SkPaint& inPaint, float x, float y);
192a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik
193161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate:
194161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
195161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        node->syncProperties();
196161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        node->syncDisplayList();
197161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        auto displayList = node->getDisplayList();
198161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        if (displayList) {
199161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik            for (auto&& childOp : displayList->getChildren()) {
200161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik                syncHierarchyPropertiesAndDisplayListImpl(childOp->renderNode);
201161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik            }
202161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik        }
203161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik    }
204161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik
205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik}; // class TestUtils
206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
207b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace uirenderer */
208b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace android */
209b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik
210b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#endif /* TEST_UTILS_H */
211