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