TestUtils.h revision 98787e6c9b2c10b1ab7820bdac168686025b924a
1/* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16#ifndef TEST_UTILS_H 17#define TEST_UTILS_H 18 19#include <DeviceInfo.h> 20#include <DisplayList.h> 21#include <Matrix.h> 22#include <Rect.h> 23#include <RenderNode.h> 24#include <renderstate/RenderState.h> 25#include <renderthread/RenderThread.h> 26#include <Snapshot.h> 27 28#if HWUI_NEW_OPS 29#include <RecordedOp.h> 30#else 31#include <DisplayListOp.h> 32#endif 33 34#include <memory> 35 36namespace android { 37namespace uirenderer { 38 39#define EXPECT_MATRIX_APPROX_EQ(a, b) \ 40 EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b)) 41 42#define EXPECT_RECT_APPROX_EQ(a, b) \ 43 EXPECT_TRUE(MathUtils::areEqual(a.left, b.left) \ 44 && MathUtils::areEqual(a.top, b.top) \ 45 && MathUtils::areEqual(a.right, b.right) \ 46 && MathUtils::areEqual(a.bottom, b.bottom)); 47 48/** 49 * Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope 50 * (for e.g. accessing its RenderState) 51 */ 52#define RENDERTHREAD_TEST(test_case_name, test_name) \ 53 class test_case_name##_##test_name##_RenderThreadTest { \ 54 public: \ 55 static void doTheThing(renderthread::RenderThread& renderThread); \ 56 }; \ 57 TEST(test_case_name, test_name) { \ 58 TestUtils::runOnRenderThread(test_case_name##_##test_name##_RenderThreadTest::doTheThing); \ 59 }; \ 60 void test_case_name##_##test_name##_RenderThreadTest::doTheThing(renderthread::RenderThread& renderThread) 61 62class TestUtils { 63public: 64 class SignalingDtor { 65 public: 66 SignalingDtor() 67 : mSignal(nullptr) {} 68 SignalingDtor(int* signal) 69 : mSignal(signal) {} 70 void setSignal(int* signal) { 71 mSignal = signal; 72 } 73 ~SignalingDtor() { 74 if (mSignal) { 75 (*mSignal)++; 76 } 77 } 78 private: 79 int* mSignal; 80 }; 81 82 static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) { 83 for (int i = 0; i < 16; i++) { 84 if (!MathUtils::areEqual(a[i], b[i])) { 85 return false; 86 } 87 } 88 return true; 89 } 90 91 static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) { 92 std::unique_ptr<Snapshot> snapshot(new Snapshot()); 93 snapshot->clip(clip.left, clip.top, clip.right, clip.bottom, SkRegion::kReplace_Op); 94 *(snapshot->transform) = transform; 95 return snapshot; 96 } 97 98 static SkBitmap createSkBitmap(int width, int height) { 99 SkBitmap bitmap; 100 SkImageInfo info = SkImageInfo::MakeUnknown(width, height); 101 bitmap.setInfo(info); 102 bitmap.allocPixels(info); 103 return bitmap; 104 } 105 106 template<class CanvasType> 107 static std::unique_ptr<DisplayList> createDisplayList(int width, int height, 108 std::function<void(CanvasType& canvas)> canvasCallback) { 109 CanvasType canvas(width, height); 110 canvasCallback(canvas); 111 return std::unique_ptr<DisplayList>(canvas.finishRecording()); 112 } 113 114 typedef std::function<int(RenderProperties&)> PropSetupCallback; 115 116 static PropSetupCallback getHwLayerSetupCallback() { 117 static PropSetupCallback sLayerSetupCallback = [] (RenderProperties& properties) { 118 properties.mutateLayerProperties().setType(LayerType::RenderLayer); 119 return RenderNode::GENERIC; 120 }; 121 return sLayerSetupCallback; 122 } 123 124 static sp<RenderNode> createNode(int left, int top, int right, int bottom, 125 PropSetupCallback propSetupCallback = nullptr) { 126#if HWUI_NULL_GPU 127 // if RenderNodes are being sync'd/used, device info will be needed, since 128 // DeviceInfo::maxTextureSize() affects layer property 129 DeviceInfo::initialize(); 130#endif 131 132 sp<RenderNode> node = new RenderNode(); 133 node->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom); 134 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); 135 if (propSetupCallback) { 136 node->setPropertyFieldsDirty(propSetupCallback(node->mutateStagingProperties())); 137 } 138 return node; 139 } 140 141 template<class CanvasType> 142 static sp<RenderNode> createNode(int left, int top, int right, int bottom, 143 std::function<void(CanvasType& canvas)> canvasCallback, 144 PropSetupCallback propSetupCallback = nullptr) { 145 sp<RenderNode> node = createNode(left, top, right, bottom, propSetupCallback); 146 147 auto&& props = node->stagingProperties(); // staging, since not sync'd yet 148 CanvasType canvas(props.getWidth(), props.getHeight()); 149 canvasCallback(canvas); 150 node->setStagingDisplayList(canvas.finishRecording()); 151 return node; 152 } 153 154 static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) { 155 syncHierarchyPropertiesAndDisplayListImpl(node.get()); 156 } 157 158 typedef std::function<void(renderthread::RenderThread& thread)> RtCallback; 159 160 class TestTask : public renderthread::RenderTask { 161 public: 162 TestTask(RtCallback rtCallback) 163 : rtCallback(rtCallback) {} 164 virtual ~TestTask() {} 165 virtual void run() override { 166 // RenderState only valid once RenderThread is running, so queried here 167 RenderState& renderState = renderthread::RenderThread::getInstance().renderState(); 168 169 renderState.onGLContextCreated(); 170 rtCallback(renderthread::RenderThread::getInstance()); 171 renderState.onGLContextDestroyed(); 172 }; 173 RtCallback rtCallback; 174 }; 175 176 /** 177 * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely. 178 */ 179 static void runOnRenderThread(RtCallback rtCallback) { 180 TestTask task(rtCallback); 181 renderthread::RenderThread::getInstance().queueAndWait(&task); 182 } 183private: 184 static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) { 185 node->syncProperties(); 186 node->syncDisplayList(); 187 auto displayList = node->getDisplayList(); 188 if (displayList) { 189 for (auto&& childOp : displayList->getChildren()) { 190 syncHierarchyPropertiesAndDisplayListImpl(childOp->renderNode); 191 } 192 } 193 } 194 195}; // class TestUtils 196 197} /* namespace uirenderer */ 198} /* namespace android */ 199 200#endif /* TEST_UTILS_H */ 201