Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Unified Diff: src/core/SkPicturePlayback.cpp

Issue 12545009: Adding option in SkPicture to record device-space bounds of draw commands. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/core/SkPicturePlayback.cpp
===================================================================
--- src/core/SkPicturePlayback.cpp (revision 9110)
+++ src/core/SkPicturePlayback.cpp (working copy)
@@ -124,6 +124,12 @@
}
}
+#if SK_RECORD_BOUNDS_IN_PICTURE
+ fHasRecordedBounds = true;
+#else
+ fHasRecordedBounds = false;
+#endif
+
#ifdef SK_DEBUG_SIZE
int overall = fPlayback->size(&overallBytes);
bitmaps = fPlayback->bitmaps(&bitmapBytes);
@@ -176,7 +182,7 @@
fBoundingHierarchy = src.fBoundingHierarchy;
fStateTree = src.fStateTree;
-
+ fHasRecordedBounds = src.fHasRecordedBounds;
SkSafeRef(fBoundingHierarchy);
SkSafeRef(fStateTree);
@@ -270,6 +276,7 @@
fFactoryPlayback = NULL;
fBoundingHierarchy = NULL;
fStateTree = NULL;
+ fHasRecordedBounds = false;
}
SkPicturePlayback::~SkPicturePlayback() {
@@ -592,7 +599,13 @@
SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info,
SkPicture::InstallPixelRefProc proc) {
this->init();
-
+#if SK_RECORD_BOUNDS_IN_PICTURE
+ fHasRecordedBounds = SkToBool(info.fFlags & SkPictInfo::kHasRecordedBounds_Flag);
+#else
+ // Can't handle skps with recorded bounds in a build that does support them.
Tom Hudson 2013/05/14 17:00:49 Typo: does *not* support them?
+ SkASSERT(false == SkToBool(info.fFlags & SkPictInfo::kHasRecordedBounds_Flag));
+ fHasRecordedBounds = false;
+#endif
for (;;) {
uint32_t tag = stream->readU32();
if (PICT_EOF_TAG == tag) {
@@ -656,6 +669,42 @@
return (DrawType) op;
}
+// Sets 'bounds' to represent the clip bounds of the playback canvas,
+// expressed in the recording device's coordinate space.
+// returns true if the bounds are not empty.
+static inline bool get_intial_clip_bounds(const SkCanvas& canvas, SkIRect* bounds) {
+ SkASSERT(NULL != bounds);
+ SkRect clipBounds;
+ if (canvas.getClipBounds(&clipBounds)) {
+ clipBounds.roundOut(bounds);
+ } else {
+ bounds->setEmpty();
+ return false;
+ }
+ return !bounds->isEmpty();
+}
+
+class SkDisableQuickRejectInScope {
+public:
+ SkDisableQuickRejectInScope() {
+ fCanvas = NULL;
Tom Hudson 2013/05/14 17:00:49 Why not pass a canvas to the constructor, and avoi
+ }
+ void set(SkCanvas* canvas) {
+ if (canvas->fQuickRejectEnabled == true) {
Tom Hudson 2013/05/14 17:00:49 // protect against nested Disables
+ fCanvas = canvas;
+ fCanvas->fQuickRejectEnabled = false;
+ }
+ }
+
+ ~SkDisableQuickRejectInScope() {
+ if (fCanvas) {
+ fCanvas->fQuickRejectEnabled = true;
+ }
+ }
+private:
+ SkCanvas* fCanvas;
+};
+
void SkPicturePlayback::draw(SkCanvas& canvas) {
#ifdef ENABLE_TIME_DRAW
SkAutoTime at("SkPicture::draw", 50);
@@ -677,21 +726,39 @@
TextContainer text;
SkTDArray<void*> results;
+#if SK_RECORD_BOUNDS_IN_PICTURE
+ bool initialClipBoundsSet = false;
+#endif
+ SkIRect initialClipBounds; // only computed if needed
if (NULL != fStateTree && NULL != fBoundingHierarchy) {
- SkRect clipBounds;
- if (canvas.getClipBounds(&clipBounds)) {
- SkIRect query;
- clipBounds.roundOut(&query);
- fBoundingHierarchy->search(query, &results);
- if (results.count() == 0) {
- return;
- }
- SkTQSort<SkPictureStateTree::Draw>(
- reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()),
- reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1));
+ if (!get_intial_clip_bounds(canvas, &initialClipBounds)) {
+ return;
Tom Hudson 2013/05/14 17:00:49 You now have an early return where it looks like y
}
+ fBoundingHierarchy->search(initialClipBounds, &results);
+ if (results.count() == 0) {
+ return;
+ }
+#if SK_RECORD_BOUNDS_IN_PICTURE
+ initialClipBoundsSet = true;
+#endif
+ SkTQSort<SkPictureStateTree::Draw>(
+ reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()),
+ reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1));
}
+#if SK_RECORD_BOUNDS_IN_PICTURE
+ SkDisableQuickRejectInScope dqr;
+ if (fHasRecordedBounds) {
+ // Temporarily disable quickReject testing on 'canvas'
+ // because it is redundant with early bounds check.
Tom Hudson 2013/05/14 17:00:49 Nit: Second line of this comment is more useful th
+ dqr.set(&canvas);
Tom Hudson 2013/05/14 17:00:49 Ugh, given that you need this to be conditionally
+ if (!initialClipBoundsSet && !get_intial_clip_bounds(canvas, &initialClipBounds)) {
+ return;
+ }
+ initialClipBoundsSet = true;
+ }
+#endif
+
SkPictureStateTree::Iterator it = (NULL == fStateTree) ?
SkPictureStateTree::Iterator() :
fStateTree->getIterator(results, &canvas);
@@ -727,9 +794,22 @@
// "curOffset + size"
skipTo = this->preDraw(curOffset, op);
#endif
- if (0 == skipTo && NOOP == op) {
- // NOOPs are to be ignored - do not propagate them any further
- skipTo = curOffset + size;
+ if (0 == skipTo) {
+ if (NOOP == op) {
+ // NOOPs are to be ignored - do not propagate them any further
+ skipTo = curOffset + size;
+ }
+#if SK_RECORD_BOUNDS_IN_PICTURE
+ else if (fHasRecordedBounds && SkPictureRecord::canRecordBounds(op)) {
+ const SkIRect& clippedBounds = reader.skipT<SkIRect>();
+ // recording canvas device bounds are in the same coordinate space
+ // as local clip bounds at start of playback.
+ SkASSERT(initialClipBoundsSet);
+ if (!SkIRect::Intersects(clippedBounds, initialClipBounds)) {
+ skipTo = curOffset + size;
+ }
+ }
+#endif
}
if (0 != skipTo) {

Powered by Google App Engine
This is Rietveld 408576698