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
This commit is contained in:
scroggo@google.com 2012-06-06 21:07:10 +00:00
parent 47059542e7
commit 72c9672ce2
6 changed files with 166 additions and 43 deletions

View File

@ -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],

View File

@ -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',

View File

@ -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,

View File

@ -545,12 +545,21 @@ SkGPipeState::~SkGPipeState() {
#include "SkGPipe.h"
SkGPipeReader::SkGPipeReader(SkCanvas* target) {
SkSafeRef(target);
fCanvas = target;
SkGPipeReader::SkGPipeReader() {
fCanvas = NULL;
fState = NULL;
}
SkGPipeReader::SkGPipeReader(SkCanvas* target) {
fCanvas = NULL;
this->setCanvas(target);
fState = NULL;
}
void SkGPipeReader::setCanvas(SkCanvas *target) {
SkRefCnt_SafeAssign(fCanvas, target);
}
SkGPipeReader::~SkGPipeReader() {
SkSafeUnref(fCanvas);
delete fState;

View File

@ -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);
}

View File

@ -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;
};