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 
17 #include "AnimationContext.h"
18 #include "RenderNode.h"
19 #include "tests/common/TestContext.h"
20 #include "tests/common/TestScene.h"
21 #include "tests/common/scenes/TestSceneBase.h"
22 #include "renderthread/RenderProxy.h"
23 #include "renderthread/RenderTask.h"
24 
25 #include <cutils/log.h>
26 #include <gui/Surface.h>
27 #include <ui/PixelFormat.h>
28 
29 using namespace android;
30 using namespace android::uirenderer;
31 using namespace android::uirenderer::renderthread;
32 using namespace android::uirenderer::test;
33 
34 class ContextFactory : public IContextFactory {
35 public:
createAnimationContext(renderthread::TimeLord & clock)36     virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
37         return new AnimationContext(clock);
38     }
39 };
40 
41 template<class T>
42 class ModifiedMovingAverage {
43 public:
ModifiedMovingAverage(int weight)44     ModifiedMovingAverage(int weight) : mWeight(weight) {}
45 
add(T today)46     T add(T today) {
47         if (!mHasValue) {
48             mAverage = today;
49         } else {
50             mAverage = (((mWeight - 1) * mAverage) + today) / mWeight;
51         }
52         return mAverage;
53     }
54 
average()55     T average() {
56         return mAverage;
57     }
58 
59 private:
60     bool mHasValue = false;
61     int mWeight;
62     T mAverage;
63 };
64 
run(const TestScene::Info & info,const TestScene::Options & opts)65 void run(const TestScene::Info& info, const TestScene::Options& opts) {
66     // Switch to the real display
67     gDisplay = getBuiltInDisplay();
68 
69     std::unique_ptr<TestScene> scene(info.createScene(opts));
70 
71     TestContext testContext;
72 
73     // create the native surface
74     const int width = gDisplay.w;
75     const int height = gDisplay.h;
76     sp<Surface> surface = testContext.surface();
77 
78     sp<RenderNode> rootNode = TestUtils::createNode(0, 0, width, height,
79             [&scene, width, height](RenderProperties& props, TestCanvas& canvas) {
80         props.setClipToBounds(false);
81         scene->createContent(width, height, canvas);
82     });
83 
84     ContextFactory factory;
85     std::unique_ptr<RenderProxy> proxy(new RenderProxy(false,
86             rootNode.get(), &factory));
87     proxy->loadSystemProperties();
88     proxy->initialize(surface);
89     float lightX = width / 2.0;
90     proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15);
91     proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
92 
93     // Do a few cold runs then reset the stats so that the caches are all hot
94     for (int i = 0; i < 5; i++) {
95         testContext.waitForVsync();
96         nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
97         UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
98         proxy->syncAndDrawFrame(nullptr);
99     }
100 
101     proxy->resetProfileInfo();
102     proxy->fence();
103 
104     ModifiedMovingAverage<double> avgMs(opts.reportFrametimeWeight);
105 
106     for (int i = 0; i < opts.count; i++) {
107         testContext.waitForVsync();
108         nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
109         {
110             ATRACE_NAME("UI-Draw Frame");
111             UiFrameInfoBuilder(proxy->frameInfo()).setVsync(vsync, vsync);
112             scene->doFrame(i);
113             proxy->syncAndDrawFrame(nullptr);
114         }
115         if (opts.reportFrametimeWeight) {
116             proxy->fence();
117             nsecs_t done = systemTime(CLOCK_MONOTONIC);
118             avgMs.add((done - vsync) / 1000000.0);
119             if (i % 10 == 9) {
120                 printf("Average frametime %.3fms\n", avgMs.average());
121             }
122         }
123     }
124 
125     proxy->dumpProfileInfo(STDOUT_FILENO, DumpFlags::JankStats);
126 }
127