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 "BakedOpDispatcher.h" 20 #include "BakedOpRenderer.h" 21 #include "BakedOpState.h" 22 #include "FrameBuilder.h" 23 #include "LayerUpdateQueue.h" 24 #include "RecordedOp.h" 25 #include "RecordingCanvas.h" 26 #include "Vector.h" 27 #include "tests/common/TestContext.h" 28 #include "tests/common/TestScene.h" 29 #include "tests/common/TestUtils.h" 30 31 #include <vector> 32 33 using namespace android; 34 using namespace android::uirenderer; 35 using namespace android::uirenderer::renderthread; 36 using namespace android::uirenderer::test; 37 38 const FrameBuilder::LightGeometry sLightGeometry = {{100, 100, 100}, 50}; 39 const BakedOpRenderer::LightInfo sLightInfo = {128, 128}; 40 41 static sp<RenderNode> createTestNode() { 42 auto node = TestUtils::createNode<RecordingCanvas>( 43 0, 0, 200, 200, [](RenderProperties& props, RecordingCanvas& canvas) { 44 sk_sp<Bitmap> bitmap(TestUtils::createBitmap(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 61 void 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, sLightGeometry, 66 Caches::getInstance()); 67 frameBuilder.deferRenderNode(*node); 68 benchmark::DoNotOptimize(&frameBuilder); 69 } 70 }); 71 } 72 BENCHMARK(BM_FrameBuilder_defer); 73 74 void 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, sLightGeometry, caches); 83 frameBuilder.deferRenderNode(*node); 84 85 BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo); 86 frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 87 benchmark::DoNotOptimize(&renderer); 88 } 89 }); 90 } 91 BENCHMARK(BM_FrameBuilder_deferAndRender); 92 93 static sp<RenderNode> getSyncedSceneNode(const char* sceneName) { 94 gDisplay = getBuiltInDisplay(); // switch to real display if present 95 96 TestContext testContext; 97 TestScene::Options opts; 98 std::unique_ptr<TestScene> scene(TestScene::testMap()[sceneName].createScene(opts)); 99 100 sp<RenderNode> rootNode = TestUtils::createNode<RecordingCanvas>( 101 0, 0, gDisplay.w, gDisplay.h, 102 [&scene](RenderProperties& props, RecordingCanvas& canvas) { 103 scene->createContent(gDisplay.w, gDisplay.h, canvas); 104 }); 105 106 TestUtils::syncHierarchyPropertiesAndDisplayList(rootNode); 107 return rootNode; 108 } 109 110 static auto SCENES = { 111 "listview", 112 }; 113 114 void BM_FrameBuilder_defer_scene(benchmark::State& state) { 115 TestUtils::runOnRenderThread([&state](RenderThread& thread) { 116 const char* sceneName = *(SCENES.begin() + state.range(0)); 117 state.SetLabel(sceneName); 118 auto node = getSyncedSceneNode(sceneName); 119 while (state.KeepRunning()) { 120 FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, 121 gDisplay.h, sLightGeometry, Caches::getInstance()); 122 frameBuilder.deferRenderNode(*node); 123 benchmark::DoNotOptimize(&frameBuilder); 124 } 125 }); 126 } 127 BENCHMARK(BM_FrameBuilder_defer_scene)->DenseRange(0, SCENES.size() - 1); 128 129 void BM_FrameBuilder_deferAndRender_scene(benchmark::State& state) { 130 TestUtils::runOnRenderThread([&state](RenderThread& thread) { 131 const char* sceneName = *(SCENES.begin() + state.range(0)); 132 state.SetLabel(sceneName); 133 auto node = getSyncedSceneNode(sceneName); 134 135 RenderState& renderState = thread.renderState(); 136 Caches& caches = Caches::getInstance(); 137 138 while (state.KeepRunning()) { 139 FrameBuilder frameBuilder(SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, 140 gDisplay.h, sLightGeometry, Caches::getInstance()); 141 frameBuilder.deferRenderNode(*node); 142 143 BakedOpRenderer renderer(caches, renderState, true, false, sLightInfo); 144 frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer); 145 benchmark::DoNotOptimize(&renderer); 146 } 147 }); 148 } 149 BENCHMARK(BM_FrameBuilder_deferAndRender_scene)->DenseRange(0, SCENES.size() - 1); 150