TestUtils.h revision 161f54b2d4160b8d3f3da9eba5746da5162e4821
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 48class TestUtils { 49public: 50 class SignalingDtor { 51 public: 52 SignalingDtor() 53 : mSignal(nullptr) {} 54 SignalingDtor(int* signal) 55 : mSignal(signal) {} 56 void setSignal(int* signal) { 57 mSignal = signal; 58 } 59 ~SignalingDtor() { 60 if (mSignal) { 61 (*mSignal)++; 62 } 63 } 64 private: 65 int* mSignal; 66 }; 67 68 static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) { 69 for (int i = 0; i < 16; i++) { 70 if (!MathUtils::areEqual(a[i], b[i])) { 71 return false; 72 } 73 } 74 return true; 75 } 76 77 static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) { 78 std::unique_ptr<Snapshot> snapshot(new Snapshot()); 79 snapshot->clip(clip.left, clip.top, clip.right, clip.bottom, SkRegion::kReplace_Op); 80 *(snapshot->transform) = transform; 81 return snapshot; 82 } 83 84 static SkBitmap createSkBitmap(int width, int height) { 85 SkBitmap bitmap; 86 SkImageInfo info = SkImageInfo::MakeUnknown(width, height); 87 bitmap.setInfo(info); 88 bitmap.allocPixels(info); 89 return bitmap; 90 } 91 92 template<class CanvasType> 93 static std::unique_ptr<DisplayList> createDisplayList(int width, int height, 94 std::function<void(CanvasType& canvas)> canvasCallback) { 95 CanvasType canvas(width, height); 96 canvasCallback(canvas); 97 return std::unique_ptr<DisplayList>(canvas.finishRecording()); 98 } 99 100 static sp<RenderNode> createNode(int left, int top, int right, int bottom, bool onLayer = false) { 101 // if RenderNodes are being sync'd/used, device info will be needed, since 102 // DeviceInfo::maxTextureSize() affects layer property 103 DeviceInfo::initialize(); 104 105 sp<RenderNode> node = new RenderNode(); 106 node->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom); 107 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y); 108 if (onLayer) { 109 node->mutateStagingProperties().mutateLayerProperties().setType(LayerType::RenderLayer); 110 node->setPropertyFieldsDirty(RenderNode::GENERIC); 111 } 112 return node; 113 } 114 115 template<class CanvasType> 116 static sp<RenderNode> createNode(int left, int top, int right, int bottom, 117 std::function<void(CanvasType& canvas)> canvasCallback, bool onLayer = false) { 118 sp<RenderNode> node = createNode(left, top, right, bottom, onLayer); 119 120 auto&& props = node->stagingProperties(); // staging, since not sync'd yet 121 CanvasType canvas(props.getWidth(), props.getHeight()); 122 canvasCallback(canvas); 123 node->setStagingDisplayList(canvas.finishRecording()); 124 return node; 125 } 126 127 static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) { 128 syncHierarchyPropertiesAndDisplayListImpl(node.get()); 129 } 130 131 typedef std::function<void(renderthread::RenderThread& thread)> RtCallback; 132 133 class TestTask : public renderthread::RenderTask { 134 public: 135 TestTask(RtCallback rtCallback) 136 : rtCallback(rtCallback) {} 137 virtual ~TestTask() {} 138 virtual void run() override { 139 // RenderState only valid once RenderThread is running, so queried here 140 RenderState& renderState = renderthread::RenderThread::getInstance().renderState(); 141 142 renderState.onGLContextCreated(); 143 rtCallback(renderthread::RenderThread::getInstance()); 144 renderState.onGLContextDestroyed(); 145 }; 146 RtCallback rtCallback; 147 }; 148 149 /** 150 * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely. 151 */ 152 static void runOnRenderThread(RtCallback rtCallback) { 153 TestTask task(rtCallback); 154 renderthread::RenderThread::getInstance().queueAndWait(&task); 155 } 156private: 157 static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) { 158 node->syncProperties(); 159 node->syncDisplayList(); 160 auto displayList = node->getDisplayList(); 161 if (displayList) { 162 for (auto&& childOp : displayList->getChildren()) { 163 syncHierarchyPropertiesAndDisplayListImpl(childOp->renderNode); 164 } 165 } 166 } 167 168}; // class TestUtils 169 170} /* namespace uirenderer */ 171} /* namespace android */ 172 173#endif /* TEST_UTILS_H */ 174