From acfb30e5bb797249f4ec41edda4c4d4b86e0e5d0 Mon Sep 17 00:00:00 2001 From: "scroggo@google.com" Date: Tue, 18 Sep 2012 14:32:35 +0000 Subject: [PATCH] Reuse one canvas for every tile in bench_pictures (in single threaded mode). Turn off multi threaded option for now. In bench_pictures, do not create a large canvas, since we never use it. Remove unused functions on TiledPictureRenderer. Review URL: https://codereview.appspot.com/6521043 git-svn-id: http://skia.googlecode.com/svn/trunk@5583 2bbb7eff-a529-9590-31e7-b0007b416f81 --- tools/PictureRenderer.cpp | 127 ++++++++++++++++++++++++---------------------- tools/PictureRenderer.h | 23 +-------- 2 files changed, 68 insertions(+), 82 deletions(-) diff --git a/tools/PictureRenderer.cpp b/tools/PictureRenderer.cpp index cc9babb..cea7b5b 100644 --- a/tools/PictureRenderer.cpp +++ b/tools/PictureRenderer.cpp @@ -115,6 +115,8 @@ bool PictureRenderer::write(const SkString& path) const { return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100); } +/////////////////////////////////////////////////////////////////////////////////////////////// + void RecordPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { SkPicture replayer; SkCanvas* recorder = replayer.beginRecording(fPicture->width(), fPicture->height()); @@ -122,6 +124,8 @@ void RecordPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { replayer.endRecording(); } +/////////////////////////////////////////////////////////////////////////////////////////////// + void PipePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { SkASSERT(fCanvas.get() != NULL); SkASSERT(fPicture != NULL); @@ -137,6 +141,8 @@ void PipePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { fCanvas->flush(); } +/////////////////////////////////////////////////////////////////////////////////////////////// + void SimplePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { SkASSERT(fCanvas.get() != NULL); SkASSERT(fPicture != NULL); @@ -148,6 +154,8 @@ void SimplePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { fCanvas->flush(); } +/////////////////////////////////////////////////////////////////////////////////////////////// + TiledPictureRenderer::TiledPictureRenderer() : fMultiThreaded(false) , fUsePipe(false) @@ -159,12 +167,14 @@ TiledPictureRenderer::TiledPictureRenderer() void TiledPictureRenderer::init(SkPicture* pict) { SkASSERT(pict != NULL); - SkASSERT(0 == fTiles.count()); - if (NULL == pict || fTiles.count() != 0) { + SkASSERT(0 == fTileRects.count()); + if (NULL == pict || fTileRects.count() != 0) { return; } - this->INHERITED::init(pict); + // Do not call INHERITED::init(), which would create a (potentially large) canvas which is not + // used by bench_pictures. + fPicture = pict; if (fTileWidthPercentage > 0) { fTileWidth = sk_float_ceil2int(float(fTileWidthPercentage * fPicture->width() / 100)); @@ -180,19 +190,6 @@ void TiledPictureRenderer::init(SkPicture* pict) { } } -void TiledPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { - SkASSERT(fCanvas.get() != NULL); - SkASSERT(fPicture != NULL); - if (NULL == fCanvas.get() || NULL == fPicture) { - return; - } - - this->drawTiles(); - if (doExtraWorkToDrawToBaseCanvas) { - this->copyTilesToCanvas(); - } -} - void TiledPictureRenderer::end() { this->deleteTiles(); this->INHERITED::end(); @@ -202,27 +199,13 @@ TiledPictureRenderer::~TiledPictureRenderer() { this->deleteTiles(); } -void TiledPictureRenderer::clipTile(SkCanvas* tile) { - SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()), - SkIntToScalar(fPicture->height())); - tile->clipRect(clip); -} - -void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start, int width, int height) { - SkCanvas* tile = this->setupCanvas(width, height); - - tile->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start)); - this->clipTile(tile); - - fTiles.push(tile); -} - void TiledPictureRenderer::setupTiles() { - for (int tile_y_start = 0; tile_y_start < fPicture->height(); - tile_y_start += fTileHeight) { - for (int tile_x_start = 0; tile_x_start < fPicture->width(); - tile_x_start += fTileWidth) { - this->addTile(tile_x_start, tile_y_start, fTileWidth, fTileHeight); + for (int tile_y_start = 0; tile_y_start < fPicture->height(); tile_y_start += fTileHeight) { + for (int tile_x_start = 0; tile_x_start < fPicture->width(); tile_x_start += fTileWidth) { + *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), + SkIntToScalar(tile_y_start), + SkIntToScalar(fTileWidth), + SkIntToScalar(fTileHeight)); } } } @@ -250,11 +233,17 @@ void TiledPictureRenderer::setupPowerOf2Tiles() { for (int tile_y_start = 0; tile_y_start < fPicture->height(); tile_y_start += fTileHeight) { int tile_x_start = 0; int current_width = largest_possible_tile_size; + // Set fTileWidth to be the width of the widest tile, so that each canvas is large enough + // to draw each tile. + fTileWidth = current_width; while (current_width >= fTileMinPowerOf2Width) { // It is very important this is a bitwise AND. if (current_width & rounded_value) { - this->addTile(tile_x_start, tile_y_start, current_width, fTileHeight); + *fTileRects.append() = SkRect::MakeXYWH(SkIntToScalar(tile_x_start), + SkIntToScalar(tile_y_start), + SkIntToScalar(current_width), + SkIntToScalar(fTileHeight)); tile_x_start += current_width; } @@ -264,11 +253,7 @@ void TiledPictureRenderer::setupPowerOf2Tiles() { } void TiledPictureRenderer::deleteTiles() { - for (int i = 0; i < fTiles.count(); ++i) { - SkDELETE(fTiles[i]); - } - - fTiles.reset(); + fTileRects.reset(); } /////////////////////////////////////////////////////////////////////////////////////////////// @@ -317,8 +302,21 @@ CloneData::CloneData(SkCanvas* target, SkPicture* clone) /////////////////////////////////////////////////////////////////////////////////////////////// -void TiledPictureRenderer::drawTiles() { +void TiledPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) { + SkASSERT(fPicture != NULL); + if (NULL == fPicture) { + return; + } + + if (doExtraWorkToDrawToBaseCanvas) { + if (NULL == fCanvas.get()) { + fCanvas.reset(this->setupCanvas()); + } + } + if (fMultiThreaded) { + // FIXME: Turning off multi threading while we transition to using a pool of tiles +/* if (fUsePipe) { // First, draw into a pipe controller SkGPipeWriter writer; @@ -358,29 +356,36 @@ void TiledPictureRenderer::drawTiles() { SkDELETE(cloneData[i]); } } + */ } else { - for (int i = 0; i < fTiles.count(); ++i) { - fTiles[i]->drawPicture(*(fPicture)); - fTiles[i]->flush(); + // For single thread, we really only need one canvas total + SkCanvas* canvas = this->setupCanvas(fTileWidth, fTileHeight); + SkAutoUnref aur(canvas); + + // Clip the tile to an area that is completely in what the SkPicture says is the + // drawn-to area. This is mostly important for tiles on the right and bottom edges + // as they may go over this area and the picture may have some commands that + // draw outside of this area and so should not actually be written. + SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()), + SkIntToScalar(fPicture->height())); + for (int i = 0; i < fTileRects.count(); ++i) { + canvas->resetMatrix(); + canvas->clipRect(clip); + // Translate so that we draw the correct portion of the picture + canvas->translate(-fTileRects[i].fLeft, -fTileRects[i].fTop); + canvas->drawPicture(*(fPicture)); + canvas->flush(); + if (doExtraWorkToDrawToBaseCanvas) { + SkASSERT(fCanvas.get() != NULL); + SkBitmap source = canvas->getDevice()->accessBitmap(false); + fCanvas->drawBitmap(source, fTileRects[i].fLeft, fTileRects[i].fTop); + fCanvas->flush(); + } } } } -void TiledPictureRenderer::copyTilesToCanvas() { - for (int i = 0; i < fTiles.count(); ++i) { - // Since SkPicture performs a save and restore when being drawn to a - // canvas, we can be confident that the transform matrix of the canvas - // is what we set when creating the tiles. - SkMatrix matrix = fTiles[i]->getTotalMatrix(); - SkScalar tile_x_start = matrix.getTranslateX(); - SkScalar tile_y_start = matrix.getTranslateY(); - - SkBitmap source = fTiles[i]->getDevice()->accessBitmap(false); - - fCanvas->drawBitmap(source, -tile_x_start, -tile_y_start); - } - fCanvas->flush(); -} +/////////////////////////////////////////////////////////////////////////////////////////////// void PlaybackCreationRenderer::setup() { SkCanvas* recorder = fReplayer.beginRecording(fPicture->width(), fPicture->height()); diff --git a/tools/PictureRenderer.h b/tools/PictureRenderer.h index 9eeb03d..5ae3f29 100644 --- a/tools/PictureRenderer.h +++ b/tools/PictureRenderer.h @@ -11,6 +11,7 @@ #include "SkPicture.h" #include "SkTypes.h" #include "SkTDArray.h" +#include "SkRect.h" #include "SkRefCnt.h" #include "SkString.h" @@ -147,7 +148,6 @@ public: virtual void init(SkPicture* pict) SK_OVERRIDE; virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE; virtual void end() SK_OVERRIDE; - void drawTiles(); void setTileWidth(int width) { fTileWidth = width; @@ -194,26 +194,14 @@ public: return fTileMinPowerOf2Width; } - int numTiles() const { - return fTiles.count(); - } - void setMultiThreaded(bool multi) { fMultiThreaded = multi; } - bool isMultiThreaded() const { - return fMultiThreaded; - } - void setUsePipe(bool usePipe) { fUsePipe = usePipe; } - bool isUsePipe() const { - return fUsePipe; - } - ~TiledPictureRenderer(); private: @@ -225,18 +213,11 @@ private: double fTileHeightPercentage; int fTileMinPowerOf2Width; - SkTDArray fTiles; + SkTDArray fTileRects; - // Clips the tile to an area that is completely in what the SkPicture says is the - // drawn-to area. This is mostly important for tiles on the right and bottom edges - // as they may go over this area and the picture may have some commands that - // draw outside of this area and so should not actually be written. - void clipTile(SkCanvas* tile); - void addTile(int tile_x_start, int tile_y_start, int width, int height); void setupTiles(); void setupPowerOf2Tiles(); void deleteTiles(); - void copyTilesToCanvas(); typedef PictureRenderer INHERITED; }; -- 2.7.4