From 72c9672ce274a3b6cb40800d66374edf25b157a3 Mon Sep 17 00:00:00 2001 From: "scroggo@google.com" Date: Wed, 6 Jun 2012 21:07:10 +0000 Subject: Add tiled rendering as an option to GM. Use an SkGPipe to play back drawing into tiles. This will help us to debug differences in drawing while tiled. Pass --tiledPipe to gm to use the tiled pipe. Review URL: https://codereview.appspot.com/6295050 git-svn-id: http://skia.googlecode.com/svn/trunk@4199 2bbb7eff-a529-9590-31e7-b0007b416f81 --- gm/gmmain.cpp | 75 +++++++++++++++----------------- gyp/gm.gyp | 2 + include/pipe/SkGPipe.h | 2 + src/pipe/SkGPipeRead.cpp | 13 +++++- src/pipe/utils/SamplePipeControllers.cpp | 72 ++++++++++++++++++++++++++++++ src/pipe/utils/SamplePipeControllers.h | 43 ++++++++++++++++++ 6 files changed, 165 insertions(+), 42 deletions(-) create mode 100644 src/pipe/utils/SamplePipeControllers.cpp create mode 100644 src/pipe/utils/SamplePipeControllers.h diff --git a/gm/gmmain.cpp b/gm/gmmain.cpp index 08c7c52151..34ded4af9b 100644 --- a/gm/gmmain.cpp +++ b/gm/gmmain.cpp @@ -20,8 +20,9 @@ #include "SkImageDecoder.h" #include "SkImageEncoder.h" #include "SkPicture.h" -#include "SkStream.h" #include "SkRefCnt.h" +#include "SkStream.h" +#include "SamplePipeControllers.h" static bool gForceBWtext; @@ -619,45 +620,6 @@ static ErrorBitfield test_picture_serialization(GM* gm, } } -class PipeController : public SkGPipeController { -public: - PipeController(SkCanvas* target); - ~PipeController(); - virtual void* requestBlock(size_t minRequest, size_t* actual); - virtual void notifyWritten(size_t bytes); -private: - SkGPipeReader fReader; - void* fBlock; - size_t fBlockSize; - size_t fBytesWritten; - SkGPipeReader::Status fStatus; -}; - -PipeController::PipeController(SkCanvas* target) -:fReader(target) { - fBlock = NULL; - fBlockSize = fBytesWritten = 0; -} - -PipeController::~PipeController() { - sk_free(fBlock); -} - -void* PipeController::requestBlock(size_t minRequest, size_t *actual) { - sk_free(fBlock); - fBlockSize = minRequest * 4; - fBlock = sk_malloc_throw(fBlockSize); - fBytesWritten = 0; - *actual = fBlockSize; - return fBlock; -} - -void PipeController::notifyWritten(size_t bytes) { - fStatus = fReader.playback((const char*)fBlock + fBytesWritten, bytes); - SkASSERT(SkGPipeReader::kError_Status != fStatus); - fBytesWritten += bytes; -} - static ErrorBitfield test_pipe_playback(GM* gm, const ConfigData& gRec, const SkBitmap& comparisonBitmap, @@ -680,6 +642,27 @@ static ErrorBitfield test_pipe_playback(GM* gm, "-pipe", bitmap, NULL, &comparisonBitmap); } +static ErrorBitfield test_tiled_pipe_playback(GM* gm, + const ConfigData& gRec, + const SkBitmap& comparisonBitmap, + const char readPath [], + const char diffPath []) { + if (kRaster_Backend != gRec.fBackend) { + return ERROR_NONE; + } + SkBitmap bitmap; + SkISize size = gm->getISize(); + setup_bitmap(gRec, size, &bitmap); + TiledPipeController pipeController(bitmap); + SkGPipeWriter writer; + SkCanvas* pipeCanvas = writer.startRecording(&pipeController, + SkGPipeWriter::kCrossProcess_Flag); + invokeGM(gm, pipeCanvas); + writer.endRecording(); + return handle_test_results(gm, gRec, NULL, NULL, diffPath, + "-tiled pipe", bitmap, NULL, &comparisonBitmap); +} + static void write_picture_serialization(GM* gm, const ConfigData& rec, const char writePicturePath[]) { // only do this once, so we pick raster @@ -701,6 +684,7 @@ static void usage(const char * argv0) { SkDebugf( "%s [-w writePath] [-r readPath] [-d diffPath] [-i resourcePath]\n" " [--noreplay] [--pipe] [--serialize] [--forceBWtext] [--nopdf] \n" + " [--tiledPipe] \n" " [--nodeferred] [--match substring] [--notexturecache]\n" , argv0); SkDebugf(" writePath: directory to write rendered images in.\n"); @@ -711,6 +695,7 @@ static void usage(const char * argv0) { SkDebugf(" resourcePath: directory that stores image resources.\n"); SkDebugf(" --noreplay: do not exercise SkPicture replay.\n"); SkDebugf(" --pipe: Exercise SkGPipe replay.\n"); + SkDebugf(" --tiledPipe: Exercise tiled SkGPipe replay.\n"); SkDebugf( " --serialize: exercise SkPicture serialization & deserialization.\n"); SkDebugf(" --forceBWtext: disable text anti-aliasing.\n"); @@ -823,6 +808,7 @@ int main(int argc, char * const argv[]) { bool doPDF = true; bool doReplay = true; bool doPipe = false; + bool doTiledPipe = false; bool doSerialize = false; bool doDeferred = true; bool disableTextureCache = false; @@ -861,6 +847,8 @@ int main(int argc, char * const argv[]) { gForceBWtext = true; } else if (strcmp(*argv, "--pipe") == 0) { doPipe = true; + } else if (strcmp(*argv, "--tiledPipe") == 0) { + doTiledPipe = true; } else if (strcmp(*argv, "--noreplay") == 0) { doReplay = false; } else if (strcmp(*argv, "--nopdf") == 0) { @@ -1007,6 +995,13 @@ int main(int argc, char * const argv[]) { readPath, diffPath); } + if ((ERROR_NONE == testErrors) && doTiledPipe && + !(gmFlags & GM::kSkipPipe_Flag)) { + testErrors |= test_tiled_pipe_playback(gm, gRec[i], + forwardRenderedBitmap, + readPath, diffPath); + } + if ((ERROR_NONE == testErrors) && doSerialize && !(gmFlags & GM::kSkipPicture_Flag)) { testErrors |= test_picture_serialization(gm, gRec[i], diff --git a/gyp/gm.gyp b/gyp/gm.gyp index 980c199bdc..c3f359c37e 100644 --- a/gyp/gm.gyp +++ b/gyp/gm.gyp @@ -17,6 +17,8 @@ '../gm/gm.cpp', '../gm/gmmain.cpp', '../gm/system_preferences_default.cpp', + '../src/pipe/utils/SamplePipeControllers.h', + '../src/pipe/utils/SamplePipeControllers.cpp', ], 'dependencies': [ 'core.gyp:core', diff --git a/include/pipe/SkGPipe.h b/include/pipe/SkGPipe.h index 29b058eb2d..e0b52e044b 100644 --- a/include/pipe/SkGPipe.h +++ b/include/pipe/SkGPipe.h @@ -23,6 +23,7 @@ class SkCanvas; class SkGPipeReader { public: + SkGPipeReader(); SkGPipeReader(SkCanvas* target); ~SkGPipeReader(); @@ -33,6 +34,7 @@ public: kReadAtom_Status//!< finished reading an atom }; + void setCanvas(SkCanvas*); // data must be 4-byte aligned // length must be a multiple of 4 Status playback(const void* data, size_t length, size_t* bytesRead = NULL, diff --git a/src/pipe/SkGPipeRead.cpp b/src/pipe/SkGPipeRead.cpp index 976abbf10a..ddc0cc41d9 100644 --- a/src/pipe/SkGPipeRead.cpp +++ b/src/pipe/SkGPipeRead.cpp @@ -545,12 +545,21 @@ SkGPipeState::~SkGPipeState() { #include "SkGPipe.h" +SkGPipeReader::SkGPipeReader() { + fCanvas = NULL; + fState = NULL; +} + SkGPipeReader::SkGPipeReader(SkCanvas* target) { - SkSafeRef(target); - fCanvas = target; + fCanvas = NULL; + this->setCanvas(target); fState = NULL; } +void SkGPipeReader::setCanvas(SkCanvas *target) { + SkRefCnt_SafeAssign(fCanvas, target); +} + SkGPipeReader::~SkGPipeReader() { SkSafeUnref(fCanvas); delete fState; diff --git a/src/pipe/utils/SamplePipeControllers.cpp b/src/pipe/utils/SamplePipeControllers.cpp new file mode 100644 index 0000000000..487a2b8356 --- /dev/null +++ b/src/pipe/utils/SamplePipeControllers.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SamplePipeControllers.h" +#include "SkCanvas.h" +#include "SkDevice.h" +#include "SkGPipe.h" + +PipeController::PipeController(SkCanvas* target) +:fReader(target) { + fBlock = NULL; + fBlockSize = fBytesWritten = 0; +} + +PipeController::~PipeController() { + sk_free(fBlock); +} + +void* PipeController::requestBlock(size_t minRequest, size_t *actual) { + sk_free(fBlock); + fBlockSize = minRequest * 4; + fBlock = sk_malloc_throw(fBlockSize); + fBytesWritten = 0; + *actual = fBlockSize; + return fBlock; +} + +void PipeController::notifyWritten(size_t bytes) { + fStatus = fReader.playback(this->getData(), bytes); + SkASSERT(SkGPipeReader::kError_Status != fStatus); + fBytesWritten += bytes; +} + +//////////////////////////////////////////////////////////////////////////////// + +TiledPipeController::TiledPipeController(const SkBitmap& bitmap) +: INHERITED(NULL) { + int32_t top = 0; + int32_t bottom; + int32_t height = bitmap.height() / NumberOfTiles; + SkIRect rect; + for (int i = 0; i < NumberOfTiles; i++) { + bottom = i + 1 == NumberOfTiles ? bitmap.height() : top + height; + rect.setLTRB(0, top, bitmap.width(), bottom); + top = bottom; + + bool extracted = bitmap.extractSubset(&fBitmaps[i], rect); + SkASSERT(extracted); + SkDevice* device = new SkDevice(fBitmaps[i]); + SkCanvas* canvas = new SkCanvas(device); + device->unref(); + canvas->translate(SkIntToScalar(-rect.left()), + SkIntToScalar(-rect.top())); + if (0 == i) { + fReader.setCanvas(canvas); + } else { + fReaders[i - 1].setCanvas(canvas); + } + canvas->unref(); + } +} + +void TiledPipeController::notifyWritten(size_t bytes) { + for (int i = 0; i < NumberOfTiles - 1; i++) { + fReaders[i].playback(this->getData(), bytes); + } + this->INHERITED::notifyWritten(bytes); +} diff --git a/src/pipe/utils/SamplePipeControllers.h b/src/pipe/utils/SamplePipeControllers.h new file mode 100644 index 0000000000..ace6274bae --- /dev/null +++ b/src/pipe/utils/SamplePipeControllers.h @@ -0,0 +1,43 @@ +/* + * Copyright 2012 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBitmap.h" +#include "SkGPipe.h" + +class SkCanvas; + +class PipeController : public SkGPipeController { +public: + PipeController(SkCanvas* target); + virtual ~PipeController(); + virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE; + virtual void notifyWritten(size_t bytes) SK_OVERRIDE; +protected: + const void* getData() { return (const char*) fBlock + fBytesWritten; } + SkGPipeReader fReader; +private: + void* fBlock; + size_t fBlockSize; + size_t fBytesWritten; + SkGPipeReader::Status fStatus; +}; + +//////////////////////////////////////////////////////////////////////////////// + +class TiledPipeController : public PipeController { +public: + TiledPipeController(const SkBitmap&); + virtual ~TiledPipeController() {}; + virtual void notifyWritten(size_t bytes) SK_OVERRIDE; +private: + enum { + NumberOfTiles = 10 + }; + SkGPipeReader fReaders[NumberOfTiles - 1]; + SkBitmap fBitmaps[NumberOfTiles]; + typedef PipeController INHERITED; +}; -- cgit v1.2.3