Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(265)

Side by Side Diff: gm/optimizations.cpp

Issue 12843028: Add testing of optimizations to GM (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: compiler warning/error fixes Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | gyp/SampleApp.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "gm.h"
9 #include "SkDebugCanvas.h"
10 #include "SkPictureFlat.h"
11
12 #define WARN(msg) \
13 SkDebugf("%s:%d: %s\n", __FILE__, __LINE__, msg);
14
15 namespace {
16
17 // Do the commands in 'input' match the supplied pattern? Note: this is a pretty
18 // heavy-weight operation since we are drawing the picture into a debug canvas
19 // to extract the commands.
20 bool check_pattern(SkPicture& input, const SkTDArray<DrawType> &pattern) {
21 SkDebugCanvas debugCanvas(input.width(), input.height());
22 debugCanvas.setBounds(input.width(), input.height());
23 input.draw(&debugCanvas);
24
25 if (pattern.count() != debugCanvas.getSize()) {
26 return false;
27 }
28
29 for (int i = 0; i < pattern.count(); ++i) {
30 if (pattern[i] != debugCanvas.getDrawCommandAt(i)->getType()) {
31 return false;
32 }
33 }
34
35 return true;
36 }
37
38 // construct the pattern removed by the SkPictureRecord::remove_save_layer1
39 // optimization, i.e.:
40 // SAVE_LAYER
41 // DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_REC T
42 // RESTORE
43 //
44 // saveLayerHasPaint - control if the saveLayer has a paint (the optimization
45 // takes a different path if this is false)
46 // dbmr2rHasPaint - control if the dbmr2r has a paint (the optimization
47 // takes a different path if this is false)
48 // colorsMatch - control if the saveLayer and dbmr2r paint colors
49 // match (the optimization will fail if they do not)
50 SkPicture* create_save_layer_opt_1(SkTDArray<DrawType> *preOptPattern,
51 SkTDArray<DrawType> *postOptPattern,
52 const SkBitmap& checkerBoard,
53 bool saveLayerHasPaint,
54 bool dbmr2rHasPaint,
55 bool colorsMatch) {
56 // Create the pattern that should trigger the optimization
57 preOptPattern->setCount(5);
58 (*preOptPattern)[0] = SAVE;
59 (*preOptPattern)[1] = SAVE_LAYER;
60 (*preOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT;
61 (*preOptPattern)[3] = RESTORE;
62 (*preOptPattern)[4] = RESTORE;
63
64 if (colorsMatch) {
65 // Create the pattern that should appear after the optimization
66 postOptPattern->setCount(5);
67 (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
68 (*postOptPattern)[1] = SAVE;
69 (*postOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT;
70 (*postOptPattern)[3] = RESTORE;
71 (*postOptPattern)[4] = RESTORE;
72 } else {
73 // Create the pattern that appears if the optimization doesn't fire
74 postOptPattern->setCount(7);
75 (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
76 (*postOptPattern)[1] = SAVE;
77 (*postOptPattern)[2] = SAVE_LAYER;
78 (*postOptPattern)[3] = DRAW_BITMAP_RECT_TO_RECT;
79 (*postOptPattern)[4] = RESTORE;
80 (*postOptPattern)[5] = RESTORE;
81 (*postOptPattern)[6] = RESTORE;
82 }
83
84 SkPicture* result = new SkPicture;
85
86 // have to disable the optimizations while generating the picture
87 SkCanvas* canvas = result->beginRecording(100, 100,
88 SkPicture::kDisableRecordOptimizations_RecordingFlag);
89
90 SkPaint saveLayerPaint;
91 saveLayerPaint.setColor(0xCC000000);
92
93 // saveLayer's 'bounds' parameter must be NULL for this optimization
94 if (saveLayerHasPaint) {
95 canvas->saveLayer(NULL, &saveLayerPaint);
96 } else {
97 canvas->saveLayer(NULL, NULL);
98 }
99
100 SkRect rect = { 10, 10, 90, 90 };
101
102 // The dbmr2r's paint must be opaque
103 SkPaint dbmr2rPaint;
104 if (colorsMatch) {
105 dbmr2rPaint.setColor(0xFF000000);
106 } else {
107 dbmr2rPaint.setColor(0xFFFF0000);
108 }
109
110 if (dbmr2rHasPaint) {
111 canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint);
112 } else {
113 canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, NULL);
114 }
115 canvas->restore();
116
117 result->endRecording();
118
119 return result;
120 }
121
122 // straight-ahead version that is seen in the skps
123 SkPicture* create_save_layer_opt_1_v1(SkTDArray<DrawType> *preOptPattern,
124 SkTDArray<DrawType> *postOptPattern,
125 const SkBitmap& checkerBoard) {
126 return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
127 true, // saveLayer has a paint
128 true, // dbmr2r has a paint
129 true); // and the colors match
130 }
131
132 // alternate version that should still succeed
133 SkPicture* create_save_layer_opt_1_v2(SkTDArray<DrawType> *preOptPattern,
134 SkTDArray<DrawType> *postOptPattern,
135 const SkBitmap& checkerBoard) {
136 return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
137 false, // saveLayer doesn't have a paint!
138 true, // dbmr2r has a paint
139 true); // color matching not really applicab le
140 }
141
142 // alternate version that should still succeed
143 SkPicture* create_save_layer_opt_1_v3(SkTDArray<DrawType> *preOptPattern,
144 SkTDArray<DrawType> *postOptPattern,
145 const SkBitmap& checkerBoard) {
146 return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
147 true, // saveLayer has a paint
148 false, // dbmr2r doesn't have a paint!
149 true); // color matching not really applicab le
150 }
151
152 // version in which the optimization fails b.c. the colors don't match
153 SkPicture* create_save_layer_opt_1_v4(SkTDArray<DrawType> *preOptPattern,
154 SkTDArray<DrawType> *postOptPattern,
155 const SkBitmap& checkerBoard) {
156 return create_save_layer_opt_1(preOptPattern, postOptPattern, checkerBoard,
157 true, // saveLayer has a paint
158 true, // dbmr2r has a paint
159 false); // and the colors don't match!
160 }
161
162 // construct the pattern removed by the SkPictureRecord::remove_save_layer2
163 // optimization, i.e.:
164 // SAVE_LAYER (with NULL == bounds)
165 // SAVE
166 // CLIP_RECT
167 // DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_R ECT
168 // RESTORE
169 // RESTORE
170 //
171 // saveLayerHasPaint - control if the saveLayer has a paint (the optimization
172 // takes a different path if this is false)
173 // dbmr2rHasPaint - control if the dbmr2r has a paint (the optimization
174 // takes a different path if this is false)
175 // colorsMatch - control if the saveLayer and dbmr2r paint colors
176 // match (the optimization will fail if they do not)
177 SkPicture* create_save_layer_opt_2(SkTDArray<DrawType> *preOptPattern,
178 SkTDArray<DrawType> *postOptPattern,
179 const SkBitmap& checkerBoard,
180 bool saveLayerHasPaint,
181 bool dbmr2rHasPaint,
182 bool colorsMatch) {
183 // Create the pattern that should trigger the optimization
184 preOptPattern->setCount(8);
185 (*preOptPattern)[0] = SAVE;
186 (*preOptPattern)[1] = SAVE_LAYER;
187 (*preOptPattern)[2] = SAVE;
188 (*preOptPattern)[3] = CLIP_RECT;
189 (*preOptPattern)[4] = DRAW_BITMAP_RECT_TO_RECT;
190 (*preOptPattern)[5] = RESTORE;
191 (*preOptPattern)[6] = RESTORE;
192 (*preOptPattern)[7] = RESTORE;
193
194 if (colorsMatch) {
195 // Create the pattern that should appear after the optimization
196 postOptPattern->setCount(8);
197 (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
198 (*postOptPattern)[1] = SAVE;
199 (*postOptPattern)[2] = SAVE;
200 (*postOptPattern)[3] = CLIP_RECT;
201 (*postOptPattern)[4] = DRAW_BITMAP_RECT_TO_RECT;
202 (*postOptPattern)[5] = RESTORE;
203 (*postOptPattern)[6] = RESTORE;
204 (*postOptPattern)[7] = RESTORE;
205 } else {
206 // Create the pattern that appears if the optimization doesn't fire
207 postOptPattern->setCount(10);
208 (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw
209 (*postOptPattern)[1] = SAVE;
210 (*postOptPattern)[2] = SAVE_LAYER;
211 (*postOptPattern)[3] = SAVE;
212 (*postOptPattern)[4] = CLIP_RECT;
213 (*postOptPattern)[5] = DRAW_BITMAP_RECT_TO_RECT;
214 (*postOptPattern)[6] = RESTORE;
215 (*postOptPattern)[7] = RESTORE;
216 (*postOptPattern)[8] = RESTORE;
217 (*postOptPattern)[9] = RESTORE;
218 }
219
220 SkPicture* result = new SkPicture;
221
222 // have to disable the optimizations while generating the picture
223 SkCanvas* canvas = result->beginRecording(100, 100,
224 SkPicture::kDisableRecordOptimizations_RecordingFlag);
225
226 SkPaint saveLayerPaint;
227 saveLayerPaint.setColor(0xCC000000);
228
229 // saveLayer's 'bounds' parameter must be NULL for this optimization
230 if (saveLayerHasPaint) {
231 canvas->saveLayer(NULL, &saveLayerPaint);
232 } else {
233 canvas->saveLayer(NULL, NULL);
234 }
235
236 canvas->save();
237
238 SkRect rect = { 10, 10, 90, 90 };
239 canvas->clipRect(rect);
240
241 // The dbmr2r's paint must be opaque
242 SkPaint dbmr2rPaint;
243 if (colorsMatch) {
244 dbmr2rPaint.setColor(0xFF000000);
245 } else {
246 dbmr2rPaint.setColor(0xFFFF0000);
247 }
248
249 if (dbmr2rHasPaint) {
250 canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint);
251 } else {
252 canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, NULL);
253 }
254 canvas->restore();
255 canvas->restore();
256
257 result->endRecording();
258
259 return result;
260 }
261
262 // straight-ahead version that is seen in the skps
263 SkPicture* create_save_layer_opt_2_v1(SkTDArray<DrawType> *preOptPattern,
264 SkTDArray<DrawType> *postOptPattern,
265 const SkBitmap& checkerBoard) {
266 return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
267 true, // saveLayer has a paint
268 true, // dbmr2r has a paint
269 true); // and the colors match
270 }
271
272 // alternate version that should still succeed
273 SkPicture* create_save_layer_opt_2_v2(SkTDArray<DrawType> *preOptPattern,
274 SkTDArray<DrawType> *postOptPattern,
275 const SkBitmap& checkerBoard) {
276 return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
277 false, // saveLayer doesn't have a paint!
278 true, // dbmr2r has a paint
279 true); // color matching not really applicab le
280 }
281
282 // alternate version that should still succeed
283 SkPicture* create_save_layer_opt_2_v3(SkTDArray<DrawType> *preOptPattern,
284 SkTDArray<DrawType> *postOptPattern,
285 const SkBitmap& checkerBoard) {
286 return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
287 true, // saveLayer has a paint
288 false, // dbmr2r doesn't have a paint!
289 true); // color matching not really applicab le
290 }
291
292 // version in which the optimization fails b.c. the colors don't match
293 SkPicture* create_save_layer_opt_2_v4(SkTDArray<DrawType> *preOptPattern,
294 SkTDArray<DrawType> *postOptPattern,
295 const SkBitmap& checkerBoard) {
296 return create_save_layer_opt_2(preOptPattern, postOptPattern, checkerBoard,
297 true, // saveLayer has a paint
298 true, // dbmr2r has a paint
299 false); // and the colors don't match!
300 }
301
302 };
303
304
305 // As our .skp optimizations get folded into the captured skps our code will
306 // no longer be locally exercised. This GM manually constructs the patterns
307 // our optimizations will remove to test them. It acts as both a GM and a unit
308 // test
309 class OptimizationsGM : public skiagm::GM {
310 public:
311 OptimizationsGM() {
312 this->makeCheckerboard();
313 }
314
315 static const int kWidth = 800;
316 static const int kHeight = 800;
317
318 protected:
319 SkString onShortName() {
320 return SkString("optimizations");
321 }
322
323 SkISize onISize() { return SkISize::Make(kWidth, kHeight); }
324
325 typedef SkPicture* (*PFCreateOpt)(SkTDArray<DrawType> *preOptPattern,
326 SkTDArray<DrawType> *postOptPattern,
327 const SkBitmap& checkerBoard);
328
329 virtual void onDraw(SkCanvas* canvas) {
330
331 PFCreateOpt gOpts[] = {
332 create_save_layer_opt_1_v1,
333 create_save_layer_opt_1_v2,
334 create_save_layer_opt_1_v3,
335 create_save_layer_opt_1_v4,
336 create_save_layer_opt_2_v1,
337 create_save_layer_opt_2_v2,
338 create_save_layer_opt_2_v3,
339 create_save_layer_opt_2_v4,
340 };
341
342 SkTDArray<DrawType> prePattern, postPattern;
343 int xPos = 0, yPos = 0;
344
345 for (size_t i = 0; i < SK_ARRAY_COUNT(gOpts); ++i) {
346 SkAutoTUnref<SkPicture> pre((*gOpts[i])(&prePattern, &postPattern, f Checkerboard));
347
348 if (!(check_pattern(*pre, prePattern))) {
349 WARN("Pre optimization pattern mismatch");
350 SkASSERT(0);
351 }
352
353 canvas->save();
354 canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos));
355 pre->draw(canvas);
356 xPos += pre->width();
357 canvas->restore();
358
359 // re-render the 'pre' picture and thus 'apply' the optimization
360 SkAutoTUnref<SkPicture> post(new SkPicture);
361
362 SkCanvas* recordCanvas = post->beginRecording(pre->width(), pre->hei ght());
363
364 pre->draw(recordCanvas);
365
366 post->endRecording();
367
368 if (!(check_pattern(*post, postPattern))) {
369 WARN("Post optimization pattern mismatch");
370 SkASSERT(0);
371 }
372
373 canvas->save();
374 canvas->translate(SkIntToScalar(xPos), SkIntToScalar(yPos));
375 post->draw(canvas);
376 xPos += post->width();
377 canvas->restore();
378
379 if (xPos >= kWidth) {
380 // start a new line
381 xPos = 0;
382 yPos += post->height();
383 }
384
385 // TODO: we could also render the pre and post pictures to bitmaps
386 // and manually compare them in this method
387 }
388 }
389
390 private:
391 void makeCheckerboard() {
392 static const unsigned int kCheckerboardWidth = 16;
393 static const unsigned int kCheckerboardHeight = 16;
394
395 fCheckerboard.setConfig(SkBitmap::kARGB_8888_Config,
396 kCheckerboardWidth, kCheckerboardHeight);
397 fCheckerboard.allocPixels();
398 SkAutoLockPixels lock(fCheckerboard);
399 for (unsigned int y = 0; y < kCheckerboardHeight; y += 2) {
400 SkPMColor* scanline = fCheckerboard.getAddr32(0, y);
401 for (unsigned int x = 0; x < kCheckerboardWidth; x += 2) {
402 *scanline++ = 0xFFFFFFFF;
403 *scanline++ = 0xFF000000;
404 }
405 scanline = fCheckerboard.getAddr32(0, y + 1);
406 for (unsigned int x = 0; x < kCheckerboardWidth; x += 2) {
407 *scanline++ = 0xFF000000;
408 *scanline++ = 0xFFFFFFFF;
409 }
410 }
411 }
412
413 SkBitmap fCheckerboard;
414
415 typedef skiagm::GM INHERITED;
416 };
417
418 //////////////////////////////////////////////////////////////////////////////
419
420 DEF_GM( return new OptimizationsGM; )
OLDNEW
« no previous file with comments | « no previous file | gyp/SampleApp.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698