blob: a224376c7e7746946fc8696cba2a6bc6666eb29d [file] [log] [blame]
John Reck94c40fe2014-10-08 09:28:43 -07001/*
2 * Copyright (C) 2014 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
John Reck94c40fe2014-10-08 09:28:43 -070017#include <cutils/log.h>
18#include <gui/Surface.h>
19#include <ui/PixelFormat.h>
20
21#include <AnimationContext.h>
Chris Craikdb663fe2015-04-20 13:34:45 -070022#include <DisplayListCanvas.h>
John Reck94c40fe2014-10-08 09:28:43 -070023#include <RenderNode.h>
24#include <renderthread/RenderProxy.h>
John Reck84e390c2015-01-05 09:42:52 -080025#include <renderthread/RenderTask.h>
John Reck94c40fe2014-10-08 09:28:43 -070026
27#include "TestContext.h"
28
John Reck7f2e5e32015-05-05 11:00:53 -070029#include <stdio.h>
30#include <unistd.h>
31
John Reck94c40fe2014-10-08 09:28:43 -070032using namespace android;
33using namespace android::uirenderer;
34using namespace android::uirenderer::renderthread;
John Reck84e390c2015-01-05 09:42:52 -080035using namespace android::uirenderer::test;
John Reck94c40fe2014-10-08 09:28:43 -070036
37class ContextFactory : public IContextFactory {
38public:
Chris Craikd41c4d82015-01-05 15:51:13 -080039 virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) override {
John Reck94c40fe2014-10-08 09:28:43 -070040 return new AnimationContext(clock);
41 }
42};
43
Chris Craikdb663fe2015-04-20 13:34:45 -070044static DisplayListCanvas* startRecording(RenderNode* node) {
Derek Sollenbergercc882b62015-07-09 15:51:20 -040045 DisplayListCanvas* renderer = new DisplayListCanvas(
46 node->stagingProperties().getWidth(), node->stagingProperties().getHeight());
John Reck94c40fe2014-10-08 09:28:43 -070047 return renderer;
48}
49
Chris Craikdb663fe2015-04-20 13:34:45 -070050static void endRecording(DisplayListCanvas* renderer, RenderNode* node) {
John Reck94c40fe2014-10-08 09:28:43 -070051 node->setStagingDisplayList(renderer->finishRecording());
52 delete renderer;
53}
54
Chris Craik03188872015-02-02 18:39:33 -080055class TreeContentAnimation {
56public:
57 virtual ~TreeContentAnimation() {}
Tim Murraybfbcd882015-05-06 12:38:05 -070058 int frameCount = 150;
59 virtual int getFrameCount() { return frameCount; }
60 virtual void setFrameCount(int fc) {
61 if (fc > 0) {
62 frameCount = fc;
63 }
64 }
Chris Craikdb663fe2015-04-20 13:34:45 -070065 virtual void createContent(int width, int height, DisplayListCanvas* renderer) = 0;
Chris Craik03188872015-02-02 18:39:33 -080066 virtual void doFrame(int frameNr) = 0;
John Reck94c40fe2014-10-08 09:28:43 -070067
Chris Craik03188872015-02-02 18:39:33 -080068 template <class T>
Tim Murraybfbcd882015-05-06 12:38:05 -070069 static void run(int frameCount) {
Chris Craik03188872015-02-02 18:39:33 -080070 T animation;
Tim Murraybfbcd882015-05-06 12:38:05 -070071 animation.setFrameCount(frameCount);
John Reck94c40fe2014-10-08 09:28:43 -070072
Chris Craik03188872015-02-02 18:39:33 -080073 TestContext testContext;
John Reck94c40fe2014-10-08 09:28:43 -070074
Chris Craik03188872015-02-02 18:39:33 -080075 // create the native surface
76 const int width = gDisplay.w;
77 const int height = gDisplay.h;
78 sp<Surface> surface = testContext.surface();
John Reck94c40fe2014-10-08 09:28:43 -070079
Chris Craik03188872015-02-02 18:39:33 -080080 RenderNode* rootNode = new RenderNode();
81 rootNode->incStrong(nullptr);
82 rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height);
83 rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
84 rootNode->mutateStagingProperties().setClipToBounds(false);
85 rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);
John Reck94c40fe2014-10-08 09:28:43 -070086
Chris Craik03188872015-02-02 18:39:33 -080087 ContextFactory factory;
88 std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode, &factory));
89 proxy->loadSystemProperties();
90 proxy->initialize(surface);
91 float lightX = width / 2.0;
Alan Viverette50210d92015-05-14 18:05:36 -070092 proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15);
93 proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
John Reck94c40fe2014-10-08 09:28:43 -070094
Chris Craik03188872015-02-02 18:39:33 -080095 android::uirenderer::Rect DUMMY;
John Reck94c40fe2014-10-08 09:28:43 -070096
Chris Craikdb663fe2015-04-20 13:34:45 -070097 DisplayListCanvas* renderer = startRecording(rootNode);
Chris Craik03188872015-02-02 18:39:33 -080098 animation.createContent(width, height, renderer);
99 endRecording(renderer, rootNode);
John Reck94c40fe2014-10-08 09:28:43 -0700100
John Reck7f2e5e32015-05-05 11:00:53 -0700101 // Do a few cold runs then reset the stats so that the caches are all hot
102 for (int i = 0; i < 3; i++) {
Chris Craik03188872015-02-02 18:39:33 -0800103 testContext.waitForVsync();
John Reck7f2e5e32015-05-05 11:00:53 -0700104 proxy->syncAndDrawFrame();
105 }
106 proxy->resetProfileInfo();
John Reck94c40fe2014-10-08 09:28:43 -0700107
John Reck7f2e5e32015-05-05 11:00:53 -0700108 for (int i = 0; i < animation.getFrameCount(); i++) {
109 testContext.waitForVsync();
110
Chris Craik03188872015-02-02 18:39:33 -0800111 ATRACE_NAME("UI-Draw Frame");
John Reck7f2e5e32015-05-05 11:00:53 -0700112 nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
113 UiFrameInfoBuilder(proxy->frameInfo())
114 .setVsync(vsync, vsync);
Chris Craik03188872015-02-02 18:39:33 -0800115 animation.doFrame(i);
John Reckba6adf62015-02-19 14:36:50 -0800116 proxy->syncAndDrawFrame();
John Reck94c40fe2014-10-08 09:28:43 -0700117 }
Chris Craik03188872015-02-02 18:39:33 -0800118
John Reck7f2e5e32015-05-05 11:00:53 -0700119 proxy->dumpProfileInfo(STDOUT_FILENO, 0);
Chris Craik03188872015-02-02 18:39:33 -0800120 rootNode->decStrong(nullptr);
John Reck94c40fe2014-10-08 09:28:43 -0700121 }
Chris Craik03188872015-02-02 18:39:33 -0800122};
John Reck94c40fe2014-10-08 09:28:43 -0700123
Chris Craik03188872015-02-02 18:39:33 -0800124class ShadowGridAnimation : public TreeContentAnimation {
125public:
126 std::vector< sp<RenderNode> > cards;
Chris Craikdb663fe2015-04-20 13:34:45 -0700127 void createContent(int width, int height, DisplayListCanvas* renderer) override {
Chris Craik03188872015-02-02 18:39:33 -0800128 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
129 renderer->insertReorderBarrier(true);
John Reck84e390c2015-01-05 09:42:52 -0800130
Chris Craik03188872015-02-02 18:39:33 -0800131 for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
132 for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
133 sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
Chris Craik956f3402015-04-27 16:41:00 -0700134 renderer->drawRenderNode(card.get());
Chris Craik03188872015-02-02 18:39:33 -0800135 cards.push_back(card);
136 }
137 }
138
139 renderer->insertReorderBarrier(false);
140 }
141 void doFrame(int frameNr) override {
Tim Murraybfbcd882015-05-06 12:38:05 -0700142 int curFrame = frameNr % 150;
Andreas Gampe2ab82982014-11-21 14:19:06 -0800143 for (size_t ci = 0; ci < cards.size(); ci++) {
Tim Murraybfbcd882015-05-06 12:38:05 -0700144 cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
145 cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
John Reck94c40fe2014-10-08 09:28:43 -0700146 cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
147 }
John Reck94c40fe2014-10-08 09:28:43 -0700148 }
Chris Craik03188872015-02-02 18:39:33 -0800149private:
150 sp<RenderNode> createCard(int x, int y, int width, int height) {
151 sp<RenderNode> node = new RenderNode();
152 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
153 node->mutateStagingProperties().setElevation(dp(16));
154 node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
155 node->mutateStagingProperties().mutableOutline().setShouldClip(true);
156 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
John Reck94c40fe2014-10-08 09:28:43 -0700157
Chris Craikdb663fe2015-04-20 13:34:45 -0700158 DisplayListCanvas* renderer = startRecording(node.get());
Chris Craik03188872015-02-02 18:39:33 -0800159 renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
160 endRecording(renderer, node.get());
161 return node;
162 }
163};
John Reck94c40fe2014-10-08 09:28:43 -0700164
Tim Murraybfbcd882015-05-06 12:38:05 -0700165class ShadowGrid2Animation : public TreeContentAnimation {
166public:
167 std::vector< sp<RenderNode> > cards;
168 void createContent(int width, int height, DisplayListCanvas* renderer) override {
169 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
170 renderer->insertReorderBarrier(true);
171
172 for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
173 for (int y = dp(8); y < (height - dp(58)); y += dp(58)) {
174 sp<RenderNode> card = createCard(x, y, dp(50), dp(50));
175 renderer->drawRenderNode(card.get());
176 cards.push_back(card);
177 }
178 }
179
180 renderer->insertReorderBarrier(false);
181 }
182 void doFrame(int frameNr) override {
183 int curFrame = frameNr % 150;
184 for (size_t ci = 0; ci < cards.size(); ci++) {
185 cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
186 cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
187 cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
188 }
189 }
190private:
191 sp<RenderNode> createCard(int x, int y, int width, int height) {
192 sp<RenderNode> node = new RenderNode();
193 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
194 node->mutateStagingProperties().setElevation(dp(16));
195 node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
196 node->mutateStagingProperties().mutableOutline().setShouldClip(true);
197 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
198
199 DisplayListCanvas* renderer = startRecording(node.get());
200 renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
201 endRecording(renderer, node.get());
202 return node;
203 }
204};
205
Chris Craik03188872015-02-02 18:39:33 -0800206class RectGridAnimation : public TreeContentAnimation {
207public:
208 sp<RenderNode> card;
Chris Craikdb663fe2015-04-20 13:34:45 -0700209 void createContent(int width, int height, DisplayListCanvas* renderer) override {
Chris Craik03188872015-02-02 18:39:33 -0800210 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
211 renderer->insertReorderBarrier(true);
212
213 card = createCard(40, 40, 200, 200);
Chris Craik956f3402015-04-27 16:41:00 -0700214 renderer->drawRenderNode(card.get());
Chris Craik03188872015-02-02 18:39:33 -0800215
216 renderer->insertReorderBarrier(false);
217 }
218 void doFrame(int frameNr) override {
Tim Murraybfbcd882015-05-06 12:38:05 -0700219 int curFrame = frameNr % 150;
220 card->mutateStagingProperties().setTranslationX(curFrame);
221 card->mutateStagingProperties().setTranslationY(curFrame);
Chris Craik03188872015-02-02 18:39:33 -0800222 card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
223 }
224private:
225 sp<RenderNode> createCard(int x, int y, int width, int height) {
226 sp<RenderNode> node = new RenderNode();
227 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
228 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
229
Chris Craikdb663fe2015-04-20 13:34:45 -0700230 DisplayListCanvas* renderer = startRecording(node.get());
Chris Craik03188872015-02-02 18:39:33 -0800231 renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
232
Derek Sollenberger94394b32015-07-10 09:58:41 -0400233 SkRegion region;
Chris Craik03188872015-02-02 18:39:33 -0800234 float rects[width * height];
235 int index = 0;
236 for (int xOffset = 0; xOffset < width; xOffset+=2) {
237 for (int yOffset = 0; yOffset < height; yOffset+=2) {
Derek Sollenberger94394b32015-07-10 09:58:41 -0400238 region.op(xOffset, yOffset, xOffset + 1, yOffset + 1, SkRegion::kUnion_Op);
Chris Craik03188872015-02-02 18:39:33 -0800239 }
240 }
241 int count = width * height;
242
243 SkPaint paint;
244 paint.setColor(0xff00ffff);
Derek Sollenberger94394b32015-07-10 09:58:41 -0400245 renderer->drawRegion(region, paint);
Chris Craik03188872015-02-02 18:39:33 -0800246
247 endRecording(renderer, node.get());
248 return node;
249 }
250};
251
Chris Craik117bdbc2015-02-05 10:12:38 -0800252class OvalAnimation : public TreeContentAnimation {
253public:
254 sp<RenderNode> card;
Chris Craikdb663fe2015-04-20 13:34:45 -0700255 void createContent(int width, int height, DisplayListCanvas* renderer) override {
Chris Craik117bdbc2015-02-05 10:12:38 -0800256 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
257 renderer->insertReorderBarrier(true);
258
Chris Craik08fa43f2015-02-09 18:58:32 -0800259 card = createCard(40, 40, 400, 400);
Chris Craik956f3402015-04-27 16:41:00 -0700260 renderer->drawRenderNode(card.get());
Chris Craik117bdbc2015-02-05 10:12:38 -0800261
262 renderer->insertReorderBarrier(false);
263 }
264
265 void doFrame(int frameNr) override {
Tim Murraybfbcd882015-05-06 12:38:05 -0700266 int curFrame = frameNr % 150;
267 card->mutateStagingProperties().setTranslationX(curFrame);
268 card->mutateStagingProperties().setTranslationY(curFrame);
Chris Craik117bdbc2015-02-05 10:12:38 -0800269 card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
270 }
271private:
272 sp<RenderNode> createCard(int x, int y, int width, int height) {
273 sp<RenderNode> node = new RenderNode();
274 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
275 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
276
Chris Craikdb663fe2015-04-20 13:34:45 -0700277 DisplayListCanvas* renderer = startRecording(node.get());
Chris Craik117bdbc2015-02-05 10:12:38 -0800278
279 SkPaint paint;
280 paint.setAntiAlias(true);
Chris Craik08fa43f2015-02-09 18:58:32 -0800281 paint.setColor(0xFF000000);
Chris Craik117bdbc2015-02-05 10:12:38 -0800282 renderer->drawOval(0, 0, width, height, paint);
283
284 endRecording(renderer, node.get());
285 return node;
286 }
287};
288
Chris Craik03188872015-02-02 18:39:33 -0800289struct cstr_cmp {
290 bool operator()(const char *a, const char *b) const {
291 return std::strcmp(a, b) < 0;
292 }
293};
294
Tim Murraybfbcd882015-05-06 12:38:05 -0700295typedef void (*testProc)(int);
Chris Craik03188872015-02-02 18:39:33 -0800296
297std::map<const char*, testProc, cstr_cmp> gTestMap {
298 {"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
Tim Murraybfbcd882015-05-06 12:38:05 -0700299 {"shadowgrid2", TreeContentAnimation::run<ShadowGrid2Animation>},
Chris Craik03188872015-02-02 18:39:33 -0800300 {"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
Chris Craik117bdbc2015-02-05 10:12:38 -0800301 {"oval", TreeContentAnimation::run<OvalAnimation> },
Chris Craik03188872015-02-02 18:39:33 -0800302};
303
304int main(int argc, char* argv[]) {
305 const char* testName = argc > 1 ? argv[1] : "shadowgrid";
306 testProc proc = gTestMap[testName];
307 if(!proc) {
308 printf("Error: couldn't find test %s\n", testName);
309 return 1;
310 }
Tim Murray1a0f1c72015-05-06 11:37:37 -0700311 int loopCount = 1;
312 if (argc > 2) {
313 loopCount = atoi(argv[2]);
314 if (!loopCount) {
315 printf("Invalid loop count!\n");
316 return 1;
317 }
318 }
Tim Murraybfbcd882015-05-06 12:38:05 -0700319 int frameCount = 150;
320 if (argc > 3) {
321 frameCount = atoi(argv[3]);
322 if (frameCount < 1) {
323 printf("Invalid frame count!\n");
324 return 1;
325 }
326 }
Tim Murray1a0f1c72015-05-06 11:37:37 -0700327 if (loopCount < 0) {
328 loopCount = INT_MAX;
329 }
330 for (int i = 0; i < loopCount; i++) {
Tim Murraybfbcd882015-05-06 12:38:05 -0700331 proc(frameCount);
Tim Murray1a0f1c72015-05-06 11:37:37 -0700332 }
John Reck94c40fe2014-10-08 09:28:43 -0700333 printf("Success!\n");
334 return 0;
335}