TestUtils.h revision 4f901c8cec76780264021167210f90dcbe6f0d03
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> 2298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#include <Properties.h> 230a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <Rect.h> 24b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <RenderNode.h> 251bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#include <Snapshot.h> 26c1c54062f8cc9d47bdea820ae5ab6aef260b4488sergeyv#include <hwui/Bitmap.h> 27500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev#include <pipeline/skia/SkiaRecordingCanvas.h> 280a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderstate/RenderState.h> 290a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik#include <renderthread/RenderThread.h> 30b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 31161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik#include <RecordedOp.h> 3216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck#include <RecordingCanvas.h> 33161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 34b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik#include <memory> 35b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 36b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace android { 37b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craiknamespace uirenderer { 38b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 391bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define EXPECT_MATRIX_APPROX_EQ(a, b) EXPECT_TRUE(TestUtils::matricesAreApproxEqual(a, b)) 401bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 411bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define EXPECT_RECT_APPROX_EQ(a, b) \ 421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck EXPECT_TRUE(MathUtils::areEqual((a).left, (b).left) && \ 431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck MathUtils::areEqual((a).top, (b).top) && \ 441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck MathUtils::areEqual((a).right, (b).right) && \ 451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck MathUtils::areEqual((a).bottom, (b).bottom)); 461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define EXPECT_CLIP_RECT(expRect, clipStatePtr) \ 481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck EXPECT_NE(nullptr, (clipStatePtr)) << "Op is unclipped"; \ 491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck if ((clipStatePtr)->mode == ClipMode::Rectangle) { \ 501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck EXPECT_EQ((expRect), reinterpret_cast<const ClipRect*>(clipStatePtr)->rect); \ 511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck } else { \ 521bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ADD_FAILURE() << "ClipState not a rect"; \ 531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck } 5498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 5598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#define INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, functionCall) \ 561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TEST(test_case_name, test_name##_##pipeline) { \ 571bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck RenderPipelineType oldType = Properties::getRenderPipelineType(); \ 581bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Properties::overrideRenderPipelineType(RenderPipelineType::pipeline); \ 591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck functionCall; \ 601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Properties::overrideRenderPipelineType(oldType); \ 6198c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel }; 6298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 6398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel/** 6498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel * Like gtests' TEST, but only runs with the OpenGL RenderPipelineType 6598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel */ 661bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define OPENGL_PIPELINE_TEST(test_case_name, test_name) \ 671bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck class test_case_name##_##test_name##_HwuiTest { \ 681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck public: \ 691bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static void doTheThing(); \ 701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }; \ 711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck INNER_PIPELINE_TEST(test_case_name, test_name, OpenGL, \ 721bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck test_case_name##_##test_name##_HwuiTest::doTheThing()) \ 7398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel void test_case_name##_##test_name##_HwuiTest::doTheThing() 7498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 7598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel#define INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, pipeline) \ 761bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck INNER_PIPELINE_TEST(test_case_name, test_name, pipeline, \ 771bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck TestUtils::runOnRenderThread( \ 781bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck test_case_name##_##test_name##_RenderThreadTest::doTheThing)) 7998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 8098787e6c9b2c10b1ab7820bdac168686025b924aChris Craik/** 8198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * Like gtest's TEST, but runs on the RenderThread, and 'renderThread' is passed, in top level scope 8298787e6c9b2c10b1ab7820bdac168686025b924aChris Craik * (for e.g. accessing its RenderState) 8398787e6c9b2c10b1ab7820bdac168686025b924aChris Craik */ 841bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDERTHREAD_TEST(test_case_name, test_name) \ 851bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck class test_case_name##_##test_name##_RenderThreadTest { \ 861bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck public: \ 871bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static void doTheThing(renderthread::RenderThread& renderThread); \ 881bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }; \ 891bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \ 901bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \ 910f89539de6df6ebe991ae29510e55867317389c0Derek Sollenberger /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \ 921bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \ 931bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \ 941bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderthread::RenderThread& renderThread) 9598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 9698c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel/** 9798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel * Like RENDERTHREAD_TEST, but only runs with the OpenGL RenderPipelineType 9898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel */ 991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDERTHREAD_OPENGL_PIPELINE_TEST(test_case_name, test_name) \ 1001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck class test_case_name##_##test_name##_RenderThreadTest { \ 1011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck public: \ 10298c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel static void doTheThing(renderthread::RenderThread& renderThread); \ 1031bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }; \ 1041bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, OpenGL); \ 1051bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \ 1061bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderthread::RenderThread& renderThread) 10798c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 10898c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel/** 10998c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel * Like RENDERTHREAD_TEST, but only runs with the Skia RenderPipelineTypes 11098c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel */ 1111bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#define RENDERTHREAD_SKIA_PIPELINE_TEST(test_case_name, test_name) \ 1121bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck class test_case_name##_##test_name##_RenderThreadTest { \ 1131bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck public: \ 1141bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static void doTheThing(renderthread::RenderThread& renderThread); \ 1151bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }; \ 1161bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaGL); \ 1170f89539de6df6ebe991ae29510e55867317389c0Derek Sollenberger /* Temporarily disabling Vulkan until we can figure out a way to stub out the driver */ \ 1181bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck /* INNER_PIPELINE_RENDERTHREAD_TEST(test_case_name, test_name, SkiaVulkan); */ \ 1191bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void test_case_name##_##test_name##_RenderThreadTest::doTheThing( \ 1201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderthread::RenderThread& renderThread) 12198787e6c9b2c10b1ab7820bdac168686025b924aChris Craik 12237413289478a965336239c731ebfea37ac4dde28Chris Craik/** 12337413289478a965336239c731ebfea37ac4dde28Chris Craik * Sets a property value temporarily, generally for the duration of a test, restoring the previous 12437413289478a965336239c731ebfea37ac4dde28Chris Craik * value when going out of scope. 12537413289478a965336239c731ebfea37ac4dde28Chris Craik * 12637413289478a965336239c731ebfea37ac4dde28Chris Craik * Can be used e.g. to test behavior only active while Properties::debugOverdraw is enabled. 12737413289478a965336239c731ebfea37ac4dde28Chris Craik */ 12837413289478a965336239c731ebfea37ac4dde28Chris Craiktemplate <typename T> 12937413289478a965336239c731ebfea37ac4dde28Chris Craikclass ScopedProperty { 13037413289478a965336239c731ebfea37ac4dde28Chris Craikpublic: 1311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ScopedProperty(T& property, T newValue) : mPropertyPtr(&property), mOldValue(property) { 13237413289478a965336239c731ebfea37ac4dde28Chris Craik property = newValue; 13337413289478a965336239c731ebfea37ac4dde28Chris Craik } 1341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ~ScopedProperty() { *mPropertyPtr = mOldValue; } 1351bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 13637413289478a965336239c731ebfea37ac4dde28Chris Craikprivate: 13737413289478a965336239c731ebfea37ac4dde28Chris Craik T* mPropertyPtr; 13837413289478a965336239c731ebfea37ac4dde28Chris Craik T mOldValue; 13937413289478a965336239c731ebfea37ac4dde28Chris Craik}; 14037413289478a965336239c731ebfea37ac4dde28Chris Craik 141b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikclass TestUtils { 142b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craikpublic: 14376ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik class SignalingDtor { 14476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik public: 1451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck SignalingDtor() : mSignal(nullptr) {} 1461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck explicit SignalingDtor(int* signal) : mSignal(signal) {} 1471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck void setSignal(int* signal) { mSignal = signal; } 14876ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik ~SignalingDtor() { 14976ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik if (mSignal) { 15076ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik (*mSignal)++; 15176ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik } 15276ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik } 1531bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 15476ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik private: 15576ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik int* mSignal; 15676ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik }; 15776ace115f7870fed9899a9db7d3852e21b5fb258Chris Craik 1582de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck class MockTreeObserver : public TreeObserver { 1592de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck public: 1602de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck virtual void onMaybeRemovedFromTree(RenderNode* node) {} 1612de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck }; 1622de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck 163b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static bool matricesAreApproxEqual(const Matrix4& a, const Matrix4& b) { 164b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik for (int i = 0; i < 16; i++) { 165b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik if (!MathUtils::areEqual(a[i], b[i])) { 166b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return false; 167b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 168b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 169b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return true; 170b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 171b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 172b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik static std::unique_ptr<Snapshot> makeSnapshot(const Matrix4& transform, const Rect& clip) { 173b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik std::unique_ptr<Snapshot> snapshot(new Snapshot()); 1746e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed // store clip first, so it isn't transformed 1756e49c9f007c879f05b035c40c0ba543c00f9d0d0Mike Reed snapshot->setClip(clip.left, clip.top, clip.right, clip.bottom); 176b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik *(snapshot->transform) = transform; 177b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik return snapshot; 178b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 179b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 180aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv static sk_sp<Bitmap> createBitmap(int width, int height, 1811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck SkColorType colorType = kN32_SkColorType) { 182aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv SkImageInfo info = SkImageInfo::Make(width, height, colorType, kPremul_SkAlphaType); 183fc9999505a36c66892d7ccce85187936105f4f36sergeyv return Bitmap::allocateHeapBitmap(info); 184aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv } 185aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv 186aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv static sk_sp<Bitmap> createBitmap(int width, int height, SkBitmap* outBitmap) { 187aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv SkImageInfo info = SkImageInfo::Make(width, height, kN32_SkColorType, kPremul_SkAlphaType); 188aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv outBitmap->setInfo(info); 189f51a80d2b074d1971b11b19e890c936af5aa57a3Leon Scroggins III return Bitmap::allocateHeapBitmap(outBitmap); 190aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv } 191aed7f58fb05a25ce2112829e77c0eb5dd268e8a7sergeyv 192d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik static sp<DeferredLayerUpdater> createTextureLayerUpdater( 19398c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel renderthread::RenderThread& renderThread); 19498c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel 19598c78dad1969e2321cfee2085faa55d95bba7e29Greg Daniel static sp<DeferredLayerUpdater> createTextureLayerUpdater( 196d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik renderthread::RenderThread& renderThread, uint32_t width, uint32_t height, 197243e85b2e443def1ef47a180e824b36f513c8db8Chris Craik const SkMatrix& transform); 198d2dfd8f128b632ed99418ab2b32949c939a9a369Chris Craik 1991bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck template <class CanvasType> 2001bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static std::unique_ptr<DisplayList> createDisplayList( 2011bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int width, int height, std::function<void(CanvasType& canvas)> canvasCallback) { 202b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik CanvasType canvas(width, height); 203b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik canvasCallback(canvas); 204003cc3dec8e2a92e51086fbcd5ee1bb236efa701Chris Craik return std::unique_ptr<DisplayList>(canvas.finishRecording()); 205b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 206b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2071bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static sp<RenderNode> createNode( 2081bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int left, int top, int right, int bottom, 20906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev std::function<void(RenderProperties& props, Canvas& canvas)> setup) { 21006152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev#if HWUI_NULL_GPU 21106152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev // if RenderNodes are being sync'd/used, device info will be needed, since 21206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev // DeviceInfo::maxTextureSize() affects layer property 21306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev DeviceInfo::initialize(); 21406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev#endif 21506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev 21606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev sp<RenderNode> node = new RenderNode(); 21706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev RenderProperties& props = node->mutateStagingProperties(); 21806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev props.setLeftTopRightBottom(left, top, right, bottom); 21906152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev if (setup) { 2201bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::unique_ptr<Canvas> canvas( 2211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Canvas::create_recording_canvas(props.getWidth(), props.getHeight())); 22206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev setup(props, *canvas.get()); 2232de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck node->setStagingDisplayList(canvas->finishRecording()); 22406152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev } 22506152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev node->setPropertyFieldsDirty(0xFFFFFFFF); 22606152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev return node; 22706152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev } 22806152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev 2291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck template <class RecordingCanvasType> 2301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static sp<RenderNode> createNode( 2311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int left, int top, int right, int bottom, 23206152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev std::function<void(RenderProperties& props, RecordingCanvasType& canvas)> setup) { 2339fded232a9548a304e0145011df8849fba0dcda7Chris Craik#if HWUI_NULL_GPU 23476caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // if RenderNodes are being sync'd/used, device info will be needed, since 23576caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik // DeviceInfo::maxTextureSize() affects layer property 23676caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik DeviceInfo::initialize(); 2379fded232a9548a304e0145011df8849fba0dcda7Chris Craik#endif 23876caecf421b42e9b8294a65f62ff2d90b55a337bChris Craik 239b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik sp<RenderNode> node = new RenderNode(); 24016c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck RenderProperties& props = node->mutateStagingProperties(); 24116c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck props.setLeftTopRightBottom(left, top, right, bottom); 24216c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck if (setup) { 24306152cdd06da50762716cd455dcf7ab0117f25b0Stan Iliev RecordingCanvasType canvas(props.getWidth(), props.getHeight()); 24416c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck setup(props, canvas); 2452de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck node->setStagingDisplayList(canvas.finishRecording()); 2460b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 24716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck node->setPropertyFieldsDirty(0xFFFFFFFF); 2480b7e8245db728d127ada698be63d78b33fc6e4daChris Craik return node; 2490b7e8245db728d127ada698be63d78b33fc6e4daChris Craik } 2500b7e8245db728d127ada698be63d78b33fc6e4daChris Craik 2511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static void recordNode(RenderNode& node, std::function<void(Canvas&)> contentCallback) { 2521bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::unique_ptr<Canvas> canvas(Canvas::create_recording_canvas( 2534f901c8cec76780264021167210f90dcbe6f0d03Stan Iliev node.stagingProperties().getWidth(), node.stagingProperties().getHeight(), 2544f901c8cec76780264021167210f90dcbe6f0d03Stan Iliev &node)); 2551bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck contentCallback(*canvas.get()); 2561bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck node.setStagingDisplayList(canvas->finishRecording()); 257b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 258b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 2591bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static sp<RenderNode> createSkiaNode( 2601bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int left, int top, int right, int bottom, 2611bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::function<void(RenderProperties& props, skiapipeline::SkiaRecordingCanvas& canvas)> 2621bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck setup, 263500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev const char* name = nullptr, skiapipeline::SkiaDisplayList* displayList = nullptr) { 2641bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#if HWUI_NULL_GPU 265500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev // if RenderNodes are being sync'd/used, device info will be needed, since 266500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev // DeviceInfo::maxTextureSize() affects layer property 267500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev DeviceInfo::initialize(); 2681bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck#endif 269500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev sp<RenderNode> node = new RenderNode(); 270500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (name) { 271500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev node->setName(name); 272500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 273500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev RenderProperties& props = node->mutateStagingProperties(); 274500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev props.setLeftTopRightBottom(left, top, right, bottom); 275500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (displayList) { 2762de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck node->setStagingDisplayList(displayList); 277500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 278500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev if (setup) { 279500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev std::unique_ptr<skiapipeline::SkiaRecordingCanvas> canvas( 2801bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck new skiapipeline::SkiaRecordingCanvas(nullptr, props.getWidth(), 2811bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck props.getHeight())); 282500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev setup(props, *canvas.get()); 2832de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck node->setStagingDisplayList(canvas->finishRecording()); 284500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 285500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev node->setPropertyFieldsDirty(0xFFFFFFFF); 286500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev TestUtils::syncHierarchyPropertiesAndDisplayList(node); 287500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev return node; 288500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev } 289500a0c30d4dcd012218c3e44a62926a1c34a259fStan Iliev 2908d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik /** 2918d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Forces a sync of a tree of RenderNode, such that every descendant will have its staging 2928d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * properties and DisplayList moved to the render copies. 2938d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * 2948d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * Note: does not check dirtiness bits, so any non-staging DisplayLists will be discarded. 2958d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik * For this reason, this should generally only be called once on a tree. 2968d1f2120fe80b23ab03c7168e3b6b2d13bafe2e7Chris Craik */ 297161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik static void syncHierarchyPropertiesAndDisplayList(sp<RenderNode>& node) { 298161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik syncHierarchyPropertiesAndDisplayListImpl(node.get()); 299b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik } 3000a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik 3019cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik static sp<RenderNode>& getSyncedNode(sp<RenderNode>& node) { 3029cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik syncHierarchyPropertiesAndDisplayList(node); 3039cd1bbe5c9e14472e631d8cc10005613925f34afChris Craik return node; 3047db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck } 3057db5ffb7dbd30202468459e2ef4426e91d4fcbb3John Reck 3060b7e8245db728d127ada698be63d78b33fc6e4daChris Craik typedef std::function<void(renderthread::RenderThread& thread)> RtCallback; 3070a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik 3080a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik class TestTask : public renderthread::RenderTask { 3090a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik public: 3101bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck explicit TestTask(RtCallback rtCallback) : rtCallback(rtCallback) {} 3110a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik virtual ~TestTask() {} 312e5da4ef971258193cd1e89737a12b95b6ac244bbJohn Reck virtual void run() override; 3130a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik RtCallback rtCallback; 3140a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik }; 3150a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik 3160a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik /** 3170a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik * NOTE: requires surfaceflinger to run, otherwise this method will wait indefinitely. 3180a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik */ 3190a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik static void runOnRenderThread(RtCallback rtCallback) { 3200a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik TestTask task(rtCallback); 3211bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck renderthread::RenderThread::getInstance().queue().runSync([&]() { task.run(); }); 3220a24b146cd3dacf372ce98424044423a5b2fbf2aChris Craik } 32316c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 3241bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static bool isRenderThreadRunning() { return renderthread::RenderThread::hasInstance(); } 32538e0c32852e3b9d8ca4a9d3791577f52536419cbJohn Reck 32616c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck static SkColor interpolateColor(float fraction, SkColor start, SkColor end); 32716c9d6a92e1b86d448c00c52a1630f3e71e6df76John Reck 328e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik static void layoutTextUnscaled(const SkPaint& paint, const char* text, 3291bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::vector<glyph_t>* outGlyphs, 3301bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck std::vector<float>* outPositions, float* outTotalAdvance, 3311bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck Rect* outBounds); 332e8c3c813b0e3ac98304b17a751ce6e436e252bd9Chris Craik 3331bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, float x, 3341bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck float y); 335a1717271caac5e8ea3808c331d4141ac01a42134Chris Craik 3361bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck static void drawUtf8ToCanvas(Canvas* canvas, const char* text, const SkPaint& paint, 3371bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const SkPath& path); 338d7448e65e243754f31890baef29dff187dc2e5e5Chris Craik 33979abbf22d4f672208327546661e694d837f564a9Derek Sollenberger static std::unique_ptr<uint16_t[]> asciiToUtf16(const char* str); 340dccca44ffda4836b56a21da95a046c9708ffd49csergeyv 341835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger class MockFunctor : public Functor { 3421bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck public: 3431bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck virtual status_t operator()(int what, void* data) { 3441bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck mLastMode = what; 3451bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck return DrawGlInfo::kStatusDone; 3461bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck } 3471bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int getLastMode() const { return mLastMode; } 3481bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck 3491bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck private: 3501bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck int mLastMode = -1; 3511bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck }; 352835b3a69c345d2b58a0774daeb2e717a8a878059Derek Sollenberger 353021693b967a2c5556dddd183eb0247df4079e1adStan Iliev static SkColor getColor(const sk_sp<SkSurface>& surface, int x, int y); 354021693b967a2c5556dddd183eb0247df4079e1adStan Iliev 35552771272f4f018f4fc6846224bf047497e784af1Stan Iliev static SkRect getClipBounds(const SkCanvas* canvas); 35652771272f4f018f4fc6846224bf047497e784af1Stan Iliev static SkRect getLocalClipBounds(const SkCanvas* canvas); 35752771272f4f018f4fc6846224bf047497e784af1Stan Iliev 358161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craikprivate: 359161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) { 3602de950d5a8b47c7b4648ada1b1260ce4b7342798John Reck MarkAndSweepRemoved observer(nullptr); 361161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik node->syncProperties(); 3623afd63778e401651a7a6fd721d6d795690916ab8John Reck if (node->mNeedsDisplayListSync) { 3633afd63778e401651a7a6fd721d6d795690916ab8John Reck node->mNeedsDisplayListSync = false; 3643afd63778e401651a7a6fd721d6d795690916ab8John Reck node->syncDisplayList(observer, nullptr); 3653afd63778e401651a7a6fd721d6d795690916ab8John Reck } 366161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik auto displayList = node->getDisplayList(); 367161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik if (displayList) { 36825912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev if (displayList->isSkiaDL()) { 36925912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev for (auto&& childDr : static_cast<skiapipeline::SkiaDisplayList*>( 3701bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck const_cast<DisplayList*>(displayList)) 3711bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck ->mChildNodes) { 37225912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev syncHierarchyPropertiesAndDisplayListImpl(childDr.getRenderNode()); 37325912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev } 37425912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev } else { 37525912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev for (auto&& childOp : displayList->getChildren()) { 37625912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev syncHierarchyPropertiesAndDisplayListImpl(childOp->renderNode); 37725912c78f5a5ab71a7c5f11426f34f505e6dbb0dStan Iliev } 378161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik } 379161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik } 380161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik } 381161f54b2d4160b8d3f3da9eba5746da5162e4821Chris Craik 3821bcacfdcab0eaa0cee92bd7f5a1b5e271dd68e52John Reck}; // class TestUtils 383b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik 384b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace uirenderer */ 385b565df13a9e5c7b1d7d93bdfa4a793752d66d3ccChris Craik} /* namespace android */ 386