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) { |