Chromium Code Reviews| Index: gm/optimizations.cpp |
| =================================================================== |
| --- gm/optimizations.cpp (revision 0) |
| +++ gm/optimizations.cpp (revision 0) |
| @@ -0,0 +1,240 @@ |
| +/* |
| + * Copyright 2013 Google Inc. |
| + * |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. |
| + */ |
| + |
| +#include "gm.h" |
| +#include "..\debugger\SkDebugCanvas.h" |
| +#include "SkPictureFlat.h" |
| + |
| +namespace { |
| + |
| +// Do the commands in 'input' match the supplied pattern? Note: this is a pretty |
| +// heavy-weight operation since we are drawing the picture into a debug canvas |
| +// to extract the commands. |
| +bool check_pattern(SkPicture& input, const SkTDArray<DrawType> &pattern) { |
| + SkDebugCanvas debugCanvas(input.width(), input.height()); |
| + debugCanvas.setBounds(input.width(), input.height()); |
| + input.draw(&debugCanvas); |
| + |
| + if (pattern.count() != debugCanvas.getSize()) { |
| + return false; |
| + } |
| + |
| + for (int i = 0; i < pattern.count(); ++i) { |
| + if (pattern[i] != debugCanvas.getDrawCommandAt(i)->getType()) { |
| + return false; |
| + } |
| + } |
| + |
| + return true; |
| +} |
| + |
| +// construct the pattern removed by the SkPictureRecord::remove_save_layer1 |
| +// optimization, i.e.: |
| +// SAVE_LAYER |
| +// DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT |
| +// RESTORE |
| +SkPicture* create_save_layer_opt_1(SkTDArray<DrawType> *preOptPattern, |
| + SkTDArray<DrawType> *postOptPattern, |
| + const SkBitmap& checkerBoard) { |
| + // Create the pattern that should trigger the optimization |
| + preOptPattern->setCount(5); |
| + (*preOptPattern)[0] = SAVE; |
| + (*preOptPattern)[1] = SAVE_LAYER; |
| + (*preOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT; |
| + (*preOptPattern)[3] = RESTORE; |
| + (*preOptPattern)[4] = RESTORE; |
| + |
| + // Create the pattern that should appear after the optimization |
| + postOptPattern->setCount(5); |
| + (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw |
| + (*postOptPattern)[1] = SAVE; |
| + (*postOptPattern)[2] = DRAW_BITMAP_RECT_TO_RECT; |
| + (*postOptPattern)[3] = RESTORE; |
| + (*postOptPattern)[4] = RESTORE; |
| + |
| + SkPicture* result = new SkPicture; |
| + |
| + // have to disable the optimizations while generating the picture |
| + SkCanvas* canvas = result->beginRecording(100, 100, |
| + SkPicture::kDisableOptimizations_RecordingFlag); |
| + |
| + SkPaint saveLayerPaint; |
| + saveLayerPaint.setColor(0xCC000000); |
| + |
| + // saveLayer's 'bounds' parameter must be NULL for this optimization |
| + canvas->saveLayer(NULL, &saveLayerPaint); |
| + |
| + SkRect rect = { 10, 10, 90, 90 }; |
| + |
| + // The dbmr2r's paint must be opaque |
| + SkPaint dbmr2rPaint; |
| + dbmr2rPaint.setColor(0xFF000000); |
| + |
| + canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint); |
| + canvas->restore(); |
| + |
| + result->endRecording(); |
| + |
| + return result; |
| +} |
| + |
| +// construct the pattern removed by the SkPictureRecord::remove_save_layer2 |
| +// optimization, i.e.: |
| +// SAVE_LAYER (with NULL == bounds) |
| +// SAVE |
| +// CLIP_RECT |
| +// DRAW_BITMAP|DRAW_BITMAP_MATRIX|DRAW_BITMAP_NINE|DRAW_BITMAP_RECT_TO_RECT |
| +// RESTORE |
| +// RESTORE |
| +SkPicture* create_save_layer_opt_2(SkTDArray<DrawType> *preOptPattern, |
| + SkTDArray<DrawType> *postOptPattern, |
| + const SkBitmap& checkerBoard) { |
| + // Create the pattern that should trigger the optimization |
| + preOptPattern->setCount(8); |
| + (*preOptPattern)[0] = SAVE; |
| + (*preOptPattern)[1] = SAVE_LAYER; |
| + (*preOptPattern)[2] = SAVE; |
| + (*preOptPattern)[3] = CLIP_RECT; |
| + (*preOptPattern)[4] = DRAW_BITMAP_RECT_TO_RECT; |
| + (*preOptPattern)[5] = RESTORE; |
| + (*preOptPattern)[6] = RESTORE; |
| + (*preOptPattern)[7] = RESTORE; |
| + |
| + // Create the pattern that should appear after the optimization |
| + postOptPattern->setCount(8); |
| + (*postOptPattern)[0] = SAVE; // extra save/restore added by extra draw |
| + (*postOptPattern)[1] = SAVE; |
| + (*postOptPattern)[2] = SAVE; |
| + (*postOptPattern)[3] = CLIP_RECT; |
| + (*postOptPattern)[4] = DRAW_BITMAP_RECT_TO_RECT; |
| + (*postOptPattern)[5] = RESTORE; |
| + (*postOptPattern)[6] = RESTORE; |
| + (*postOptPattern)[7] = RESTORE; |
| + |
| + SkPicture* result = new SkPicture; |
| + |
| + // have to disable the optimizations while generating the picture |
| + SkCanvas* canvas = result->beginRecording(100, 100, |
| + SkPicture::kDisableOptimizations_RecordingFlag); |
| + |
| + SkPaint saveLayerPaint; |
| + saveLayerPaint.setColor(0xCC000000); |
| + |
| + // saveLayer's 'bounds' parameter must be NULL for this optimization |
| + canvas->saveLayer(NULL, &saveLayerPaint); |
| + |
| + canvas->save(); |
| + |
| + SkRect rect = { 10, 10, 90, 90 }; |
| + canvas->clipRect(rect); |
| + |
| + // The dbmr2r's paint must be opaque |
| + SkPaint dbmr2rPaint; |
| + dbmr2rPaint.setColor(0xFF000000); |
| + |
| + canvas->drawBitmapRectToRect(checkerBoard, NULL, rect, &dbmr2rPaint); |
| + canvas->restore(); |
| + canvas->restore(); |
| + |
| + result->endRecording(); |
| + |
| + return result; |
| +} |
| + |
| +}; |
| + |
| + |
| +// As our .skp optimizations get folded into the captured skps our code will |
| +// no longer be locally exercised. This GM manually constructs the patterns |
| +// our optimizations will remove to test them. It acts as both a GM and a unit |
| +// test |
| +class OptimizationsGM : public skiagm::GM { |
| +public: |
| + OptimizationsGM() { |
| + this->makeCheckerboard(); |
| + } |
| + |
| +protected: |
| + SkString onShortName() { |
| + return SkString("optimizations"); |
| + } |
| + |
| + SkISize onISize() { return SkISize::Make(800, 800); } |
| + |
| + typedef SkPicture* (*PFCreateOpt)(SkTDArray<DrawType> *preOptPattern, |
| + SkTDArray<DrawType> *postOptPattern, |
| + const SkBitmap& checkerBoard); |
| + |
| + virtual void onDraw(SkCanvas* canvas) { |
| + |
| + PFCreateOpt gOpts[] = { |
| + create_save_layer_opt_1, |
| + create_save_layer_opt_2 |
| + }; |
| + |
| + SkTDArray<DrawType> prePattern, postPattern; |
| + |
| + for (int i = 0; i < SK_ARRAY_COUNT(gOpts); ++i) { |
| + SkAutoTUnref<SkPicture> pre((*gOpts)(&prePattern, &postPattern, fCheckerboard)); |
| + |
| + SkASSERT(check_pattern(*pre, prePattern)); |
| + |
| + canvas->drawPicture(*pre); |
| + |
| + canvas->translate(SkIntToScalar(pre->width()), 0); |
| + |
| + SkAutoTUnref<SkPicture> post(new SkPicture); |
| + |
| + SkCanvas* recordCanvas = post->beginRecording(pre->width(), pre->height()); |
| + |
| + pre->draw(recordCanvas); |
| + |
| + post->endRecording(); |
| + |
| + SkASSERT(check_pattern(*post, postPattern)); |
|
Justin Novosad
2013/03/25 18:34:55
This really feels like it should be a unit test ra
|
| + |
| + canvas->drawPicture(*post); |
| + |
| + canvas->translate(SkIntToScalar(-pre->width()), |
| + SkIntToScalar(post->height())); |
| + |
| + // TODO: we could also render the pre and post pictures to bitmaps |
| + // and manually compare them in this method |
| + } |
| + } |
| + |
| +private: |
| + void makeCheckerboard() { |
| + static const unsigned int kCheckerboardWidth = 16; |
| + static const unsigned int kCheckerboardHeight = 16; |
| + |
| + fCheckerboard.setConfig(SkBitmap::kARGB_8888_Config, |
| + kCheckerboardWidth, kCheckerboardHeight); |
| + fCheckerboard.allocPixels(); |
| + SkAutoLockPixels lock(fCheckerboard); |
| + for (int y = 0; y < kCheckerboardHeight; y += 2) { |
| + SkPMColor* scanline = fCheckerboard.getAddr32(0, y); |
| + for (int x = 0; x < kCheckerboardWidth; x += 2) { |
| + *scanline++ = 0xFFFFFFFF; |
| + *scanline++ = 0xFF000000; |
| + } |
| + scanline = fCheckerboard.getAddr32(0, y + 1); |
| + for (int x = 0; x < kCheckerboardWidth; x += 2) { |
| + *scanline++ = 0xFF000000; |
| + *scanline++ = 0xFFFFFFFF; |
| + } |
| + } |
| + } |
| + |
| + SkBitmap fCheckerboard; |
| + |
| + typedef skiagm::GM INHERITED; |
| +}; |
| + |
| +////////////////////////////////////////////////////////////////////////////// |
| + |
| +DEF_GM( return new OptimizationsGM; ) |
| Property changes on: gm\optimizations.cpp |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |