add picture-record option to speedup complex clips

remove hack that stopped picture-playback from culling on clipPath() result



git-svn-id: http://skia.googlecode.com/svn/trunk@92 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-02-13 14:56:09 +00:00
parent 9b0390626f
commit ae814c809e
5 changed files with 82 additions and 13 deletions

View File

@ -49,10 +49,28 @@ public:
*/
void swap(SkPicture& other);
enum RecordingFlags {
/* This flag specifies that when clipPath() is called, the path will
be faithfully recorded, but the recording canvas' current clip will
only see the path's bounds. This speeds up the recording process
without compromising the fidelity of the playback. The only side-
effect for recording is that calling getTotalClip() or related
clip-query calls will reflect the path's bounds, not the actual
path.
*/
kUsePathBoundsForClip_RecordingFlag = 0x01
};
/** Returns the canvas that records the drawing commands.
@param width the base width for the picture, as if the recording
canvas' bitmap had this width.
@param height the base width for the picture, as if the recording
canvas' bitmap had this height.
@param recordFlags optional flags that control recording.
@return the picture canvas.
*/
SkCanvas* beginRecording(int width, int height);
SkCanvas* beginRecording(int width, int height, uint32_t recordFlags = 0);
/** Returns the recording canvas if one is active, or NULL if recording is
not active. This does not alter the refcnt on the canvas (if present).
*/
@ -103,9 +121,10 @@ private:
class SkAutoPictureRecord : SkNoncopyable {
public:
SkAutoPictureRecord(SkPicture* pict, int width, int height) {
SkAutoPictureRecord(SkPicture* pict, int width, int height,
uint32_t recordingFlags = 0) {
fPicture = pict;
fCanvas = pict->beginRecording(width, height);
fCanvas = pict->beginRecording(width, height, recordingFlags);
}
~SkAutoPictureRecord() {
fPicture->endRecording();

View File

@ -146,7 +146,8 @@ void SkPicture::swap(SkPicture& other) {
///////////////////////////////////////////////////////////////////////////////
SkCanvas* SkPicture::beginRecording(int width, int height) {
SkCanvas* SkPicture::beginRecording(int width, int height,
uint32_t recordingFlags) {
if (fPlayback) {
SkDELETE(fPlayback);
fPlayback = NULL;
@ -157,7 +158,7 @@ SkCanvas* SkPicture::beginRecording(int width, int height) {
fRecord = NULL;
}
fRecord = SkNEW(SkPictureRecord);
fRecord = SkNEW_ARGS(SkPictureRecord, (recordingFlags));
fWidth = width;
fHeight = height;

View File

@ -3,6 +3,11 @@
#include "SkTypeface.h"
#include <new>
/* Define this to spew out a debug statement whenever we skip the remainder of
a save/restore block because a clip... command returned false (empty).
*/
#define SPEW_CLIP_SKIPPINGx
SkPicturePlayback::SkPicturePlayback() {
this->init();
}
@ -461,10 +466,31 @@ SkPicturePlayback::SkPicturePlayback(SkStream* stream) {
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
#ifdef SPEW_CLIP_SKIPPING
struct SkipClipRec {
int fCount;
size_t fSize;
SkipClipRec() {
fCount = 0;
fSize = 0;
}
void recordSkip(size_t bytes) {
fCount += 1;
fSize += bytes;
}
};
#endif
void SkPicturePlayback::draw(SkCanvas& canvas) {
#ifdef ENABLE_TIME_DRAW
SkAutoTime at("SkPicture::draw", 50);
#endif
#ifdef SPEW_CLIP_SKIPPING
SkipClipRec skipRect, skipRegion, skipPath;
#endif
TextContainer text;
fReader.rewind();
@ -476,8 +502,10 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
SkRegion::Op op = (SkRegion::Op) getInt();
size_t offsetToRestore = getInt();
// HACK (false) until I can handle op==kReplace
if (!canvas.clipPath(path, op) && false) {
//SkDebugf("---- skip clipPath for %d bytes\n", offsetToRestore - fReader.offset());
if (!canvas.clipPath(path, op)) {
#ifdef SPEW_CLIP_SKIPPING
skipPath.recordSkip(offsetToRestore - fReader.offset());
#endif
fReader.setOffset(offsetToRestore);
}
} break;
@ -486,7 +514,9 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
SkRegion::Op op = (SkRegion::Op) getInt();
size_t offsetToRestore = getInt();
if (!canvas.clipRegion(region, op)) {
//SkDebugf("---- skip clipDeviceRgn for %d bytes\n", offsetToRestore - fReader.offset());
#ifdef SPEW_CLIP_SKIPPING
skipRegion.recordSkip(offsetToRestore - fReader.offset());
#endif
fReader.setOffset(offsetToRestore);
}
} break;
@ -495,7 +525,9 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
SkRegion::Op op = (SkRegion::Op) getInt();
size_t offsetToRestore = getInt();
if (!canvas.clipRect(*rect, op)) {
//SkDebugf("---- skip clipRect for %d bytes\n", offsetToRestore - fReader.offset());
#ifdef SPEW_CLIP_SKIPPING
skipRect.recordSkip(offsetToRestore - fReader.offset());
#endif
fReader.setOffset(offsetToRestore);
}
} break;
@ -671,6 +703,14 @@ void SkPicturePlayback::draw(SkCanvas& canvas) {
}
}
#ifdef SPEW_CLIP_SKIPPING
{
size_t size = skipRect.fSize + skipPath.fSize + skipRegion.fSize;
SkDebugf("--- Clip skips %d%% rect:%d path:%d rgn:%d\n",
size * 100 / fReader.offset(), skipRect.fCount, skipPath.fCount,
skipRegion.fCount);
}
#endif
// this->dumpSize();
}

View File

@ -4,8 +4,8 @@
#define MIN_WRITER_SIZE 16384
#define HEAP_BLOCK_SIZE 4096
SkPictureRecord::SkPictureRecord() :
fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE) {
SkPictureRecord::SkPictureRecord(uint32_t flags) :
fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE), fRecordFlags(flags) {
fBitmapIndex = fMatrixIndex = fPaintIndex = fRegionIndex = 1;
#ifdef SK_DEBUG_SIZE
fPointBytes = fRectBytes = fTextBytes = 0;
@ -136,7 +136,14 @@ bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op) {
fRestoreOffsetStack.top() = offset;
validate();
return this->INHERITED::clipPath(path, op);
if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
SkRect bounds;
path.computeBounds(&bounds, SkPath::kFast_BoundsType);
return this->INHERITED::clipRect(bounds, op);
} else {
return this->INHERITED::clipPath(path, op);
}
}
bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {

View File

@ -11,7 +11,7 @@
class SkPictureRecord : public SkCanvas {
public:
SkPictureRecord();
SkPictureRecord(uint32_t recordFlags);
virtual ~SkPictureRecord();
// overrides from SkCanvas
@ -171,6 +171,8 @@ private:
SkRefCntRecorder fRCRecorder;
SkRefCntRecorder fTFRecorder;
uint32_t fRecordFlags;
friend class SkPicturePlayback;
typedef SkCanvas INHERITED;