Fixing SkPicture command pattern optimizations to make them work correctly with bounding box hierarchies
BUG=https://code.google.com/p/chromium/issues/detail?id=180645
TEST=render_pictures -r <skp_dir> --validate --bbh <grid|rtree> --mode tile 256 256
Author: junov@chromium.org
Reviewed By: robertphillips@google.com
Review URL: https://chromiumcodereview.appspot.com/12817011
git-svn-id: http://skia.googlecode.com/svn/trunk@8171 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 45412fe..38bbe33 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -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;
}
}