Refactored the bitmap creation into PictureRenderer.

Further, the picture is also stored in the PictureRenderer.

The main gain of all of this is that we will not have to change how the device in more than one place when we end up adding different devices.

Review URL: https://codereview.appspot.com/6458074

git-svn-id: http://skia.googlecode.com/svn/trunk@4990 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
keyar@chromium.org 2012-08-07 17:11:33 +00:00
parent 88e29146c1
commit 9d696c0d04
5 changed files with 175 additions and 67 deletions

View File

@ -16,28 +16,35 @@
namespace sk_tools {
void PipePictureBenchmark::run(SkPicture* pict) {
SkBitmap bitmap;
sk_tools::setup_bitmap(&bitmap, pict->width(), pict->height());
SkASSERT(pict);
if (pict == NULL) {
return;
}
SkCanvas canvas(bitmap);
renderer.init(*pict);
renderer.init(pict);
// We throw this away to remove first time effects (such as paging in this
// program)
renderer.render(pict, &canvas);
renderer.render();
BenchTimer timer = BenchTimer(NULL);
timer.start();
for (int i = 0; i < fRepeats; ++i) {
renderer.render(pict, &canvas);
renderer.render();
}
timer.end();
renderer.end();
SkDebugf("pipe: msecs = %6.2f\n", timer.fWall / fRepeats);
}
void RecordPictureBenchmark::run(SkPicture* pict) {
SkASSERT(pict);
if (pict == NULL) {
return;
}
BenchTimer timer = BenchTimer(NULL);
double wall_time = 0;
@ -59,46 +66,60 @@ void RecordPictureBenchmark::run(SkPicture* pict) {
}
void SimplePictureBenchmark::run(SkPicture* pict) {
SkBitmap bitmap;
sk_tools::setup_bitmap(&bitmap, pict->width(), pict->height());
SkASSERT(pict);
if (pict == NULL) {
return;
}
SkCanvas canvas(bitmap);
renderer.init(*pict);
renderer.init(pict);
// We throw this away to remove first time effects (such as paging in this
// program)
renderer.render(pict, &canvas);
renderer.render();
BenchTimer timer = BenchTimer(NULL);
timer.start();
for (int i = 0; i < fRepeats; ++i) {
renderer.render(pict, &canvas);
renderer.render();
}
timer.end();
renderer.end();
printf("simple: msecs = %6.2f\n", timer.fWall / fRepeats);
}
void TiledPictureBenchmark::run(SkPicture* pict) {
renderer.init(*pict);
SkASSERT(pict);
if (pict == NULL) {
return;
}
renderer.init(pict);
// We throw this away to remove first time effects (such as paging in this
// program)
renderer.drawTiles(pict);
renderer.drawTiles();
BenchTimer timer = BenchTimer(NULL);
timer.start();
for (int i = 0; i < fRepeats; ++i) {
renderer.drawTiles(pict);
renderer.drawTiles();
}
timer.end();
renderer.end();
SkDebugf("%i_tiles_%ix%i: msecs = %6.2f\n", renderer.numTiles(), renderer.getTileWidth(),
renderer.getTileHeight(), timer.fWall / fRepeats);
}
void UnflattenPictureBenchmark::run(SkPicture* pict) {
SkASSERT(pict);
if (pict == NULL) {
return;
}
BenchTimer timer = BenchTimer(NULL);
double wall_time = 0;

View File

@ -30,30 +30,37 @@ public:
protected:
int fRepeats;
private:
typedef SkRefCnt INHERITED;
};
class PipePictureBenchmark : public PictureBenchmark {
public:
virtual void run(SkPicture* pict);
virtual void run(SkPicture* pict) SK_OVERRIDE;
private:
PipePictureRenderer renderer;
typedef PictureBenchmark INHERITED;
};
class RecordPictureBenchmark : public PictureBenchmark {
public:
virtual void run(SkPicture* pict);
virtual void run(SkPicture* pict) SK_OVERRIDE;
private:
typedef PictureBenchmark INHERITED;
};
class SimplePictureBenchmark : public PictureBenchmark {
public:
virtual void run(SkPicture* pict);
virtual void run(SkPicture* pict) SK_OVERRIDE;
private:
SimplePictureRenderer renderer;
typedef PictureBenchmark INHERITED;
};
class TiledPictureBenchmark : public PictureBenchmark {
public:
virtual void run(SkPicture* pict);
virtual void run(SkPicture* pict) SK_OVERRIDE;
void setTileWidth(int width) {
renderer.setTileWidth(width);
@ -89,11 +96,14 @@ public:
private:
TiledPictureRenderer renderer;
typedef PictureBenchmark INHERITED;
};
class UnflattenPictureBenchmark : public PictureBenchmark {
public:
virtual void run(SkPicture* pict);
virtual void run(SkPicture* pict) SK_OVERRIDE;
private:
typedef PictureBenchmark INHERITED;
};
}

View File

@ -15,52 +15,103 @@ enum {
kDefaultTileHeight = 256
};
void PipePictureRenderer::render(SkPicture* pict, SkCanvas* canvas) {
PipeController pipeController(canvas);
void PictureRenderer::init(SkPicture* pict) {
SkASSERT(fPicture == NULL);
SkASSERT(fCanvas.get() == NULL);
if (fPicture != NULL || fCanvas.get() != NULL) {
return;
}
SkASSERT(pict != NULL);
if (pict == NULL) {
return;
}
fPicture = pict;
SkBitmap bitmap;
sk_tools::setup_bitmap(&bitmap, fPicture->width(), fPicture->height());
fCanvas.reset(SkNEW_ARGS(SkCanvas, (bitmap)));
}
void PictureRenderer::end() {
fPicture = NULL;
fCanvas.reset(NULL);
}
void PipePictureRenderer::render() {
SkASSERT(fCanvas.get() != NULL);
SkASSERT(fPicture != NULL);
if (fCanvas.get() == NULL || fPicture == NULL) {
return;
}
PipeController pipeController(fCanvas.get());
SkGPipeWriter writer;
SkCanvas* pipeCanvas = writer.startRecording(&pipeController);
pipeCanvas->drawPicture(*pict);
pipeCanvas->drawPicture(*fPicture);
writer.endRecording();
}
void SimplePictureRenderer::render(SkPicture* pict, SkCanvas* canvas) {
canvas->drawPicture(*pict);
void SimplePictureRenderer::render() {
SkASSERT(fCanvas.get() != NULL);
SkASSERT(fPicture != NULL);
if (fCanvas.get() == NULL || fPicture == NULL) {
return;
}
fCanvas->drawPicture(*fPicture);
}
TiledPictureRenderer::TiledPictureRenderer()
: fTileWidth(kDefaultTileWidth)
, fTileHeight(kDefaultTileHeight) {}
void TiledPictureRenderer::init(const SkPicture& pict) {
deleteTiles();
void TiledPictureRenderer::init(SkPicture* pict) {
SkASSERT(pict != NULL);
SkASSERT(fTiles.count() == 0);
if (pict == NULL || fTiles.count() != 0) {
return;
}
this->INHERITED::init(pict);
if (fTileWidthPercentage > 0) {
fTileWidth = sk_float_ceil2int(fTileWidthPercentage * pict.width() / 100);
fTileWidth = sk_float_ceil2int(fTileWidthPercentage * fPicture->width() / 100);
}
if (fTileHeightPercentage > 0) {
fTileHeight = sk_float_ceil2int(fTileHeightPercentage * pict.height() / 100);
fTileHeight = sk_float_ceil2int(fTileHeightPercentage * fPicture->height() / 100);
}
setupTiles(pict);
this->setupTiles();
}
void TiledPictureRenderer::render(SkPicture* pict, SkCanvas* canvas) {
drawTiles(pict);
void TiledPictureRenderer::render() {
SkASSERT(fCanvas.get() != NULL);
SkASSERT(fPicture != NULL);
if (fCanvas.get() == NULL || fPicture == NULL) {
return;
}
copyTilesToCanvas(*pict, canvas);
this->drawTiles();
this->copyTilesToCanvas();
}
void TiledPictureRenderer::end() {
this->deleteTiles();
this->INHERITED::end();
}
TiledPictureRenderer::~TiledPictureRenderer() {
deleteTiles();
this->deleteTiles();
}
void TiledPictureRenderer::clipTile(const SkPicture& picture, const TileInfo& tile) {
SkRect clip = SkRect::MakeWH(SkIntToScalar(picture.width()),
SkIntToScalar(picture.height()));
void TiledPictureRenderer::clipTile(const TileInfo& tile) {
SkRect clip = SkRect::MakeWH(SkIntToScalar(fPicture->width()),
SkIntToScalar(fPicture->height()));
tile.fCanvas->clipRect(clip);
}
void TiledPictureRenderer::addTile(const SkPicture& picture, int tile_x_start, int tile_y_start) {
void TiledPictureRenderer::addTile(int tile_x_start, int tile_y_start) {
TileInfo* tile = fTiles.push();
tile->fBitmap = SkNEW(SkBitmap);
@ -68,15 +119,15 @@ void TiledPictureRenderer::addTile(const SkPicture& picture, int tile_x_start, i
tile->fCanvas = SkNEW_ARGS(SkCanvas, (*(tile->fBitmap)));
tile->fCanvas->translate(SkIntToScalar(-tile_x_start), SkIntToScalar(-tile_y_start));
clipTile(picture, *tile);
this->clipTile(*tile);
}
void TiledPictureRenderer::setupTiles(const SkPicture& picture) {
for (int tile_y_start = 0; tile_y_start < picture.height();
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 < picture.width();
for (int tile_x_start = 0; tile_x_start < fPicture->width();
tile_x_start += fTileWidth) {
addTile(picture, tile_x_start, tile_y_start);
this->addTile(tile_x_start, tile_y_start);
}
}
}
@ -90,23 +141,23 @@ void TiledPictureRenderer::deleteTiles() {
fTiles.reset();
}
void TiledPictureRenderer::drawTiles(SkPicture* pict) {
void TiledPictureRenderer::drawTiles() {
for (int i = 0; i < fTiles.count(); ++i) {
fTiles[i].fCanvas->drawPicture(*pict);
fTiles[i].fCanvas->drawPicture(*(fPicture));
}
}
void TiledPictureRenderer::copyTilesToCanvas(const SkPicture& pict, SkCanvas* destination) {
void TiledPictureRenderer::copyTilesToCanvas() {
int tile_index = 0;
for (int tile_y_start = 0; tile_y_start < pict.height();
for (int tile_y_start = 0; tile_y_start < fPicture->height();
tile_y_start += fTileHeight) {
for (int tile_x_start = 0; tile_x_start < pict.width();
for (int tile_x_start = 0; tile_x_start < fPicture->width();
tile_x_start += fTileWidth) {
SkASSERT(tile_index < fTiles.count());
SkBitmap source = fTiles[tile_index].fCanvas->getDevice()->accessBitmap(false);
destination->drawBitmap(source,
SkIntToScalar(tile_x_start),
SkIntToScalar(tile_y_start));
fCanvas->drawBitmap(source,
SkIntToScalar(tile_x_start),
SkIntToScalar(tile_y_start));
++tile_index;
}
}

View File

@ -19,27 +19,47 @@ namespace sk_tools {
class PictureRenderer : public SkRefCnt {
public:
virtual void init(const SkPicture& pict){}
virtual void render(SkPicture* pict, SkCanvas* canvas) = 0;
virtual void init(SkPicture* pict);
virtual void render() = 0;
virtual void end();
SkCanvas* getCanvas() {
return fCanvas.get();
}
PictureRenderer() : fPicture(NULL){}
protected:
SkAutoTUnref<SkCanvas> fCanvas;
SkPicture* fPicture;
private:
typedef SkRefCnt INHERITED;
};
class PipePictureRenderer : public PictureRenderer {
public:
virtual void render(SkPicture* pict, SkCanvas* canvas);
virtual void render() SK_OVERRIDE;
private:
typedef PictureRenderer INHERITED;
};
class SimplePictureRenderer : public PictureRenderer {
public:
virtual void render (SkPicture* pict, SkCanvas* canvas);
virtual void render () SK_OVERRIDE;
private:
typedef PictureRenderer INHERITED;
};
class TiledPictureRenderer : public PictureRenderer {
public:
TiledPictureRenderer();
virtual void init(const SkPicture& pict);
virtual void render(SkPicture* pict, SkCanvas* canvas);
void drawTiles(SkPicture* pict);
virtual void init(SkPicture* pict) SK_OVERRIDE;
virtual void render() SK_OVERRIDE;
virtual void end() SK_OVERRIDE;
void drawTiles();
void setTileWidth(int width) {
fTileWidth = width;
@ -96,14 +116,16 @@ private:
// 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.
static void clipTile(const SkPicture& picture, const TileInfo& tile);
void addTile(const SkPicture& picture, int tile_x_start, int tile_y_start);
void setupTiles(const SkPicture& picture);
void clipTile(const TileInfo& tile);
void addTile(int tile_x_start, int tile_y_start);
void setupTiles();
// We manually delete the tiles instead of having a destructor on TileInfo as
// the destructor on TileInfo will be during a realloc. This would result in
// the canvases and bitmaps being prematurely deleted.
void deleteTiles();
void copyTilesToCanvas(const SkPicture& pict, SkCanvas* destination);
void copyTilesToCanvas();
typedef PictureRenderer INHERITED;
};
}

View File

@ -96,11 +96,15 @@ static void render_picture(const SkString& inputPath, const SkString& outputDir,
SkPicture picture(&inputStream);
SkBitmap bitmap;
sk_tools::setup_bitmap(&bitmap, picture.width(), picture.height());
SkCanvas canvas(bitmap);
renderer.init(picture);
renderer.render(&picture, &canvas);
renderer.init(&picture);
renderer.render();
renderer.getCanvas()->readPixels(&bitmap, 0, 0);
write_output(outputDir, inputFilename, bitmap);
renderer.end();
}
static void process_input(const SkString& input, const SkString& outputDir,