enum benchModes {
kNormal_benchModes,
kDeferred_benchModes,
+ kDeferredSilent_benchModes,
kRecord_benchModes,
kPictureRecord_benchModes
};
"[--timers [wcgWC]*] [--rotate]\n"
" [--scale] [--clip] [--min] [--forceAA 1|0] [--forceFilter 1|0]\n"
" [--forceDither 1|0] [--forceBlend 1|0] [--strokeWidth width]\n"
- " [--match name] [--mode normal|deferred|record|picturerecord]\n"
+ " [--match name] [--mode normal|deferred|deferredSilent|record|picturerecord]\n"
" [--config 8888|565|GPU|ANGLE|NULLGPU] [-Dfoo bar] [--logFile filename]\n"
" [-h|--help]");
SkDebugf("\n\n");
"Enable/disable dithering, default is disabled.\n");
SkDebugf(" --strokeWidth width : The width for path stroke.\n");
SkDebugf(" --match name : Only run bench whose name is matched.\n");
- SkDebugf(" --mode normal|deferred|record|picturerecord : Run in the corresponding mode\n"
+ SkDebugf(" --mode normal|deferred|deferredSilent|record|picturerecord :\n"
+ " Run in the corresponding mode\n"
" normal, Use a normal canvas to draw to;\n"
" deferred, Use a deferrred canvas when drawing;\n"
+ " deferredSilent, deferred with silent playback;\n"
" record, Benchmark the time to record to an SkPicture;\n"
" picturerecord, Benchmark the time to do record from a \n"
" SkPicture to a SkPicture.\n");
benchMode = kNormal_benchModes;
} else if (strcmp(*argv, "deferred") == 0) {
benchMode = kDeferred_benchModes;
+ } else if (strcmp(*argv, "deferredSilent") == 0) {
+ benchMode = kDeferredSilent_benchModes;
} else if (strcmp(*argv, "record") == 0) {
benchMode = kRecord_benchModes;
} else if (strcmp(*argv, "picturerecord") == 0) {
// report our current settings
{
SkString str;
+ const char* deferredMode = benchMode == kDeferred_benchModes ? "yes" :
+ (benchMode == kDeferredSilent_benchModes ? "silent" : "no");
str.printf("skia bench: alpha=0x%02X antialias=%d filter=%d "
- "deferred=%d logperiter=%d",
- forceAlpha, forceAA, forceFilter, benchMode == kDeferred_benchModes,
+ "deferred=%s logperiter=%d",
+ forceAlpha, forceAA, forceFilter, deferredMode,
logPerIter);
str.appendf(" rotate=%d scale=%d clip=%d min=%d",
doRotate, doScale, doClip, printMin);
SkPicture pictureRecordFrom;
SkPicture pictureRecordTo;
switch(benchMode) {
+ case kDeferredSilent_benchModes:
case kDeferred_benchModes:
canvas = new SkDeferredCanvas(device);
break;
} else {
bench->draw(canvas);
}
- canvas->flush();
+
+ if (kDeferredSilent_benchModes == benchMode) {
+ static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
+ } else {
+ canvas->flush();
+ }
#if SK_SUPPORT_GPU
if (glHelper) {
glHelper->grContext()->flush();
} else {
bench->draw(canvas);
}
- canvas->flush();
+
+ if (kDeferredSilent_benchModes == benchMode) {
+ static_cast<SkDeferredCanvas*>(canvas)->silentFlush();
+ } else {
+ canvas->flush();
+ }
// stop the truncated timer after the last canvas call but
// don't wait for all the GL calls to complete
int frameBound = 0;
size_t bytesRead;
while (static_cast<unsigned>(offset) < size) {
- SkGPipeReader::Status s = dumpReader->playback(data + offset,
- size - offset,
- &bytesRead,
- true);
+ SkGPipeReader::Status s =
+ dumpReader->playback(data + offset, size - offset,
+ SkGPipeReader::kReadAtom_PlaybackFlag, &bytesRead);
SkASSERT(SkGPipeReader::kError_Status != s);
offset += bytesRead;
SkGPipeReader::Status s;
//Read the first chunk
if (offset < firstChunk && firstChunk < toBeRead) {
- s = dumpReader->playback(fData.begin() + offset, firstChunk - offset, NULL, false);
+ s = dumpReader->playback(fData.begin() + offset, firstChunk - offset);
SkASSERT(SkGPipeReader::kError_Status != s);
- s = reader->playback(fData.begin() + offset, firstChunk - offset, &bytesRead, false);
+ s = reader->playback(fData.begin() + offset, firstChunk - offset, 0, &bytesRead);
SkASSERT(SkGPipeReader::kError_Status != s);
if (SkGPipeReader::kDone_Status == s){
delete dumpReader;
SkASSERT(offset == firstChunk);
//Then read the current atom
fDumper->enable();
- s = dumpReader->playback(fData.begin() + offset, toBeRead - offset, NULL, true);
+ s = dumpReader->playback(fData.begin() + offset, toBeRead - offset,
+ SkGPipeReader::kReadAtom_PlaybackFlag);
SkASSERT(SkGPipeReader::kError_Status != s);
- s = reader->playback(fData.begin() + offset, toBeRead - offset, &bytesRead, true);
+ s = reader->playback(fData.begin() + offset, toBeRead - offset,
+ SkGPipeReader::kReadAtom_PlaybackFlag, &bytesRead);
SkASSERT(SkGPipeReader::kError_Status != s);
delete reader;
kReadAtom_Status//!< finished reading an atom
};
+ enum PlaybackFlags {
+ kReadAtom_PlaybackFlag = 0x1, //!< playback a single command from the stream
+ kSilent_PlaybackFlag = 0x2, //!< playback without drawing
+ };
+
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,
- bool readAtom = false);
+ Status playback(const void* data, size_t length, uint32_t playbackFlags = 0,
+ size_t* bytesRead = NULL);
private:
SkCanvas* fCanvas;
class SkGPipeState* fState;
*/
size_t freeMemoryIfPossible(size_t bytesToFree);
+ /**
+ * Executes all pending commands without drawing
+ */
+ void silentFlush();
+
// Overrides of the SkCanvas interface
virtual int save(SaveFlags flags) SK_OVERRIDE;
virtual int saveLayer(const SkRect* bounds, const SkPaint* paint,
SkGPipeState();
~SkGPipeState();
+ void setSilent(bool silent) {
+ fSilent = silent;
+ }
+
+ bool shouldDraw() {
+ return !fSilent;
+ }
+
void setFlags(unsigned flags) {
if (fFlags != flags) {
fFlags = flags;
SkTDArray<SkTypeface*> fTypefaces;
SkTDArray<SkFlattenable::Factory> fFactoryArray;
SkTDArray<SkBitmap*> fBitmaps;
+ bool fSilent;
// Only used when sharing bitmaps with the writer.
SkBitmapHeap* fSharedHeap;
unsigned fFlags;
static void drawPaint_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
- canvas->drawPaint(state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawPaint(state->paint());
+ }
}
static void drawPoints_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkCanvas::PointMode mode = (SkCanvas::PointMode)DrawOp_unpackFlags(op32);
size_t count = reader->readU32();
const SkPoint* pts = skip<SkPoint>(reader, count);
- canvas->drawPoints(mode, count, pts, state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawPoints(mode, count, pts, state->paint());
+ }
}
static void drawRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
- canvas->drawRect(*skip<SkRect>(reader), state->paint());
+ const SkRect* rect = skip<SkRect>(reader);
+ if (state->shouldDraw()) {
+ canvas->drawRect(*rect, state->paint());
+ }
}
static void drawPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkPath path;
reader->readPath(&path);
- canvas->drawPath(path, state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawPath(path, state->paint());
+ }
}
static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
indexCount = reader->readU32();
indices = skipAlign<uint16_t>(reader, indexCount);
}
-
- canvas->drawVertices(mode, vertexCount, verts, texs, colors, xfer,
- indices, indexCount, state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawVertices(mode, vertexCount, verts, texs, colors, xfer,
+ indices, indexCount, state->paint());
+ }
}
///////////////////////////////////////////////////////////////////////////////
size_t len = reader->readU32();
const void* text = reader->skip(SkAlign4(len));
const SkScalar* xy = skip<SkScalar>(reader, 2);
- canvas->drawText(text, len, xy[0], xy[1], state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawText(text, len, xy[0], xy[1], state->paint());
+ }
}
static void drawPosText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
const void* text = reader->skip(SkAlign4(len));
size_t posCount = reader->readU32(); // compute by our writer
const SkPoint* pos = skip<SkPoint>(reader, posCount);
- canvas->drawPosText(text, len, pos, state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawPosText(text, len, pos, state->paint());
+ }
}
static void drawPosTextH_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
size_t posCount = reader->readU32(); // compute by our writer
const SkScalar* xpos = skip<SkScalar>(reader, posCount);
SkScalar constY = reader->readScalar();
- canvas->drawPosTextH(text, len, xpos, constY, state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawPosTextH(text, len, xpos, constY, state->paint());
+ }
}
static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
reader->readMatrix(&matrixStorage);
matrix = &matrixStorage;
}
-
- canvas->drawTextOnPath(text, len, path, matrix, state->paint());
+ if (state->shouldDraw()) {
+ canvas->drawTextOnPath(text, len, path, matrix, state->paint());
+ }
}
///////////////////////////////////////////////////////////////////////////////
bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpFlag);
SkScalar left = reader->readScalar();
SkScalar top = reader->readScalar();
- canvas->drawBitmap(*holder.getBitmap(), left, top, hasPaint ? &state->paint() : NULL);
+ const SkBitmap* bitmap = holder.getBitmap();
+ if (state->shouldDraw()) {
+ canvas->drawBitmap(*bitmap, left, top, hasPaint ? &state->paint() : NULL);
+ }
}
static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpFlag);
SkMatrix matrix;
reader->readMatrix(&matrix);
- canvas->drawBitmapMatrix(*holder.getBitmap(), matrix,
- hasPaint ? &state->paint() : NULL);
+ const SkBitmap* bitmap = holder.getBitmap();
+ if (state->shouldDraw()) {
+ canvas->drawBitmapMatrix(*bitmap, matrix,
+ hasPaint ? &state->paint() : NULL);
+ }
}
static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpFlag);
const SkIRect* center = skip<SkIRect>(reader);
const SkRect* dst = skip<SkRect>(reader);
- canvas->drawBitmapNine(*holder.getBitmap(), *center, *dst,
- hasPaint ? &state->paint() : NULL);
+ const SkBitmap* bitmap = holder.getBitmap();
+ if (state->shouldDraw()) {
+ canvas->drawBitmapNine(*bitmap, *center, *dst,
+ hasPaint ? &state->paint() : NULL);
+ }
}
static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
src = NULL;
}
const SkRect* dst = skip<SkRect>(reader);
- canvas->drawBitmapRectToRect(*holder.getBitmap(), src, *dst, hasPaint ? &state->paint() : NULL);
+ const SkBitmap* bitmap = holder.getBitmap();
+ if (state->shouldDraw()) {
+ canvas->drawBitmapRectToRect(*bitmap, src, *dst, hasPaint ? &state->paint() : NULL);
+ }
}
static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
BitmapHolder holder(reader, op32, state);
bool hasPaint = SkToBool(DrawOp_unpackFlags(op32) & kDrawBitmap_HasPaint_DrawOpFlag);
const SkIPoint* point = skip<SkIPoint>(reader);
- canvas->drawSprite(*holder.getBitmap(), point->fX, point->fY, hasPaint ? &state->paint() : NULL);
+ const SkBitmap* bitmap = holder.getBitmap();
+ if (state->shouldDraw()) {
+ canvas->drawSprite(*bitmap, point->fX, point->fY, hasPaint ? &state->paint() : NULL);
+ }
}
///////////////////////////////////////////////////////////////////////////////
size = reader->readU32();
}
const void* data = reader->skip(SkAlign4(size));
- canvas->drawData(data, size);
+ if (state->shouldDraw()) {
+ canvas->drawData(data, size);
+ }
}
static void drawPicture_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState::SkGPipeState()
: fReader(0)
+ , fSilent(false)
, fSharedHeap(NULL)
, fFlags(0) {
}
SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length,
- size_t* bytesRead, bool readAtom) {
+ uint32_t playbackFlags, size_t* bytesRead) {
if (NULL == fCanvas) {
return kError_Status;
}
fState = new SkGPipeState;
}
+ fState->setSilent(playbackFlags & kSilent_PlaybackFlag);
+
SkASSERT(SK_ARRAY_COUNT(gReadTable) == (kDone_DrawOp + 1));
const ReadProc* table = gReadTable;
break;
}
table[op](canvas, reader.getReader32(), op32, fState);
- if (readAtom &&
+ if ((playbackFlags & kReadAtom_PlaybackFlag) &&
(table[op] != paintOp_rp &&
table[op] != def_Typeface_rp &&
table[op] != def_PaintFlat_rp &&
virtual ~DeferredPipeController();
virtual void* requestBlock(size_t minRequest, size_t* actual) SK_OVERRIDE;
virtual void notifyWritten(size_t bytes) SK_OVERRIDE;
- void playback();
+ void playback(bool silent);
void reset();
bool hasRecorded() const { return fAllocator.blockCount() != 0; }
size_t storageAllocatedForRecording() const { return fAllocator.totalCapacity(); }
fBytesWritten += bytes;
}
-void DeferredPipeController::playback() {
-
+void DeferredPipeController::playback(bool silent) {
+ uint32_t flags = silent ? SkGPipeReader::kSilent_PlaybackFlag : 0;
for (int currentBlock = 0; currentBlock < fBlockList.count(); currentBlock++ ) {
- fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize);
+ fReader.playback(fBlockList[currentBlock].fBlock, fBlockList[currentBlock].fSize,
+ flags);
}
fBlockList.reset();
if (fBlock) {
- fReader.playback(fBlock, fBytesWritten);
+ fReader.playback(fBlock, fBytesWritten, flags);
fBlock = NULL;
}
bool isFreshFrame();
size_t storageAllocatedForRecording() const;
size_t freeMemoryIfPossible(size_t bytesToFree);
- void flushPendingCommands();
+ void flushPendingCommands(bool silent);
void skipPendingCommands();
void setMaxRecordingStorage(size_t);
void recordedDrawCommand();
}
DeferredDevice::~DeferredDevice() {
- this->flushPendingCommands();
+ this->flushPendingCommands(true);
SkSafeUnref(fImmediateCanvas);
}
return ret;
}
-void DeferredDevice::flushPendingCommands() {
+void DeferredDevice::flushPendingCommands(bool silent) {
if (!fPipeController.hasRecorded()) {
return;
}
fNotificationClient->prepareForDraw();
}
fPipeWriter.flushRecording(true);
- fPipeController.playback();
+ fPipeController.playback(silent);
if (fNotificationClient) {
fNotificationClient->flushedDrawCommands();
}
}
void DeferredDevice::flush() {
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
fImmediateCanvas->flush();
}
size_t tryFree = storageAllocated - fMaxRecordingStorageBytes;
if (this->freeMemoryIfPossible(tryFree) < tryFree) {
// Flush is necessary to free more space.
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
// Free as much as possible to avoid oscillating around fMaxRecordingStorageBytes
// which could cause a high flushing frequency.
this->freeMemoryIfPossible(~0U);
}
SkGpuRenderTarget* DeferredDevice::accessRenderTarget() {
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
return fImmediateDevice->accessRenderTarget();
}
SkCanvas::kNative_Premul_Config8888 != config8888 &&
kPMColorAlias != config8888) {
//Special case config: no deferral
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
fImmediateDevice->writePixels(bitmap, x, y, config8888);
return;
}
SkPaint paint;
paint.setXfermodeMode(SkXfermode::kSrc_Mode);
if (shouldDrawImmediately(&bitmap, NULL)) {
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
fImmediateCanvas->drawSprite(bitmap, x, y, &paint);
} else {
this->recordingCanvas()->drawSprite(bitmap, x, y, &paint);
}
const SkBitmap& DeferredDevice::onAccessBitmap(SkBitmap*) {
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
return fImmediateDevice->accessBitmap(false);
}
bool DeferredDevice::onReadPixels(
const SkBitmap& bitmap, int x, int y, SkCanvas::Config8888 config8888) {
- this->flushPendingCommands();
+ this->flushPendingCommands(false);
return fImmediateCanvas->readPixels(const_cast<SkBitmap*>(&bitmap),
x, y, config8888);
}
if (val != fDeferredDrawing) {
if (fDeferredDrawing) {
// Going live.
- this->getDeferredDevice()->flushPendingCommands();
+ this->getDeferredDevice()->flushPendingCommands(false);
}
fDeferredDrawing = val;
}
return this->getDeferredDevice()->isFreshFrame();
}
+void SkDeferredCanvas::silentFlush() {
+ if (fDeferredDrawing) {
+ this->getDeferredDevice()->flushPendingCommands(true);
+ }
+}
+
SkDeferredCanvas::~SkDeferredCanvas() {
}
"test step %s, SkDeferredCanvas state consistency before flush";
static const char* const kDeferredPostFlushPlaybackAssertMessageFormat =
"test step %s, SkDeferredCanvas playback canvas state consistency after flush";
+static const char* const kDeferredPostSilentFlushPlaybackAssertMessageFormat =
+ "test step %s, SkDeferredCanvas playback canvas state consistency after silent flush";
static const char* const kDeferredPostFlushAssertMessageFormat =
"test step %s, SkDeferredCanvas state consistency after flush";
static const char* const kPictureResourceReuseMessageFormat =
static void TestDeferredCanvasStateConsistency(
skiatest::Reporter* reporter,
CanvasTestStep* testStep,
- const SkCanvas& referenceCanvas) {
+ const SkCanvas& referenceCanvas, bool silent) {
SkBitmap deferredStore;
createBitmap(&deferredStore, SkBitmap::kARGB_8888_Config, 0xFFFFFFFF);
AssertCanvasStatesEqual(reporter, &deferredCanvas, &referenceCanvas,
testStep);
- deferredCanvas.flush();
- testStep->setAssertMessageFormat(
+ if (silent) {
+ deferredCanvas.silentFlush();
+ } else {
+ deferredCanvas.flush();
+ }
+
+ testStep->setAssertMessageFormat(
+ silent ? kDeferredPostSilentFlushPlaybackAssertMessageFormat :
kDeferredPostFlushPlaybackAssertMessageFormat);
AssertCanvasStatesEqual(reporter,
deferredCanvas.immediateCanvas(),
testStep->setAssertMessageFormat(kCanvasDrawAssertMessageFormat);
testStep->draw(&referenceCanvas, reporter);
- SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas);
+ SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, false);
+
+ SkDeferredCanvasTester::TestDeferredCanvasStateConsistency(reporter, testStep, referenceCanvas, true);
// The following test code is disabled because SkProxyCanvas is
// missing a lot of virtual overrides on get* methods, which are used