1/* 2 * Copyright (C) 2016 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 17#include <benchmark/benchmark.h> 18 19#include "BakedOpState.h" 20#include "BakedOpDispatcher.h" 21#include "BakedOpRenderer.h" 22#include "FrameBuilder.h" 23#include "LayerUpdateQueue.h" 24#include "RecordedOp.h" 25#include "RecordingCanvas.h" 26#include "tests/common/TestContext.h" 27#include "tests/common/TestScene.h" 28#include "tests/common/TestUtils.h" 29#include "Vector.h" 30 31#include <vector> 32 33using namespace android; 34using namespace android::uirenderer; 35using namespace android::uirenderer::renderthread; 36using namespace android::uirenderer::test; 37 38const FrameBuilder::LightGeometry sLightGeometry = { {100, 100, 100}, 50}; 39const BakedOpRenderer::LightInfo sLightInfo = { 128, 128 }; 40 41static sp<RenderNode> createTestNode() { 42 auto node = TestUtils::createNode(0, 0, 200, 200, 43 [](RenderProperties& props, RecordingCanvas& canvas) { 44 SkBitmap bitmap = TestUtils::createSkBitmap(10, 10); 45 SkPaint paint; 46 47 // Alternate between drawing rects and bitmaps, with bitmaps overlapping rects. 48 // Rects don't overlap bitmaps, so bitmaps should be brought to front as a group. 49 canvas.save(SaveFlags::MatrixClip); 50 for (int i = 0; i < 30; i++) { 51 canvas.translate(0, 10); 52 canvas.drawRect(0, 0, 10, 10, paint); 53 canvas.drawBitmap(bitmap, 5, 0, nullptr); 54 } 55 canvas.restore(); 56 }); 57 TestUtils::syncHierarchyPropertiesAndDisplayList(node); 58 return node; 59} 60 61void BM_FrameBuilder_defer(benchmark::State& state) { 62 TestUtils::runOnRenderThread([&state](RenderThread& thread) { 63 auto node = createTestNode(); 64 while (state.KeepRunning()) { 65 FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 66 sLightGeometry, Caches::getInstance()); 67 frameBuilder.deferRenderNode(*node); 68 benchmark::DoNotOptimize(&frameBuilder); 69 } 70 }); 71} 72BENCHMARK(BM_FrameBuilder_defer); 73 74void BM_FrameBuilder_deferAndRender(benchmark::State& state) { 75 TestUtils::runOnRenderThread([&state](RenderThread& thread) { 76 auto node = createTestNode(); 77 78 RenderState& renderState = thread.renderState(); 79 Caches& caches = Caches::getInstance(); 80 81 while (state.KeepRunning()) { 82 FrameBuilder frameBuilder(SkRect::MakeWH(100, 200), 100, 200, 83 sLightGeometry, caches); 84 frameBuilder.deferRenderNode(*node); 85 86 BakedOpRenderer renderer(caches, renderState, true, sLightInfo); 87 frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 88 benchmark::DoNotOptimize(&renderer); 89 } 90 }); 91} 92BENCHMARK(BM_FrameBuilder_deferAndRender); 93 94static sp<RenderNode> getSyncedSceneNode(const char* sceneName) { 95 gDisplay = getBuiltInDisplay(); // switch to real display if present 96 97 TestContext testContext; 98 TestScene::Options opts; 99 std::unique_ptr<TestScene> scene(TestScene::testMap()[sceneName].createScene(opts)); 100 101 sp<RenderNode> rootNode = TestUtils::createNode(0, 0, gDisplay.w, gDisplay.h, 102 [&scene](RenderProperties& props, TestCanvas& canvas) { 103 scene->createContent(gDisplay.w, gDisplay.h, canvas); 104 }); 105 106 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode); 107 return rootNode; 108} 109 110static auto SCENES = { 111 "listview", 112}; 113 114void BM_FrameBuilder_defer_scene(benchmark::State& state) { 115 TestUtils::runOnRenderThread([&state](RenderThread& thread) { 116 const char* sceneName = *(SCENES.begin() + state.range_x()); 117 state.SetLabel(sceneName); 118 auto node = getSyncedSceneNode(sceneName); 119 while (state.KeepRunning()) { 120 FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), 121 gDisplay.w, gDisplay.h, 122 sLightGeometry, Caches::getInstance()); 123 frameBuilder.deferRenderNode(*node); 124 benchmark::DoNotOptimize(&frameBuilder); 125 } 126 }); 127} 128BENCHMARK(BM_FrameBuilder_defer_scene)->DenseRange(0, SCENES.size() - 1); 129 130void BM_FrameBuilder_deferAndRender_scene(benchmark::State& state) { 131 TestUtils::runOnRenderThread([&state](RenderThread& thread) { 132 const char* sceneName = *(SCENES.begin() + state.range_x()); 133 state.SetLabel(sceneName); 134 auto node = getSyncedSceneNode(sceneName); 135 136 RenderState& renderState = thread.renderState(); 137 Caches& caches = Caches::getInstance(); 138 139 while (state.KeepRunning()) { 140 FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), 141 gDisplay.w, gDisplay.h, 142 sLightGeometry, Caches::getInstance()); 143 frameBuilder.deferRenderNode(*node); 144 145 BakedOpRenderer renderer(caches, renderState, true, sLightInfo); 146 frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 147 benchmark::DoNotOptimize(&renderer); 148 } 149 }); 150} 151BENCHMARK(BM_FrameBuilder_deferAndRender_scene)->DenseRange(0, SCENES.size() - 1); 152