зеркало из https://github.com/mozilla/moz-skia.git
In render_pictures tiled rendering, draw a separate PNG for each tile.
Since the passed in picture may represent an image which is too large to be represented on the GPU, never create such a large canvas. Instead, after drawing to each tile, create a file showing just that tile. Review URL: https://codereview.appspot.com/6532056 git-svn-id: http://skia.googlecode.com/svn/trunk@5603 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
Родитель
bcdf2ec50d
Коммит
81f9d2e05b
|
@ -71,7 +71,7 @@ void PictureBenchmark::run(SkPicture* pict) {
|
||||||
|
|
||||||
// We throw this away to remove first time effects (such as paging in this program)
|
// We throw this away to remove first time effects (such as paging in this program)
|
||||||
fRenderer->setup();
|
fRenderer->setup();
|
||||||
fRenderer->render(false);
|
fRenderer->render(NULL);
|
||||||
fRenderer->resetState();
|
fRenderer->resetState();
|
||||||
|
|
||||||
BenchTimer* timer = this->setupTimer();
|
BenchTimer* timer = this->setupTimer();
|
||||||
|
|
|
@ -99,38 +99,43 @@ void PictureRenderer::resetState() {
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PictureRenderer::write(const SkString& path) const {
|
bool PictureRenderer::write(SkCanvas* canvas, SkString path) const {
|
||||||
SkASSERT(fCanvas.get() != NULL);
|
SkASSERT(canvas != NULL);
|
||||||
SkASSERT(fPicture != NULL);
|
SkASSERT(fPicture != NULL);
|
||||||
if (NULL == fCanvas.get() || NULL == fPicture) {
|
if (NULL == canvas || NULL == fPicture) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkBitmap bitmap;
|
SkBitmap bitmap;
|
||||||
sk_tools::setup_bitmap(&bitmap, fPicture->width(), fPicture->height());
|
SkISize size = canvas->getDeviceSize();
|
||||||
|
sk_tools::setup_bitmap(&bitmap, size.width(), size.height());
|
||||||
|
|
||||||
fCanvas->readPixels(&bitmap, 0, 0);
|
canvas->readPixels(&bitmap, 0, 0);
|
||||||
sk_tools::force_all_opaque(bitmap);
|
sk_tools::force_all_opaque(bitmap);
|
||||||
|
|
||||||
|
// Since path is passed in by value, it is okay to modify it.
|
||||||
|
path.append(".png");
|
||||||
return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
|
return SkImageEncoder::EncodeFile(path.c_str(), bitmap, SkImageEncoder::kPNG_Type, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void RecordPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
bool RecordPictureRenderer::render(const SkString*) {
|
||||||
SkPicture replayer;
|
SkPicture replayer;
|
||||||
SkCanvas* recorder = replayer.beginRecording(fPicture->width(), fPicture->height());
|
SkCanvas* recorder = replayer.beginRecording(fPicture->width(), fPicture->height());
|
||||||
fPicture->draw(recorder);
|
fPicture->draw(recorder);
|
||||||
replayer.endRecording();
|
replayer.endRecording();
|
||||||
|
// Since this class does not actually render, return false.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void PipePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
bool PipePictureRenderer::render(const SkString* path) {
|
||||||
SkASSERT(fCanvas.get() != NULL);
|
SkASSERT(fCanvas.get() != NULL);
|
||||||
SkASSERT(fPicture != NULL);
|
SkASSERT(fPicture != NULL);
|
||||||
if (NULL == fCanvas.get() || NULL == fPicture) {
|
if (NULL == fCanvas.get() || NULL == fPicture) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PipeController pipeController(fCanvas.get());
|
PipeController pipeController(fCanvas.get());
|
||||||
|
@ -139,19 +144,21 @@ void PipePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||||
pipeCanvas->drawPicture(*fPicture);
|
pipeCanvas->drawPicture(*fPicture);
|
||||||
writer.endRecording();
|
writer.endRecording();
|
||||||
fCanvas->flush();
|
fCanvas->flush();
|
||||||
|
return path != NULL && this->write(fCanvas, *path);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SimplePictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
bool SimplePictureRenderer::render(const SkString* path) {
|
||||||
SkASSERT(fCanvas.get() != NULL);
|
SkASSERT(fCanvas.get() != NULL);
|
||||||
SkASSERT(fPicture != NULL);
|
SkASSERT(fPicture != NULL);
|
||||||
if (NULL == fCanvas.get() || NULL == fPicture) {
|
if (NULL == fCanvas.get() || NULL == fPicture) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fCanvas->drawPicture(*fPicture);
|
fCanvas->drawPicture(*fPicture);
|
||||||
fCanvas->flush();
|
fCanvas->flush();
|
||||||
|
return path != NULL && this->write(fCanvas, *path);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -398,16 +405,10 @@ void TiledPictureRenderer::setup() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TiledPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
bool TiledPictureRenderer::render(const SkString* path) {
|
||||||
SkASSERT(fPicture != NULL);
|
SkASSERT(fPicture != NULL);
|
||||||
if (NULL == fPicture) {
|
if (NULL == fPicture) {
|
||||||
return;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
if (doExtraWorkToDrawToBaseCanvas) {
|
|
||||||
if (NULL == fCanvas.get()) {
|
|
||||||
fCanvas.reset(this->INHERITED::setupCanvas());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->multiThreaded()) {
|
if (this->multiThreaded()) {
|
||||||
|
@ -437,6 +438,8 @@ void TiledPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||||
SkDELETE(thread);
|
SkDELETE(thread);
|
||||||
}
|
}
|
||||||
threads.reset();
|
threads.reset();
|
||||||
|
// Currently multithreaded is not an option for render_pictures
|
||||||
|
return false;
|
||||||
} else {
|
} else {
|
||||||
// For single thread, we really only need one canvas total.
|
// For single thread, we really only need one canvas total.
|
||||||
SkCanvas* canvas = this->setupCanvas(fTileWidth, fTileHeight);
|
SkCanvas* canvas = this->setupCanvas(fTileWidth, fTileHeight);
|
||||||
|
@ -444,13 +447,15 @@ void TiledPictureRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
||||||
|
|
||||||
for (int i = 0; i < fTileRects.count(); ++i) {
|
for (int i = 0; i < fTileRects.count(); ++i) {
|
||||||
DrawTileToCanvas(canvas, fTileRects[i], fPicture);
|
DrawTileToCanvas(canvas, fTileRects[i], fPicture);
|
||||||
if (doExtraWorkToDrawToBaseCanvas) {
|
if (path != NULL) {
|
||||||
SkASSERT(fCanvas.get() != NULL);
|
SkString tilePath(*path);
|
||||||
SkBitmap source = canvas->getDevice()->accessBitmap(false);
|
tilePath.appendf("%i", i);
|
||||||
fCanvas->drawBitmap(source, fTileRects[i].fLeft, fTileRects[i].fTop);
|
if (!this->write(canvas, tilePath)) {
|
||||||
fCanvas->flush();
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return path != NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -474,8 +479,10 @@ void PlaybackCreationRenderer::setup() {
|
||||||
fPicture->draw(recorder);
|
fPicture->draw(recorder);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlaybackCreationRenderer::render(bool doExtraWorkToDrawToBaseCanvas) {
|
bool PlaybackCreationRenderer::render(const SkString*) {
|
||||||
fReplayer.endRecording();
|
fReplayer.endRecording();
|
||||||
|
// Since this class does not actually render, return false.
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,12 +47,12 @@ public:
|
||||||
/**
|
/**
|
||||||
* Perform work that is to be timed. Typically this is rendering, but is also used for recording
|
* Perform work that is to be timed. Typically this is rendering, but is also used for recording
|
||||||
* and preparing picture for playback by the subclasses which do those.
|
* and preparing picture for playback by the subclasses which do those.
|
||||||
* @param doExtraWorkToDrawToBaseCanvas Perform extra work to draw to fCanvas. Some subclasses
|
* If path is non-null, subclass implementations should call write().
|
||||||
* will automatically draw to fCanvas, but in the tiled
|
* @param path If non-null, also write the output to the file specified by path. path should
|
||||||
* case, for example, true needs to be passed so that
|
* have no extension; it will be added by write().
|
||||||
* the tiles will be stitched together on fCanvas.
|
* @return bool True if path is non-null and the output is successfully written to a file.
|
||||||
*/
|
*/
|
||||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) = 0;
|
virtual bool render(const SkString* path) = 0;
|
||||||
|
|
||||||
virtual void end();
|
virtual void end();
|
||||||
void resetState();
|
void resetState();
|
||||||
|
@ -95,9 +95,14 @@ public:
|
||||||
#endif
|
#endif
|
||||||
{}
|
{}
|
||||||
|
|
||||||
bool write(const SkString& path) const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/**
|
||||||
|
* Write the canvas to the specified path.
|
||||||
|
* @param canvas Must be non-null. Canvas to be written to a file.
|
||||||
|
* @param path Path for the file to be written. Should have no extension; write() will append
|
||||||
|
* an appropriate one.
|
||||||
|
*/
|
||||||
|
bool write(SkCanvas* canvas, SkString path) const;
|
||||||
SkCanvas* setupCanvas();
|
SkCanvas* setupCanvas();
|
||||||
virtual SkCanvas* setupCanvas(int width, int height);
|
virtual SkCanvas* setupCanvas(int width, int height);
|
||||||
|
|
||||||
|
@ -119,7 +124,7 @@ private:
|
||||||
* to time.
|
* to time.
|
||||||
*/
|
*/
|
||||||
class RecordPictureRenderer : public PictureRenderer {
|
class RecordPictureRenderer : public PictureRenderer {
|
||||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
virtual bool render(const SkString*) SK_OVERRIDE;
|
||||||
|
|
||||||
virtual SkString getPerIterTimeFormat() SK_OVERRIDE { return SkString("%.4f"); }
|
virtual SkString getPerIterTimeFormat() SK_OVERRIDE { return SkString("%.4f"); }
|
||||||
|
|
||||||
|
@ -128,7 +133,7 @@ class RecordPictureRenderer : public PictureRenderer {
|
||||||
|
|
||||||
class PipePictureRenderer : public PictureRenderer {
|
class PipePictureRenderer : public PictureRenderer {
|
||||||
public:
|
public:
|
||||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
virtual bool render(const SkString*) SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef PictureRenderer INHERITED;
|
typedef PictureRenderer INHERITED;
|
||||||
|
@ -136,7 +141,7 @@ private:
|
||||||
|
|
||||||
class SimplePictureRenderer : public PictureRenderer {
|
class SimplePictureRenderer : public PictureRenderer {
|
||||||
public:
|
public:
|
||||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
virtual bool render(const SkString*) SK_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef PictureRenderer INHERITED;
|
typedef PictureRenderer INHERITED;
|
||||||
|
@ -147,8 +152,16 @@ public:
|
||||||
TiledPictureRenderer();
|
TiledPictureRenderer();
|
||||||
|
|
||||||
virtual void init(SkPicture* pict) SK_OVERRIDE;
|
virtual void init(SkPicture* pict) SK_OVERRIDE;
|
||||||
|
|
||||||
virtual void setup() SK_OVERRIDE;
|
virtual void setup() SK_OVERRIDE;
|
||||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
|
||||||
|
/**
|
||||||
|
* Renders to tiles, rather than a single canvas. If a path is provided, a separate file is
|
||||||
|
* created for each tile, named "path0.png", "path1.png", etc.
|
||||||
|
* Multithreaded mode currently does not support writing to a file.
|
||||||
|
*/
|
||||||
|
virtual bool render(const SkString* path) SK_OVERRIDE;
|
||||||
|
|
||||||
virtual void end() SK_OVERRIDE;
|
virtual void end() SK_OVERRIDE;
|
||||||
|
|
||||||
void setTileWidth(int width) {
|
void setTileWidth(int width) {
|
||||||
|
@ -241,7 +254,7 @@ class PlaybackCreationRenderer : public PictureRenderer {
|
||||||
public:
|
public:
|
||||||
virtual void setup() SK_OVERRIDE;
|
virtual void setup() SK_OVERRIDE;
|
||||||
|
|
||||||
virtual void render(bool doExtraWorkToDrawToBaseCanvas) SK_OVERRIDE;
|
virtual bool render(const SkString*) SK_OVERRIDE;
|
||||||
|
|
||||||
virtual SkString getPerIterTimeFormat() SK_OVERRIDE { return SkString("%.4f"); }
|
virtual SkString getPerIterTimeFormat() SK_OVERRIDE { return SkString("%.4f"); }
|
||||||
|
|
||||||
|
|
|
@ -75,19 +75,8 @@ static void usage(const char* argv0) {
|
||||||
static void make_output_filepath(SkString* path, const SkString& dir,
|
static void make_output_filepath(SkString* path, const SkString& dir,
|
||||||
const SkString& name) {
|
const SkString& name) {
|
||||||
sk_tools::make_filepath(path, dir, name);
|
sk_tools::make_filepath(path, dir, name);
|
||||||
path->remove(path->size() - 3, 3);
|
// Remove ".skp"
|
||||||
path->append("png");
|
path->remove(path->size() - 4, 4);
|
||||||
}
|
|
||||||
|
|
||||||
static bool write_output(const SkString& outputDir, const SkString& inputFilename,
|
|
||||||
const sk_tools::PictureRenderer& renderer) {
|
|
||||||
SkString outputPath;
|
|
||||||
make_output_filepath(&outputPath, outputDir, inputFilename);
|
|
||||||
bool isWritten = renderer.write(outputPath);
|
|
||||||
if (!isWritten) {
|
|
||||||
SkDebugf("Could not write to file %s\n", outputPath.c_str());
|
|
||||||
}
|
|
||||||
return isWritten;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool render_picture(const SkString& inputPath, const SkString& outputDir,
|
static bool render_picture(const SkString& inputPath, const SkString& outputDir,
|
||||||
|
@ -118,12 +107,16 @@ static bool render_picture(const SkString& inputPath, const SkString& outputDir,
|
||||||
|
|
||||||
renderer.init(aur);
|
renderer.init(aur);
|
||||||
|
|
||||||
renderer.render(true);
|
SkString outputPath;
|
||||||
|
make_output_filepath(&outputPath, outputDir, inputFilename);
|
||||||
|
|
||||||
|
success = renderer.render(&outputPath);
|
||||||
|
if (!success) {
|
||||||
|
SkDebugf("Could not write to file %s\n", outputPath.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
renderer.resetState();
|
renderer.resetState();
|
||||||
|
|
||||||
success = write_output(outputDir, inputFilename, renderer);
|
|
||||||
|
|
||||||
renderer.end();
|
renderer.end();
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче