Update SkPictureRecord to allow some ops to be written separately
https://codereview.chromium.org/153883002/
git-svn-id: http://skia.googlecode.com/svn/trunk@13311 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 4279ac3..463c915 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -27,13 +27,13 @@
static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
-SkPictureRecord::SkPictureRecord(uint32_t flags, SkBaseDevice* device) :
- INHERITED(device),
- fBoundingHierarchy(NULL),
- fStateTree(NULL),
- fFlattenableHeap(HEAP_BLOCK_SIZE),
- fPaints(&fFlattenableHeap),
- fRecordFlags(flags) {
+SkPictureRecord::SkPictureRecord(uint32_t flags, SkBaseDevice* device)
+ : INHERITED(device)
+ , fBoundingHierarchy(NULL)
+ , fStateTree(NULL)
+ , fFlattenableHeap(HEAP_BLOCK_SIZE)
+ , fPaints(&fFlattenableHeap)
+ , fRecordFlags(flags) {
#ifdef SK_DEBUG_SIZE
fPointBytes = fRectBytes = fTextBytes = 0;
fPointWrites = fRectWrites = fTextWrites = 0;
@@ -141,14 +141,17 @@
// record the offset to us, making it non-positive to distinguish a save
// from a clip entry.
fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
+ this->recordSave(flags);
+ return this->INHERITED::save(flags);
+}
+void SkPictureRecord::recordSave(SaveFlags flags) {
// op + flags
uint32_t size = kSaveSize;
size_t initialOffset = this->addDraw(SAVE, &size);
addInt(flags);
this->validate(initialOffset, size);
- return this->INHERITED::save(flags);
}
int SkPictureRecord::saveLayer(const SkRect* bounds, const SkPaint* paint,
@@ -156,7 +159,24 @@
// record the offset to us, making it non-positive to distinguish a save
// from a clip entry.
fRestoreOffsetStack.push(-(int32_t)fWriter.bytesWritten());
+ this->recordSaveLayer(bounds, paint, flags);
+ if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
+ fFirstSavedLayerIndex = fRestoreOffsetStack.count();
+ }
+ /* Don't actually call INHERITED::saveLayer, because that will try to allocate
+ an offscreen device (potentially very big) which we don't actually need
+ at this time (and may not be able to afford since during record our
+ clip starts out the size of the picture, which is often much larger
+ than the size of the actual device we'll use during playback).
+ */
+ int count = this->INHERITED::save(flags);
+ this->clipRectBounds(bounds, flags, NULL);
+ return count;
+}
+
+void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint,
+ SaveFlags flags) {
// op + bool for 'bounds'
uint32_t size = 2 * kUInt32Size;
if (NULL != bounds) {
@@ -173,20 +193,7 @@
addPaintPtr(paint);
addInt(flags);
- if (kNoSavedLayerIndex == fFirstSavedLayerIndex) {
- fFirstSavedLayerIndex = fRestoreOffsetStack.count();
- }
-
this->validate(initialOffset, size);
- /* Don't actually call saveLayer, because that will try to allocate an
- offscreen device (potentially very big) which we don't actually need
- at this time (and may not be able to afford since during record our
- clip starts out the size of the picture, which is often much larger
- than the size of the actual device we'll use during playback).
- */
- int count = this->INHERITED::save(flags);
- this->clipRectBounds(bounds, flags, NULL);
- return count;
}
bool SkPictureRecord::isDrawingToLayer() const {
@@ -321,7 +328,6 @@
return false;
}
-
return merge_savelayer_paint_into_drawbitmp(writer, paintDict,
result[0], result[1]);
}
@@ -601,17 +607,22 @@
if ((fRecordFlags & SkPicture::kDisableRecordOptimizations_RecordingFlag) ||
SK_ARRAY_COUNT(gPictureRecordOpts) == opt) {
// No optimization fired so add the RESTORE
- fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
- size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
- initialOffset = this->addDraw(RESTORE, &size);
+ this->recordRestore();
}
fRestoreOffsetStack.pop();
- this->validate(initialOffset, size);
return this->INHERITED::restore();
}
+void SkPictureRecord::recordRestore() {
+ uint32_t initialOffset, size;
+ fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten());
+ size = 1 * kUInt32Size; // RESTORE consists solely of 1 op code
+ initialOffset = this->addDraw(RESTORE, &size);
+ this->validate(initialOffset, size);
+}
+
bool SkPictureRecord::translate(SkScalar dx, SkScalar dy) {
// op + dx + dy
uint32_t size = 1 * kUInt32Size + 2 * sizeof(SkScalar);
@@ -652,13 +663,17 @@
}
bool SkPictureRecord::concat(const SkMatrix& matrix) {
+ this->recordConcat(matrix);
+ return this->INHERITED::concat(matrix);
+}
+
+void SkPictureRecord::recordConcat(const SkMatrix& matrix) {
this->validate(fWriter.bytesWritten(), 0);
// op + matrix
uint32_t size = kUInt32Size + matrix.writeToMemory(NULL);
size_t initialOffset = this->addDraw(CONCAT, &size);
addMatrix(matrix);
this->validate(initialOffset, size);
- return this->INHERITED::concat(matrix);
}
void SkPictureRecord::setMatrix(const SkMatrix& matrix) {
@@ -715,9 +730,9 @@
this->restoreToCount(fInitialSaveCount);
}
-void SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
+int SkPictureRecord::recordRestoreOffsetPlaceholder(SkRegion::Op op) {
if (fRestoreOffsetStack.isEmpty()) {
- return;
+ return -1;
}
// The RestoreOffset field is initially filled with a placeholder
@@ -742,9 +757,16 @@
size_t offset = fWriter.bytesWritten();
addInt(prevOffset);
fRestoreOffsetStack.top() = offset;
+ return offset;
}
bool SkPictureRecord::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+ this->recordClipRect(rect, op, doAA);
+ return this->INHERITED::clipRect(rect, op, doAA);
+}
+
+int SkPictureRecord::recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+
// id + rect + clip params
uint32_t size = 1 * kUInt32Size + sizeof(rect) + 1 * kUInt32Size;
// recordRestoreOffsetPlaceholder doesn't always write an offset
@@ -752,13 +774,14 @@
// + restore offset
size += kUInt32Size;
}
+
size_t initialOffset = this->addDraw(CLIP_RECT, &size);
addRect(rect);
addInt(ClipParams_pack(op, doAA));
- recordRestoreOffsetPlaceholder(op);
+ int offset = this->recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
- return this->INHERITED::clipRect(rect, op, doAA);
+ return offset;
}
bool SkPictureRecord::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
@@ -766,6 +789,16 @@
return this->SkPictureRecord::clipRect(rrect.getBounds(), op, doAA);
}
+ this->recordClipRRect(rrect, op, doAA);
+ if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
+ return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
+ } else {
+ return this->INHERITED::clipRRect(rrect, op, doAA);
+ }
+}
+
+int SkPictureRecord::recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+
// op + rrect + clip params
uint32_t size = 1 * kUInt32Size + SkRRect::kSizeInMemory + 1 * kUInt32Size;
// recordRestoreOffsetPlaceholder doesn't always write an offset
@@ -776,15 +809,10 @@
size_t initialOffset = this->addDraw(CLIP_RRECT, &size);
addRRect(rrect);
addInt(ClipParams_pack(op, doAA));
- recordRestoreOffsetPlaceholder(op);
+ int offset = recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
-
- if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
- return this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
- } else {
- return this->INHERITED::clipRRect(rrect, op, doAA);
- }
+ return offset;
}
bool SkPictureRecord::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
@@ -794,19 +822,8 @@
return this->clipRect(r, op, doAA);
}
- // op + path index + clip params
- uint32_t size = 3 * kUInt32Size;
- // recordRestoreOffsetPlaceholder doesn't always write an offset
- if (!fRestoreOffsetStack.isEmpty()) {
- // + restore offset
- size += kUInt32Size;
- }
- size_t initialOffset = this->addDraw(CLIP_PATH, &size);
- addPath(path);
- addInt(ClipParams_pack(op, doAA));
- recordRestoreOffsetPlaceholder(op);
-
- this->validate(initialOffset, size);
+ int pathID = this->addPathToHeap(path);
+ this->recordClipPath(pathID, op, doAA);
if (fRecordFlags & SkPicture::kUsePathBoundsForClip_RecordingFlag) {
return this->updateClipConservativelyUsingBounds(path.getBounds(), op,
@@ -816,7 +833,30 @@
}
}
+int SkPictureRecord::recordClipPath(int pathID, SkRegion::Op op, bool doAA) {
+
+ // op + path index + clip params
+ uint32_t size = 3 * kUInt32Size;
+ // recordRestoreOffsetPlaceholder doesn't always write an offset
+ if (!fRestoreOffsetStack.isEmpty()) {
+ // + restore offset
+ size += kUInt32Size;
+ }
+ size_t initialOffset = this->addDraw(CLIP_PATH, &size);
+ addInt(pathID);
+ addInt(ClipParams_pack(op, doAA));
+ int offset = recordRestoreOffsetPlaceholder(op);
+
+ this->validate(initialOffset, size);
+ return offset;
+}
+
bool SkPictureRecord::clipRegion(const SkRegion& region, SkRegion::Op op) {
+ this->recordClipRegion(region, op);
+ return this->INHERITED::clipRegion(region, op);
+}
+
+int SkPictureRecord::recordClipRegion(const SkRegion& region, SkRegion::Op op) {
// op + clip params + region
uint32_t size = 2 * kUInt32Size + region.writeToMemory(NULL);
// recordRestoreOffsetPlaceholder doesn't always write an offset
@@ -827,10 +867,10 @@
size_t initialOffset = this->addDraw(CLIP_REGION, &size);
addRegion(region);
addInt(ClipParams_pack(op, false));
- recordRestoreOffsetPlaceholder(op);
+ int offset = recordRestoreOffsetPlaceholder(op);
this->validate(initialOffset, size);
- return this->INHERITED::clipRegion(region, op);
+ return offset;
}
void SkPictureRecord::clear(SkColor color) {
@@ -1307,11 +1347,15 @@
this->addInt(index);
}
-void SkPictureRecord::addPath(const SkPath& path) {
+int SkPictureRecord::addPathToHeap(const SkPath& path) {
if (NULL == fPathHeap) {
fPathHeap = SkNEW(SkPathHeap);
}
- addInt(fPathHeap->append(path));
+ return fPathHeap->append(path);
+}
+
+void SkPictureRecord::addPath(const SkPath& path) {
+ addInt(this->addPathToHeap(path));
}
void SkPictureRecord::addPicture(SkPicture& picture) {
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index d098916..51ae0b2 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -108,9 +108,8 @@
private:
void handleOptimization(int opt);
- void recordRestoreOffsetPlaceholder(SkRegion::Op);
- void fillRestoreOffsetPlaceholdersForCurrentStackLevel(
- uint32_t restoreOffset);
+ int recordRestoreOffsetPlaceholder(SkRegion::Op);
+ void fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset);
SkTDArray<int32_t> fRestoreOffsetStack;
int fFirstSavedLayerIndex;
@@ -237,6 +236,20 @@
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint, const SkFlatData* flatPaintData);
+ int addPathToHeap(const SkPath& path); // does not write to ops stream
+
+ // These entry points allow the writing of matrices, clips, saves &
+ // restores to be deferred (e.g., if the MC state is being collapsed and
+ // only written out as needed).
+ void recordConcat(const SkMatrix& matrix);
+ int recordClipRect(const SkRect& rect, SkRegion::Op op, bool doAA);
+ int recordClipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA);
+ int recordClipPath(int pathID, SkRegion::Op op, bool doAA);
+ int recordClipRegion(const SkRegion& region, SkRegion::Op op);
+ void recordSave(SaveFlags flags);
+ void recordSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags);
+ void recordRestore();
+
// These are set to NULL in our constructor, but may be changed by
// subclasses, in which case they will be SkSafeUnref'd in our destructor.
SkBBoxHierarchy* fBoundingHierarchy;