Index: src/core/SkPictureRecord.cpp |
=================================================================== |
--- src/core/SkPictureRecord.cpp (revision 8135) |
+++ src/core/SkPictureRecord.cpp (working copy) |
@@ -502,20 +502,48 @@ |
typedef bool (*PictureRecordOptProc)(SkWriter32* writer, int32_t offset, |
SkPaintDictionary* paintDict); |
+enum PictureRecordOptType { |
+ kRewind_OptType, // Optimization rewinds the command stream |
+ kCollapseSaveLayer_OptType, // Optimization eliminates a save/restore pair |
+}; |
+struct PictureRecordOpt { |
+ PictureRecordOptProc fProc; |
+ PictureRecordOptType fType; |
+}; |
/* |
* A list of the optimizations that are tried upon seeing a restore |
* TODO: add a real API for such optimizations |
* Add the ability to fire optimizations on any op (not just RESTORE) |
*/ |
-static const PictureRecordOptProc gPictureRecordOpts[] = { |
- collapse_save_clip_restore, |
-#ifndef SK_IGNORE_PICTURE_RECORD_SAVE_LAYER_OPT |
- remove_save_layer1, |
- remove_save_layer2, |
-#endif |
+static const PictureRecordOpt gPictureRecordOpts[] = { |
+ { collapse_save_clip_restore, kRewind_OptType }, |
+ { remove_save_layer1, kCollapseSaveLayer_OptType }, |
+ { remove_save_layer2, kCollapseSaveLayer_OptType } |
}; |
+// This is called after an optimization has been applied to the command stream |
+// in order to adjust the contents and state of the bounding box hierarchy and |
+// state tree to reflect the optimization. |
+static void apply_optimization_to_bbh(PictureRecordOptType opt, SkPictureStateTree* stateTree, |
+ SkBBoxHierarchy* boundingHierarchy) { |
+ switch (opt) { |
+ case kCollapseSaveLayer_OptType: |
+ stateTree->saveCollapsed(); |
+ break; |
+ case kRewind_OptType: |
+ if (NULL != boundingHierarchy) { |
+ boundingHierarchy->rewindInserts(); |
+ } |
+ // Note: No need to touch the state tree for this to work correctly. |
+ // Unused branches do not burden the playback, and pruning the tree |
+ // would be O(N^2), so it is best to leave it alone. |
+ break; |
+ default: |
+ SkASSERT(0); |
+ } |
+} |
+ |
void SkPictureRecord::restore() { |
// FIXME: SkDeferredCanvas needs to be refactored to respect |
// save/restore balancing so that the following test can be |
@@ -536,10 +564,12 @@ |
uint32_t initialOffset, size; |
size_t opt; |
for (opt = 0; opt < SK_ARRAY_COUNT(gPictureRecordOpts); ++opt) { |
- if ((*gPictureRecordOpts[opt])(&fWriter, fRestoreOffsetStack.top(), &fPaints)) { |
+ if ((*gPictureRecordOpts[opt].fProc)(&fWriter, fRestoreOffsetStack.top(), &fPaints)) { |
// Some optimization fired so don't add the RESTORE |
size = 0; |
initialOffset = fWriter.size(); |
+ apply_optimization_to_bbh(gPictureRecordOpts[opt].fType, |
+ fStateTree, fBoundingHierarchy); |
break; |
} |
} |