Index: src/core/SkPictureRecord.cpp |
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp |
index 042e6a39cb9602bf929b8cfaed6e7bbd57c5353a..5b6461084c9c8afe8d463a1933d52d504c7ca1ef 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 |
+ 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 |
@@ -1530,6 +1532,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) { |
+ // 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); |
+ |
+ addRect(cullRect); |
+ fCullOffsetStack.push(fWriter.bytesWritten()); |
+ 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); |
+ 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) { |