Index: src/core/SkPictureRecord.cpp |
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp |
index be86951ae803f768035906d3fd76ca0bf93a6d9d..60cd1f594807dbcb5923c57e843bc537f6eb8772 100644 |
--- a/src/core/SkPictureRecord.cpp |
+++ b/src/core/SkPictureRecord.cpp |
@@ -76,6 +76,8 @@ static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) { |
0, // CLIP_REGION - no paint |
0, // CLIP_RECT - no paint |
0, // CLIP_RRECT - no paint |
robertphillips
2014/02/25 15:58:41
move to match other moves?
f(malita)
2014/02/25 16:50:28
Will do.
|
+ 0, // PUSH_CULL - no paint |
+ 0, // POP_CULL - no paint |
0, // CONCAT - no paint |
1, // DRAW_BITMAP - right after op code |
1, // DRAW_BITMAP_MATRIX - right after op code |
@@ -1548,6 +1550,60 @@ void SkPictureRecord::endCommentGroup() { |
this->validate(initialOffset, size); |
} |
+// [op/size] [rect] [skip offset] |
+static const uint32_t kPushCullOpSize = 2 * kUInt32Size + sizeof(SkRect); |
+void SkPictureRecord::onPushCull(const SkRect& cullRect) { |
robertphillips
2014/02/25 15:58:41
Don't we also want to assert that the current cull
f(malita)
2014/02/25 16:50:28
At a high level it surely makes sense (and my init
|
+ // Skip identical cull rects. |
+ if (!fCullOffsetStack.isEmpty()) { |
+ const SkRect& prevCull = fWriter.readTAt<SkRect>(fCullOffsetStack.top() - sizeof(SkRect)); |
+ if (prevCull == cullRect) { |
+ // Skipped culls are tracked on the stack, but they point to the previous offset. |
+ fCullOffsetStack.push(fCullOffsetStack.top()); |
+ return; |
+ } |
+ } |
+ |
+ uint32_t size = kPushCullOpSize; |
+ size_t initialOffset = this->addDraw(PUSH_CULL, &size); |
+ // PUSH_CULL's size should stay constant (used to rewind). |
+ SkASSERT(size == kPushCullOpSize); |
+ |
robertphillips
2014/02/25 15:58:41
this->
|
+ addRect(cullRect); |
+ fCullOffsetStack.push(fWriter.bytesWritten()); |
robertphillips
2014/02/25 15:58:41
this->
|
+ addInt(0); |
+ this->validate(initialOffset, size); |
+} |
+ |
+void SkPictureRecord::onPopCull() { |
+ SkASSERT(!fCullOffsetStack.isEmpty()); |
+ |
+ uint32_t cullSkipOffset = fCullOffsetStack.top(); |
+ fCullOffsetStack.pop(); |
+ |
+ // Skipped push, do the same for pop. |
+ if (!fCullOffsetStack.isEmpty() && cullSkipOffset == fCullOffsetStack.top()) { |
+ return; |
+ } |
+ |
+ // Collapse empty push/pop pairs. |
+ if ((size_t)(cullSkipOffset + kUInt32Size) == fWriter.bytesWritten()) { |
+ SkASSERT(fWriter.bytesWritten() >= kPushCullOpSize); |
robertphillips
2014/02/25 15:58:41
can we have a peek_op static function for this?
|
+ SkASSERT(fWriter.readTAt<uint32_t>( |
+ fWriter.bytesWritten() - kPushCullOpSize) >> 24 == PUSH_CULL); |
+ fWriter.rewindToOffset(fWriter.bytesWritten() - kPushCullOpSize); |
+ return; |
+ } |
+ |
+ // op only |
+ uint32_t size = kUInt32Size; |
+ size_t initialOffset = this->addDraw(POP_CULL, &size); |
+ |
+ // update the cull skip offset to point past this op. |
+ fWriter.overwriteTAt<uint32_t>(cullSkipOffset, fWriter.bytesWritten()); |
+ |
+ this->validate(initialOffset, size); |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
SkSurface* SkPictureRecord::onNewSurface(const SkImageInfo& info) { |