| Index: src/core/SkPictureRecord.cpp
|
| diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
|
| index be86951ae803f768035906d3fd76ca0bf93a6d9d..978e2b37c2f65dc23f36f2f29c990be713f03ca4 100644
|
| --- a/src/core/SkPictureRecord.cpp
|
| +++ b/src/core/SkPictureRecord.cpp
|
| @@ -112,6 +112,8 @@ static inline uint32_t getPaintOffset(DrawType op, uint32_t opSize) {
|
| 0, // COMMENT - no paint
|
| 0, // END_GROUP - no paint
|
| 1, // DRAWDRRECT - right after op code
|
| + 0, // PUSH_CULL - no paint
|
| + 0, // POP_CULL - no paint
|
| };
|
|
|
| SK_COMPILE_ASSERT(sizeof(gPaintOffsets) == LAST_DRAWTYPE_ENUM + 1,
|
| @@ -220,6 +222,15 @@ bool SkPictureRecord::isDrawingToLayer() const {
|
| }
|
|
|
| /*
|
| + * Read the op code from 'offset' in 'writer'.
|
| + */
|
| +#ifdef SK_DEBUG
|
| +static DrawType peek_op(SkWriter32* writer, int32_t offset) {
|
| + return (DrawType)(writer->readTAt<uint32_t>(offset) >> 24);
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| * Read the op code from 'offset' in 'writer' and extract the size too.
|
| */
|
| static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* size) {
|
| @@ -1548,6 +1559,61 @@ 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;
|
| + }
|
| +
|
| + SkASSERT(prevCull.contains(cullRect));
|
| + }
|
| +
|
| + 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);
|
| +
|
| + this->addRect(cullRect);
|
| + fCullOffsetStack.push(fWriter.bytesWritten());
|
| + 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);
|
| + SkASSERT(PUSH_CULL == peek_op(&fWriter, fWriter.bytesWritten() - kPushCullOpSize));
|
| + 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) {
|
|
|