From 78c71272fb26852bf3d2ca31785e61d4a598af82 Mon Sep 17 00:00:00 2001 From: robertphillips Date: Thu, 9 Oct 2014 04:59:19 -0700 Subject: Update old tools to allow MultiPictureDraw rendering I'll post a separate patch for nanobench and dm Review URL: https://codereview.chromium.org/639013003 --- tools/CopyTilesRenderer.cpp | 14 ++++- tools/CopyTilesRenderer.h | 3 +- tools/PictureBenchmark.cpp | 27 ++++------ tools/PictureBenchmark.h | 6 +-- tools/PictureRenderer.cpp | 119 +++++++++++++++++++++++++++++++---------- tools/PictureRenderer.h | 16 ++++-- tools/bbh_shootout.cpp | 10 ++-- tools/bench_pictures_main.cpp | 15 +----- tools/render_pictures_main.cpp | 20 +------ 9 files changed, 136 insertions(+), 94 deletions(-) (limited to 'tools') diff --git a/tools/CopyTilesRenderer.cpp b/tools/CopyTilesRenderer.cpp index 30a3256d63..6f95da758b 100644 --- a/tools/CopyTilesRenderer.cpp +++ b/tools/CopyTilesRenderer.cpp @@ -10,6 +10,7 @@ #include "SkCanvas.h" #include "SkDevice.h" #include "SkImageEncoder.h" +#include "SkMultiPictureDraw.h" #include "SkPicture.h" #include "SkPixelRef.h" #include "SkRect.h" @@ -28,7 +29,7 @@ namespace sk_tools { #endif void CopyTilesRenderer::init(const SkPicture* pict, const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) { + bool useChecksumBasedFilenames, bool useMultiPictureDraw) { // Do not call INHERITED::init(), which would create a (potentially large) canvas which is // not used by bench_pictures. SkASSERT(pict != NULL); @@ -39,6 +40,7 @@ namespace sk_tools { this->CopyString(&fMismatchPath, mismatchPath); this->CopyString(&fInputFilename, inputFilename); fUseChecksumBasedFilenames = useChecksumBasedFilenames; + fUseMultiPictureDraw = useMultiPictureDraw; this->buildBBoxHierarchy(); // In order to avoid allocating a large canvas (particularly important for GPU), create one // canvas that is a multiple of the tile size, and draw portions of the picture. @@ -61,7 +63,15 @@ namespace sk_tools { mat.postTranslate(SkIntToScalar(-x), SkIntToScalar(-y)); fCanvas->setMatrix(mat); // Draw the picture - fCanvas->drawPicture(fPicture); + if (fUseMultiPictureDraw) { + SkMultiPictureDraw mpd; + + mpd.add(fCanvas, fPicture); + + mpd.draw(); + } else { + fCanvas->drawPicture(fPicture); + } // Now extract the picture into tiles SkBitmap baseBitmap; fCanvas->readPixels(SkIRect::MakeSize(fCanvas->getBaseLayerSize()), &baseBitmap); diff --git a/tools/CopyTilesRenderer.h b/tools/CopyTilesRenderer.h index b24414223c..92996bbea8 100644 --- a/tools/CopyTilesRenderer.h +++ b/tools/CopyTilesRenderer.h @@ -31,7 +31,8 @@ namespace sk_tools { const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) SK_OVERRIDE; + bool useChecksumBasedFilenames, + bool useMultiPictureDraw) SK_OVERRIDE; /** * Similar to TiledPictureRenderer, this will draw a PNG for each tile. However, the diff --git a/tools/PictureBenchmark.cpp b/tools/PictureBenchmark.cpp index 15b6173aa1..f708f53613 100644 --- a/tools/PictureBenchmark.cpp +++ b/tools/PictureBenchmark.cpp @@ -15,15 +15,14 @@ namespace sk_tools { PictureBenchmark::PictureBenchmark() -: fRepeats(1) -, fRenderer(NULL) -, fTimerResult(TimerData::kAvg_Result) -, fTimerTypes(0) -, fTimeIndividualTiles(false) -, fPurgeDecodedTex(false) -, fPreprocess(false) -, fWriter(NULL) -{} + : fRepeats(1) + , fRenderer(NULL) + , fTimerResult(TimerData::kAvg_Result) + , fTimerTypes(0) + , fTimeIndividualTiles(false) + , fPurgeDecodedTex(false) + , fWriter(NULL) { +} PictureBenchmark::~PictureBenchmark() { SkSafeUnref(fRenderer); @@ -56,7 +55,7 @@ PictureRenderer* PictureBenchmark::setRenderer(sk_tools::PictureRenderer* render return renderer; } -void PictureBenchmark::run(SkPicture* pict) { +void PictureBenchmark::run(SkPicture* pict, bool useMultiPictureDraw) { SkASSERT(pict); if (NULL == pict) { return; @@ -67,17 +66,11 @@ void PictureBenchmark::run(SkPicture* pict) { return; } - fRenderer->init(pict, NULL, NULL, NULL, false); + fRenderer->init(pict, NULL, NULL, NULL, false, useMultiPictureDraw); // We throw this away to remove first time effects (such as paging in this program) fRenderer->setup(); - if (fPreprocess) { - if (fRenderer->getCanvas()) { - fRenderer->getCanvas()->EXPERIMENTAL_optimize(fRenderer->getPicture()); - } - } - fRenderer->render(NULL); fRenderer->resetState(true); // flush, swapBuffers and Finish diff --git a/tools/PictureBenchmark.h b/tools/PictureBenchmark.h index 2b1ccb5383..99eca6bcc0 100644 --- a/tools/PictureBenchmark.h +++ b/tools/PictureBenchmark.h @@ -28,7 +28,7 @@ public: * Draw the provided SkPicture fRepeats times while collecting timing data, and log the output * via fWriter. */ - void run(SkPicture* pict); + void run(SkPicture* pict, bool useMultiPictureDraw); void setRepeats(int repeats) { fRepeats = repeats; @@ -45,9 +45,6 @@ public: void setPurgeDecodedTex(bool purgeDecodedTex) { fPurgeDecodedTex = purgeDecodedTex; } bool purgeDecodedText() const { return fPurgeDecodedTex; } - void setPreprocess(bool preprocess) { fPreprocess = preprocess; } - bool preprocess() const { return fPreprocess; } - PictureRenderer* setRenderer(PictureRenderer*); PictureRenderer* renderer() { return fRenderer; } @@ -64,7 +61,6 @@ private: uint32_t fTimerTypes; // bitfield of TimerData::TimerFlags values bool fTimeIndividualTiles; bool fPurgeDecodedTex; - bool fPreprocess; PictureResultsWriter* fWriter; diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp index 705849d01a..89f2cda3dd 100644 --- a/tools/PictureRenderer.cpp +++ b/tools/PictureRenderer.cpp @@ -22,6 +22,7 @@ #include "SkImageEncoder.h" #include "SkMaskFilter.h" #include "SkMatrix.h" +#include "SkMultiPictureDraw.h" #include "SkOSFile.h" #include "SkPicture.h" #include "SkPictureRecorder.h" @@ -30,6 +31,7 @@ #include "SkScalar.h" #include "SkStream.h" #include "SkString.h" +#include "SkSurface.h" #include "SkTemplates.h" #include "SkTDArray.h" #include "SkThreadUtils.h" @@ -52,11 +54,13 @@ void PictureRenderer::init(const SkPicture* pict, const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) { + bool useChecksumBasedFilenames, + bool useMultiPictureDraw) { this->CopyString(&fWritePath, writePath); this->CopyString(&fMismatchPath, mismatchPath); this->CopyString(&fInputFilename, inputFilename); fUseChecksumBasedFilenames = useChecksumBasedFilenames; + fUseMultiPictureDraw = useMultiPictureDraw; SkASSERT(NULL == fPicture); SkASSERT(NULL == fCanvas.get()); @@ -415,8 +419,9 @@ SkString PipePictureRenderer::getConfigNameInternal() { void SimplePictureRenderer::init(const SkPicture* picture, const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) { - INHERITED::init(picture, writePath, mismatchPath, inputFilename, useChecksumBasedFilenames); + bool useChecksumBasedFilenames, bool useMultiPictureDraw) { + INHERITED::init(picture, writePath, mismatchPath, inputFilename, + useChecksumBasedFilenames, useMultiPictureDraw); this->buildBBoxHierarchy(); } @@ -427,7 +432,15 @@ bool SimplePictureRenderer::render(SkBitmap** out) { return false; } - fCanvas->drawPicture(fPicture); + if (fUseMultiPictureDraw) { + SkMultiPictureDraw mpd; + + mpd.add(fCanvas, fPicture); + + mpd.draw(); + } else { + fCanvas->drawPicture(fPicture); + } fCanvas->flush(); if (out) { *out = SkNEW(SkBitmap); @@ -467,7 +480,7 @@ TiledPictureRenderer::TiledPictureRenderer() void TiledPictureRenderer::init(const SkPicture* pict, const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) { + bool useChecksumBasedFilenames, bool useMultiPictureDraw) { SkASSERT(pict); SkASSERT(0 == fTileRects.count()); if (NULL == pict || fTileRects.count() != 0) { @@ -481,6 +494,7 @@ void TiledPictureRenderer::init(const SkPicture* pict, const SkString* writePath this->CopyString(&fMismatchPath, mismatchPath); this->CopyString(&fInputFilename, inputFilename); fUseChecksumBasedFilenames = useChecksumBasedFilenames; + fUseMultiPictureDraw = useMultiPictureDraw; this->buildBBoxHierarchy(); if (fTileWidthPercentage > 0) { @@ -519,10 +533,8 @@ void TiledPictureRenderer::setupTiles() { // Only count tiles in the X direction on the first pass. fTilesX++; } - *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), - SkIntToScalar(tile_y_start), - SkIntToScalar(fTileWidth), - SkIntToScalar(fTileHeight)); + *fTileRects.append() = SkIRect::MakeXYWH(tile_x_start, tile_y_start, + fTileWidth, fTileHeight); } } } @@ -575,10 +587,8 @@ void TiledPictureRenderer::setupPowerOf2Tiles() { // Only count tiles in the X direction on the first pass. fTilesX++; } - *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), - SkIntToScalar(tile_y_start), - SkIntToScalar(current_width), - SkIntToScalar(fTileHeight)); + *fTileRects.append() = SkIRect::MakeXYWH(tile_x_start, tile_y_start, + current_width, fTileHeight); tile_x_start += current_width; } @@ -594,13 +604,13 @@ void TiledPictureRenderer::setupPowerOf2Tiles() { * is called. */ static void draw_tile_to_canvas(SkCanvas* canvas, - const SkRect& tileRect, + const SkIRect& tileRect, const SkPicture* picture) { int saveCount = canvas->save(); // Translate so that we draw the correct portion of the picture. // Perform a postTranslate so that the scaleFactor does not interfere with the positioning. SkMatrix mat(canvas->getTotalMatrix()); - mat.postTranslate(-tileRect.fLeft, -tileRect.fTop); + mat.postTranslate(-SkIntToScalar(tileRect.fLeft), -SkIntToScalar(tileRect.fTop)); canvas->setMatrix(mat); canvas->drawPicture(picture); canvas->restoreToCount(saveCount); @@ -643,6 +653,27 @@ void TiledPictureRenderer::drawCurrentTile() { draw_tile_to_canvas(fCanvas, fTileRects[fCurrentTileOffset], fPicture); } +bool TiledPictureRenderer::postRender(SkCanvas* canvas, const SkIRect& tileRect, + SkBitmap* tempBM, SkBitmap** out, + int tileNumber) { + bool success = true; + + if (fEnableWrites) { + success &= write(canvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr, + fUseChecksumBasedFilenames, &tileNumber); + } + if (out) { + if (canvas->readPixels(tempBM, 0, 0)) { + // Add this tile to the entire bitmap. + bitmapCopyAtOffset(*tempBM, *out, tileRect.left(), tileRect.top()); + } else { + success = false; + } + } + + return success; +} + bool TiledPictureRenderer::render(SkBitmap** out) { SkASSERT(fPicture != NULL); if (NULL == fPicture) { @@ -650,29 +681,59 @@ bool TiledPictureRenderer::render(SkBitmap** out) { } SkBitmap bitmap; - if (out){ + if (out) { *out = SkNEW(SkBitmap); setup_bitmap(*out, SkScalarCeilToInt(fPicture->cullRect().width()), SkScalarCeilToInt(fPicture->cullRect().height())); setup_bitmap(&bitmap, fTileWidth, fTileHeight); } bool success = true; - for (int i = 0; i < fTileRects.count(); ++i) { - draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture); - if (fEnableWrites) { - success &= write(fCanvas, fWritePath, fMismatchPath, fInputFilename, fJsonSummaryPtr, - fUseChecksumBasedFilenames, &i); + + if (fUseMultiPictureDraw) { + SkMultiPictureDraw mpd; + SkTDArray surfaces; + surfaces.setReserve(fTileRects.count()); + + // Create a separate SkSurface/SkCanvas for each tile along with a + // translated version of the skp (to mimic Chrome's behavior) and + // feed all such pairs to the MultiPictureDraw. + for (int i = 0; i < fTileRects.count(); ++i) { + SkImageInfo ii = fCanvas->imageInfo().makeWH(fTileRects[i].width(), + fTileRects[i].height()); + *surfaces.append() = fCanvas->newSurface(ii); + surfaces[i]->getCanvas()->setMatrix(fCanvas->getTotalMatrix()); + + SkPictureRecorder recorder; + SkCanvas* c = recorder.beginRecording(SkIntToScalar(fTileRects[i].width()), + SkIntToScalar(fTileRects[i].height())); + c->save(); + SkMatrix mat; + mat.setTranslate(-SkIntToScalar(fTileRects[i].fLeft), + -SkIntToScalar(fTileRects[i].fTop)); + c->setMatrix(mat); + c->drawPicture(fPicture); + c->restore(); + + SkAutoTUnref xlatedPicture(recorder.endRecording()); + + mpd.add(surfaces[i]->getCanvas(), xlatedPicture); } - if (out) { - if (fCanvas->readPixels(&bitmap, 0, 0)) { - // Add this tile to the entire bitmap. - bitmapCopyAtOffset(bitmap, *out, SkScalarFloorToInt(fTileRects[i].left()), - SkScalarFloorToInt(fTileRects[i].top())); - } else { - success = false; - } + + // Render all the buffered SkCanvases/SkPictures + mpd.draw(); + + // Sort out the results and cleanup the allocated surfaces + for (int i = 0; i < fTileRects.count(); ++i) { + success &= this->postRender(surfaces[i]->getCanvas(), fTileRects[i], &bitmap, out, i); + surfaces[i]->unref(); + } + } else { + for (int i = 0; i < fTileRects.count(); ++i) { + draw_tile_to_canvas(fCanvas, fTileRects[i], fPicture); + success &= this->postRender(fCanvas, fTileRects[i], &bitmap, out, i); } } + return success; } diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h index 04ac20fcb6..3f58b18121 100644 --- a/tools/PictureRenderer.h +++ b/tools/PictureRenderer.h @@ -88,12 +88,14 @@ public: * @param inputFilename The name of the input file we are rendering. * @param useChecksumBasedFilenames Whether to use checksum-based filenames when writing * bitmap images to disk. + * @param useMultiPictureDraw true if MultiPictureDraw should be used for rendering */ virtual void init(const SkPicture* pict, const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames); + bool useChecksumBasedFilenames, + bool useMultiPictureDraw); /** * TODO(epoger): Temporary hack, while we work on http://skbug.com/2584 ('bench_pictures is @@ -445,6 +447,7 @@ protected: SkAutoTUnref fCanvas; SkAutoTUnref fPicture; bool fUseChecksumBasedFilenames; + bool fUseMultiPictureDraw; ImageResultsAndExpectations* fJsonSummaryPtr; SkDeviceTypes fDeviceType; bool fEnableWrites; @@ -548,7 +551,8 @@ public: const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) SK_OVERRIDE; + bool useChecksumBasedFilenames, + bool useMultiPictureDraw) SK_OVERRIDE; virtual bool render(SkBitmap** out = NULL) SK_OVERRIDE; @@ -570,7 +574,8 @@ public: const SkString* writePath, const SkString* mismatchPath, const SkString* inputFilename, - bool useChecksumBasedFilenames) SK_OVERRIDE; + bool useChecksumBasedFilenames, + bool useMultiPictureDraw) SK_OVERRIDE; /** * Renders to tiles, rather than a single canvas. @@ -659,7 +664,7 @@ public: void drawCurrentTile(); protected: - SkTDArray fTileRects; + SkTDArray fTileRects; virtual SkCanvas* setupCanvas(int width, int height) SK_OVERRIDE; virtual SkString getConfigNameInternal() SK_OVERRIDE; @@ -681,6 +686,9 @@ private: void setupTiles(); void setupPowerOf2Tiles(); + bool postRender(SkCanvas*, const SkIRect& tileRect, + SkBitmap* tempBM, SkBitmap** out, + int tileNumber); typedef PictureRenderer INHERITED; }; diff --git a/tools/bbh_shootout.cpp b/tools/bbh_shootout.cpp index 2a827fd896..d4b290d06b 100644 --- a/tools/bbh_shootout.cpp +++ b/tools/bbh_shootout.cpp @@ -60,13 +60,13 @@ static SkPicture* pic_from_path(const char path[]) { * @param timer The timer used to benchmark the work. */ static void do_benchmark_work(sk_tools::PictureRenderer* renderer, - BBoxType bBoxType, - SkPicture* pic, - const int numRepeats, - Timer* timer) { + BBoxType bBoxType, + SkPicture* pic, + const int numRepeats, + Timer* timer) { renderer->setBBoxHierarchyType(bBoxType); renderer->setGridSize(FLAGS_tilesize, FLAGS_tilesize); - renderer->init(pic, NULL, NULL, NULL, false); + renderer->init(pic, NULL, NULL, NULL, false, false); SkDebugf("%s %d times...\n", renderer->getConfigName().c_str(), numRepeats); for (int i = 0; i < numRepeats; ++i) { diff --git a/tools/bench_pictures_main.cpp b/tools/bench_pictures_main.cpp index ade93fc3e6..93ee308ae1 100644 --- a/tools/bench_pictures_main.cpp +++ b/tools/bench_pictures_main.cpp @@ -59,7 +59,7 @@ DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. " "Report some GPU call statistics."); #endif -DEFINE_bool(preprocess, false, "If true, perform device specific preprocessing before timing."); +DEFINE_bool(mpd, false, "If true, use MultiPictureDraw to render."); // Buildbot-specific parameters DEFINE_string(builderName, "", "Name of the builder this is running on."); @@ -202,23 +202,13 @@ static bool run_single_benchmark(const SkString& inputPath, return false; } - if (FLAGS_preprocess) { - // Because the GPU preprocessing step relies on the in-memory picture - // statistics we need to rerecord the picture here - SkPictureRecorder recorder; - picture->playback(recorder.beginRecording(picture->cullRect().width(), - picture->cullRect().height(), - NULL, 0)); - picture.reset(recorder.endRecording()); - } - SkString filename = SkOSPath::Basename(inputPath.c_str()); gWriter.bench(filename.c_str(), SkScalarCeilToInt(picture->cullRect().width()), SkScalarCeilToInt(picture->cullRect().height())); - benchmark.run(picture); + benchmark.run(picture, FLAGS_mpd); #if SK_LAZY_CACHE_STATS if (FLAGS_trackDeferredCaching) { @@ -365,7 +355,6 @@ static void setup_benchmark(sk_tools::PictureBenchmark* benchmark) { } benchmark->setPurgeDecodedTex(FLAGS_purgeDecodedTex); - benchmark->setPreprocess(FLAGS_preprocess); if (FLAGS_readPath.count() < 1) { gLogger.logError(".skp files or directories are required.\n"); diff --git a/tools/render_pictures_main.cpp b/tools/render_pictures_main.cpp index d7a213cb47..6faa81ac0e 100644 --- a/tools/render_pictures_main.cpp +++ b/tools/render_pictures_main.cpp @@ -40,7 +40,7 @@ DEFINE_string(mismatchPath, "", "Write images for tests that failed due to " DEFINE_bool(gpuStats, false, "Only meaningful with gpu configurations. " "Report some GPU call statistics."); #endif -DEFINE_bool(preprocess, false, "If true, perform device specific preprocessing before rendering."); +DEFINE_bool(mpd, false, "If true, use MultiPictureDraw for rendering."); DEFINE_string(readJsonSummaryPath, "", "JSON file to read image expectations from."); DECLARE_string(readPath); DEFINE_bool(writeChecksumBasedFilenames, false, @@ -184,16 +184,6 @@ static bool render_picture_internal(const SkString& inputPath, const SkString* w return false; } - if (FLAGS_preprocess) { - // Because the GPU preprocessing step relies on the in-memory picture - // statistics we need to rerecord the picture here - SkPictureRecorder recorder; - picture->playback(recorder.beginRecording(picture->cullRect().width(), - picture->cullRect().height(), - NULL, 0)); - picture.reset(recorder.endRecording()); - } - while (FLAGS_bench_record) { SkPictureRecorder recorder; picture->playback(recorder.beginRecording(picture->cullRect().width(), @@ -208,13 +198,7 @@ static bool render_picture_internal(const SkString& inputPath, const SkString* w inputPath.c_str()); renderer.init(picture, &writePathString, &mismatchPathString, &inputFilename, - FLAGS_writeChecksumBasedFilenames); - - if (FLAGS_preprocess) { - if (renderer.getCanvas()) { - renderer.getCanvas()->EXPERIMENTAL_optimize(renderer.getPicture()); - } - } + FLAGS_writeChecksumBasedFilenames, FLAGS_mpd); renderer.setup(); renderer.enableWrites(); -- cgit v1.2.3