Noop away PushCull/PopCull pairs with nothing between them.
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 8 May 2014 18:17:51 +0000 (18:17 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 8 May 2014 18:17:51 +0000 (18:17 +0000)
BUG=skia:2378
R=fmalita@chromium.org, mtklein@google.com

Author: mtklein@chromium.org

Review URL: https://codereview.chromium.org/277613002

git-svn-id: http://skia.googlecode.com/svn/trunk@14653 2bbb7eff-a529-9590-31e7-b0007b416f81

src/record/SkRecordOpts.cpp
src/record/SkRecordOpts.h
tests/RecordOptsTest.cpp

index bfc45bd..1322c0f 100644 (file)
@@ -15,8 +15,10 @@ using namespace SkRecords;
 
 void SkRecordOptimize(SkRecord* record) {
     // TODO(mtklein): fuse independent optimizations to reduce number of passes?
+    SkRecordNoopCulls(record);
     SkRecordNoopSaveRestores(record);
     SkRecordNoopSaveLayerDrawRestores(record);
+
     SkRecordAnnotateCullingPairs(record);
     SkRecordReduceDrawPosTextStrength(record);  // Helpful to run this before BoundDrawPosTextH.
     SkRecordBoundDrawPosTextH(record);
@@ -42,6 +44,21 @@ static bool apply(Pass* pass, SkRecord* record) {
     return changed;
 }
 
+struct CullNooper {
+    typedef Pattern3<Is<PushCull>, Star<Is<NoOp> >, Is<PopCull> > Pattern;
+
+    bool onMatch(SkRecord* record, Pattern* pattern, unsigned begin, unsigned end) {
+        record->replace<NoOp>(begin);  // PushCull
+        record->replace<NoOp>(end-1);  // PopCull
+        return true;
+    }
+};
+
+void SkRecordNoopCulls(SkRecord* record) {
+    CullNooper pass;
+    while (apply(&pass, record));
+}
+
 // Turns the logical NoOp Save and Restore in Save-Draw*-Restore patterns into actual NoOps.
 struct SaveOnlyDrawsRestoreNooper {
     typedef Pattern3<Is<Save>,
index ad8c3bc..b535ec9 100644 (file)
@@ -13,6 +13,8 @@
 // Run all optimizations in recommended order.
 void SkRecordOptimize(SkRecord*);
 
+// NoOp away pointless PushCull/PopCull pairs with nothing between them.
+void SkRecordNoopCulls(SkRecord*);
 
 // Turns logical no-op Save-[non-drawing command]*-Restore patterns into actual no-ops.
 void SkRecordNoopSaveRestores(SkRecord*);
index c427c25..34229d7 100644 (file)
@@ -60,6 +60,35 @@ DEF_TEST(RecordOpts_Culling, r) {
     REPORTER_ASSERT(r, 2 == assert_type<SkRecords::PairedPushCull>(r, record, 4)->skip);
 }
 
+DEF_TEST(RecordOpts_NoopCulls, r) {
+    SkRecord record;
+    SkRecorder recorder(SkRecorder::kWriteOnly_Mode, &record, W, H);
+
+    // All should be nooped.
+    recorder.pushCull(SkRect::MakeWH(200, 200));
+        recorder.pushCull(SkRect::MakeWH(100, 100));
+        recorder.popCull();
+    recorder.popCull();
+
+    // Kept for now.  We could peel off a layer of culling.
+    recorder.pushCull(SkRect::MakeWH(5, 5));
+        recorder.pushCull(SkRect::MakeWH(5, 5));
+            recorder.drawRect(SkRect::MakeWH(1, 1), SkPaint());
+        recorder.popCull();
+    recorder.popCull();
+
+    SkRecordNoopCulls(&record);
+
+    for (unsigned i = 0; i < 4; i++) {
+        assert_type<SkRecords::NoOp>(r, record, i);
+    }
+    assert_type<SkRecords::PushCull>(r, record, 4);
+    assert_type<SkRecords::PushCull>(r, record, 5);
+    assert_type<SkRecords::DrawRect>(r, record, 6);
+    assert_type<SkRecords::PopCull>(r, record, 7);
+    assert_type<SkRecords::PopCull>(r, record, 8);
+}
+
 static void draw_pos_text(SkCanvas* canvas, const char* text, bool constantY) {
     const size_t len = strlen(text);
     SkAutoTMalloc<SkPoint> pos(len);