blob: ceee953ef7c2643a4863d46d28deaab1a0193269 [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) {
45 DisplayListCanvas* renderer = new DisplayListCanvas();
Chris Craik03188872015-02-02 18:39:33 -080046 renderer->setViewport(node->stagingProperties().getWidth(),
47 node->stagingProperties().getHeight());
Tom Hudson8dfaa492014-12-09 15:03:44 -050048 renderer->prepare();
John Reck94c40fe2014-10-08 09:28:43 -070049 return renderer;
50}
51
Chris Craikdb663fe2015-04-20 13:34:45 -070052static void endRecording(DisplayListCanvas* renderer, RenderNode* node) {
John Reck94c40fe2014-10-08 09:28:43 -070053 renderer->finish();
54 node->setStagingDisplayList(renderer->finishRecording());
55 delete renderer;
56}
57
Chris Craik03188872015-02-02 18:39:33 -080058class TreeContentAnimation {
59public:
60 virtual ~TreeContentAnimation() {}
Tim Murraybfbcd882015-05-06 12:38:05 -070061 int frameCount = 150;
62 virtual int getFrameCount() { return frameCount; }
63 virtual void setFrameCount(int fc) {
64 if (fc > 0) {
65 frameCount = fc;
66 }
67 }
Chris Craikdb663fe2015-04-20 13:34:45 -070068 virtual void createContent(int width, int height, DisplayListCanvas* renderer) = 0;
Chris Craik03188872015-02-02 18:39:33 -080069 virtual void doFrame(int frameNr) = 0;
John Reck94c40fe2014-10-08 09:28:43 -070070
Chris Craik03188872015-02-02 18:39:33 -080071 template <class T>
Tim Murraybfbcd882015-05-06 12:38:05 -070072 static void run(int frameCount) {
Chris Craik03188872015-02-02 18:39:33 -080073 T animation;
Tim Murraybfbcd882015-05-06 12:38:05 -070074 animation.setFrameCount(frameCount);
John Reck94c40fe2014-10-08 09:28:43 -070075
Chris Craik03188872015-02-02 18:39:33 -080076 TestContext testContext;
John Reck94c40fe2014-10-08 09:28:43 -070077
Chris Craik03188872015-02-02 18:39:33 -080078 // create the native surface
79 const int width = gDisplay.w;
80 const int height = gDisplay.h;
81 sp<Surface> surface = testContext.surface();
John Reck94c40fe2014-10-08 09:28:43 -070082
Chris Craik03188872015-02-02 18:39:33 -080083 RenderNode* rootNode = new RenderNode();
84 rootNode->incStrong(nullptr);
85 rootNode->mutateStagingProperties().setLeftTopRightBottom(0, 0, width, height);
86 rootNode->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
87 rootNode->mutateStagingProperties().setClipToBounds(false);
88 rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);
John Reck94c40fe2014-10-08 09:28:43 -070089
Chris Craik03188872015-02-02 18:39:33 -080090 ContextFactory factory;
91 std::unique_ptr<RenderProxy> proxy(new RenderProxy(false, rootNode, &factory));
92 proxy->loadSystemProperties();
93 proxy->initialize(surface);
94 float lightX = width / 2.0;
Alan Viverette50210d92015-05-14 18:05:36 -070095 proxy->setup(width, height, dp(800.0f), 255 * 0.075, 255 * 0.15);
96 proxy->setLightCenter((Vector3){lightX, dp(-200.0f), dp(800.0f)});
John Reck94c40fe2014-10-08 09:28:43 -070097
Chris Craik03188872015-02-02 18:39:33 -080098 android::uirenderer::Rect DUMMY;
John Reck94c40fe2014-10-08 09:28:43 -070099
Chris Craikdb663fe2015-04-20 13:34:45 -0700100 DisplayListCanvas* renderer = startRecording(rootNode);
Chris Craik03188872015-02-02 18:39:33 -0800101 animation.createContent(width, height, renderer);
102 endRecording(renderer, rootNode);
John Reck94c40fe2014-10-08 09:28:43 -0700103
John Reck7f2e5e32015-05-05 11:00:53 -0700104 // Do a few cold runs then reset the stats so that the caches are all hot
105 for (int i = 0; i < 3; i++) {
Chris Craik03188872015-02-02 18:39:33 -0800106 testContext.waitForVsync();
John Reck7f2e5e32015-05-05 11:00:53 -0700107 proxy->syncAndDrawFrame();
108 }
109 proxy->resetProfileInfo();
John Reck94c40fe2014-10-08 09:28:43 -0700110
John Reck7f2e5e32015-05-05 11:00:53 -0700111 for (int i = 0; i < animation.getFrameCount(); i++) {
112 testContext.waitForVsync();
113
114 // workaround b/20853441
115 proxy->fence();
Chris Craik03188872015-02-02 18:39:33 -0800116 ATRACE_NAME("UI-Draw Frame");
John Reck7f2e5e32015-05-05 11:00:53 -0700117 nsecs_t vsync = systemTime(CLOCK_MONOTONIC);
118 UiFrameInfoBuilder(proxy->frameInfo())
119 .setVsync(vsync, vsync);
Chris Craik03188872015-02-02 18:39:33 -0800120 animation.doFrame(i);
John Reckba6adf62015-02-19 14:36:50 -0800121 proxy->syncAndDrawFrame();
John Reck94c40fe2014-10-08 09:28:43 -0700122 }
Chris Craik03188872015-02-02 18:39:33 -0800123
John Reck7f2e5e32015-05-05 11:00:53 -0700124 proxy->dumpProfileInfo(STDOUT_FILENO, 0);
Chris Craik03188872015-02-02 18:39:33 -0800125 rootNode->decStrong(nullptr);
John Reck94c40fe2014-10-08 09:28:43 -0700126 }
Chris Craik03188872015-02-02 18:39:33 -0800127};
John Reck94c40fe2014-10-08 09:28:43 -0700128
Chris Craik03188872015-02-02 18:39:33 -0800129class ShadowGridAnimation : public TreeContentAnimation {
130public:
131 std::vector< sp<RenderNode> > cards;
Chris Craikdb663fe2015-04-20 13:34:45 -0700132 void createContent(int width, int height, DisplayListCanvas* renderer) override {
Chris Craik03188872015-02-02 18:39:33 -0800133 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
134 renderer->insertReorderBarrier(true);
John Reck84e390c2015-01-05 09:42:52 -0800135
Chris Craik03188872015-02-02 18:39:33 -0800136 for (int x = dp(16); x < (width - dp(116)); x += dp(116)) {
137 for (int y = dp(16); y < (height - dp(116)); y += dp(116)) {
138 sp<RenderNode> card = createCard(x, y, dp(100), dp(100));
Chris Craik956f3402015-04-27 16:41:00 -0700139 renderer->drawRenderNode(card.get());
Chris Craik03188872015-02-02 18:39:33 -0800140 cards.push_back(card);
141 }
142 }
143
144 renderer->insertReorderBarrier(false);
145 }
146 void doFrame(int frameNr) override {
Tim Murraybfbcd882015-05-06 12:38:05 -0700147 int curFrame = frameNr % 150;
Andreas Gampe2ab82982014-11-21 14:19:06 -0800148 for (size_t ci = 0; ci < cards.size(); ci++) {
Tim Murraybfbcd882015-05-06 12:38:05 -0700149 cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
150 cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
John Reck94c40fe2014-10-08 09:28:43 -0700151 cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
152 }
John Reck94c40fe2014-10-08 09:28:43 -0700153 }
Chris Craik03188872015-02-02 18:39:33 -0800154private:
155 sp<RenderNode> createCard(int x, int y, int width, int height) {
156 sp<RenderNode> node = new RenderNode();
157 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
158 node->mutateStagingProperties().setElevation(dp(16));
159 node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(10), 1);
160 node->mutateStagingProperties().mutableOutline().setShouldClip(true);
161 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
John Reck94c40fe2014-10-08 09:28:43 -0700162
Chris Craikdb663fe2015-04-20 13:34:45 -0700163 DisplayListCanvas* renderer = startRecording(node.get());
Chris Craik03188872015-02-02 18:39:33 -0800164 renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
165 endRecording(renderer, node.get());
166 return node;
167 }
168};
John Reck94c40fe2014-10-08 09:28:43 -0700169
Tim Murraybfbcd882015-05-06 12:38:05 -0700170class ShadowGrid2Animation : public TreeContentAnimation {
171public:
172 std::vector< sp<RenderNode> > cards;
173 void createContent(int width, int height, DisplayListCanvas* renderer) override {
174 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
175 renderer->insertReorderBarrier(true);
176
177 for (int x = dp(8); x < (width - dp(58)); x += dp(58)) {
178 for (int y = dp(8); y < (height - dp(58)); y += dp(58)) {
179 sp<RenderNode> card = createCard(x, y, dp(50), dp(50));
180 renderer->drawRenderNode(card.get());
181 cards.push_back(card);
182 }
183 }
184
185 renderer->insertReorderBarrier(false);
186 }
187 void doFrame(int frameNr) override {
188 int curFrame = frameNr % 150;
189 for (size_t ci = 0; ci < cards.size(); ci++) {
190 cards[ci]->mutateStagingProperties().setTranslationX(curFrame);
191 cards[ci]->mutateStagingProperties().setTranslationY(curFrame);
192 cards[ci]->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
193 }
194 }
195private:
196 sp<RenderNode> createCard(int x, int y, int width, int height) {
197 sp<RenderNode> node = new RenderNode();
198 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
199 node->mutateStagingProperties().setElevation(dp(16));
200 node->mutateStagingProperties().mutableOutline().setRoundRect(0, 0, width, height, dp(6), 1);
201 node->mutateStagingProperties().mutableOutline().setShouldClip(true);
202 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y | RenderNode::Z);
203
204 DisplayListCanvas* renderer = startRecording(node.get());
205 renderer->drawColor(0xFFEEEEEE, SkXfermode::kSrcOver_Mode);
206 endRecording(renderer, node.get());
207 return node;
208 }
209};
210
Chris Craik03188872015-02-02 18:39:33 -0800211class RectGridAnimation : public TreeContentAnimation {
212public:
213 sp<RenderNode> card;
Chris Craikdb663fe2015-04-20 13:34:45 -0700214 void createContent(int width, int height, DisplayListCanvas* renderer) override {
Chris Craik03188872015-02-02 18:39:33 -0800215 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
216 renderer->insertReorderBarrier(true);
217
218 card = createCard(40, 40, 200, 200);
Chris Craik956f3402015-04-27 16:41:00 -0700219 renderer->drawRenderNode(card.get());
Chris Craik03188872015-02-02 18:39:33 -0800220
221 renderer->insertReorderBarrier(false);
222 }
223 void doFrame(int frameNr) override {
Tim Murraybfbcd882015-05-06 12:38:05 -0700224 int curFrame = frameNr % 150;
225 card->mutateStagingProperties().setTranslationX(curFrame);
226 card->mutateStagingProperties().setTranslationY(curFrame);
Chris Craik03188872015-02-02 18:39:33 -0800227 card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
228 }
229private:
230 sp<RenderNode> createCard(int x, int y, int width, int height) {
231 sp<RenderNode> node = new RenderNode();
232 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
233 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
234
Chris Craikdb663fe2015-04-20 13:34:45 -0700235 DisplayListCanvas* renderer = startRecording(node.get());
Chris Craik03188872015-02-02 18:39:33 -0800236 renderer->drawColor(0xFFFF00FF, SkXfermode::kSrcOver_Mode);
237
238 float rects[width * height];
239 int index = 0;
240 for (int xOffset = 0; xOffset < width; xOffset+=2) {
241 for (int yOffset = 0; yOffset < height; yOffset+=2) {
242 rects[index++] = xOffset;
243 rects[index++] = yOffset;
244 rects[index++] = xOffset + 1;
245 rects[index++] = yOffset + 1;
246 }
247 }
248 int count = width * height;
249
250 SkPaint paint;
251 paint.setColor(0xff00ffff);
252 renderer->drawRects(rects, count, &paint);
253
254 endRecording(renderer, node.get());
255 return node;
256 }
257};
258
Chris Craik117bdbc2015-02-05 10:12:38 -0800259class OvalAnimation : public TreeContentAnimation {
260public:
261 sp<RenderNode> card;
Chris Craikdb663fe2015-04-20 13:34:45 -0700262 void createContent(int width, int height, DisplayListCanvas* renderer) override {
Chris Craik117bdbc2015-02-05 10:12:38 -0800263 renderer->drawColor(0xFFFFFFFF, SkXfermode::kSrcOver_Mode);
264 renderer->insertReorderBarrier(true);
265
Chris Craik08fa43f2015-02-09 18:58:32 -0800266 card = createCard(40, 40, 400, 400);
Chris Craik956f3402015-04-27 16:41:00 -0700267 renderer->drawRenderNode(card.get());
Chris Craik117bdbc2015-02-05 10:12:38 -0800268
269 renderer->insertReorderBarrier(false);
270 }
271
272 void doFrame(int frameNr) override {
Tim Murraybfbcd882015-05-06 12:38:05 -0700273 int curFrame = frameNr % 150;
274 card->mutateStagingProperties().setTranslationX(curFrame);
275 card->mutateStagingProperties().setTranslationY(curFrame);
Chris Craik117bdbc2015-02-05 10:12:38 -0800276 card->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
277 }
278private:
279 sp<RenderNode> createCard(int x, int y, int width, int height) {
280 sp<RenderNode> node = new RenderNode();
281 node->mutateStagingProperties().setLeftTopRightBottom(x, y, x + width, y + height);
282 node->setPropertyFieldsDirty(RenderNode::X | RenderNode::Y);
283
Chris Craikdb663fe2015-04-20 13:34:45 -0700284 DisplayListCanvas* renderer = startRecording(node.get());
Chris Craik117bdbc2015-02-05 10:12:38 -0800285
286 SkPaint paint;
287 paint.setAntiAlias(true);
Chris Craik08fa43f2015-02-09 18:58:32 -0800288 paint.setColor(0xFF000000);
Chris Craik117bdbc2015-02-05 10:12:38 -0800289 renderer->drawOval(0, 0, width, height, paint);
290
291 endRecording(renderer, node.get());
292 return node;
293 }
294};
295
Chris Craik03188872015-02-02 18:39:33 -0800296struct cstr_cmp {
297 bool operator()(const char *a, const char *b) const {
298 return std::strcmp(a, b) < 0;
299 }
300};
301
Tim Murraybfbcd882015-05-06 12:38:05 -0700302typedef void (*testProc)(int);
Chris Craik03188872015-02-02 18:39:33 -0800303
304std::map<const char*, testProc, cstr_cmp> gTestMap {
305 {"shadowgrid", TreeContentAnimation::run<ShadowGridAnimation>},
Tim Murraybfbcd882015-05-06 12:38:05 -0700306 {"shadowgrid2", TreeContentAnimation::run<ShadowGrid2Animation>},
Chris Craik03188872015-02-02 18:39:33 -0800307 {"rectgrid", TreeContentAnimation::run<RectGridAnimation> },
Chris Craik117bdbc2015-02-05 10:12:38 -0800308 {"oval", TreeContentAnimation::run<OvalAnimation> },
Chris Craik03188872015-02-02 18:39:33 -0800309};
310
311int main(int argc, char* argv[]) {
312 const char* testName = argc > 1 ? argv[1] : "shadowgrid";
313 testProc proc = gTestMap[testName];
314 if(!proc) {
315 printf("Error: couldn't find test %s\n", testName);
316 return 1;
317 }
Tim Murray1a0f1c72015-05-06 11:37:37 -0700318 int loopCount = 1;
319 if (argc > 2) {
320 loopCount = atoi(argv[2]);
321 if (!loopCount) {
322 printf("Invalid loop count!\n");
323 return 1;
324 }
325 }
Tim Murraybfbcd882015-05-06 12:38:05 -0700326 int frameCount = 150;
327 if (argc > 3) {
328 frameCount = atoi(argv[3]);
329 if (frameCount < 1) {
330 printf("Invalid frame count!\n");
331 return 1;
332 }
333 }
Tim Murray1a0f1c72015-05-06 11:37:37 -0700334 if (loopCount < 0) {
335 loopCount = INT_MAX;
336 }
337 for (int i = 0; i < loopCount; i++) {
Tim Murraybfbcd882015-05-06 12:38:05 -0700338 proc(frameCount);
Tim Murray1a0f1c72015-05-06 11:37:37 -0700339 }
John Reck94c40fe2014-10-08 09:28:43 -0700340 printf("Success!\n");
341 return 0;
342}