Add SkRecord::defrag().
authormtklein <mtklein@chromium.org>
Thu, 19 Nov 2015 15:23:49 +0000 (07:23 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 19 Nov 2015 15:23:49 +0000 (07:23 -0800)
Called by SkRecordOptimize(), this moves all the NoOps to the end and
slices them off.

This implementation with std::remove_if() is linear and doesn't malloc.

No diffs: https://gold.skia.org/search2?issue=1461663003&unt=true&query=source_type%3Dgm&master=false

BUG=skia:

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

src/core/SkRecord.cpp
src/core/SkRecord.h
src/core/SkRecordOpts.cpp
tests/RecordTest.cpp
tests/RecordTestUtils.h

index 2d2fa58..2e03e99 100644 (file)
@@ -6,6 +6,7 @@
  */
 
 #include "SkRecord.h"
+#include <algorithm>
 
 SkRecord::~SkRecord() {
     Destroyer destroyer;
@@ -30,3 +31,12 @@ size_t SkRecord::bytesUsed() const {
     }
     return bytes;
 }
+
+void SkRecord::defrag() {
+    // Remove all the NoOps, preserving the order of other ops, e.g.
+    //      Save, ClipRect, NoOp, DrawRect, NoOp, NoOp, Restore
+    //  ->  Save, ClipRect, DrawRect, Restore
+    Record* noops = std::remove_if(fRecords.get(), fRecords.get() + fCount,
+                                   [](Record op) { return op.type() == SkRecords::NoOp_Type; });
+    fCount = noops - fRecords.get();
+}
index ee10b15..8901d62 100644 (file)
@@ -111,6 +111,10 @@ public:
     // need to iterate with a visitor to measure those they care for.
     size_t bytesUsed() const;
 
+    // Rearrange and resize this record to eliminate any NoOps.
+    // May change count() and the indices of ops, but preserves their order.
+    void defrag();
+
 private:
     // An SkRecord is structured as an array of pointers into a big chunk of memory where
     // records representing each canvas draw call are stored:
index 8faa45c..04c72c3 100644 (file)
@@ -22,6 +22,8 @@ void SkRecordOptimize(SkRecord* record) {
 
     SkRecordNoopSaveLayerDrawRestores(record);
     SkRecordMergeSvgOpacityAndFilterLayers(record);
+
+    record->defrag();
 }
 
 // Most of the optimizations in this file are pattern-based.  These are all defined as structs with:
index 9e02c88..e613b42 100644 (file)
@@ -5,13 +5,14 @@
  * found in the LICENSE file.
  */
 
-#include "Test.h"
-
+#include "RecordTestUtils.h"
 #include "SkBitmap.h"
 #include "SkImageInfo.h"
-#include "SkShader.h"
 #include "SkRecord.h"
 #include "SkRecords.h"
+#include "SkShader.h"
+#include "Test.h"
+
 
 // Sums the area of any DrawRect command it sees.
 class AreaSummer {
@@ -76,6 +77,25 @@ DEF_TEST(Record, r) {
     REPORTER_ASSERT(r, summer.area() == 500);
 }
 
+DEF_TEST(Record_defrag, r) {
+    SkRecord record;
+    APPEND(record, SkRecords::Save);
+    APPEND(record, SkRecords::ClipRect);
+    APPEND(record, SkRecords::NoOp);
+    APPEND(record, SkRecords::DrawRect);
+    APPEND(record, SkRecords::NoOp);
+    APPEND(record, SkRecords::NoOp);
+    APPEND(record, SkRecords::Restore);
+    REPORTER_ASSERT(r, record.count() == 7);
+
+    record.defrag();
+    REPORTER_ASSERT(r, record.count() == 4);
+    assert_type<SkRecords::Save    >(r, record, 0);
+    assert_type<SkRecords::ClipRect>(r, record, 1);
+    assert_type<SkRecords::DrawRect>(r, record, 2);
+    assert_type<SkRecords::Restore >(r, record, 3);
+}
+
 #undef APPEND
 
 template <typename T>
index e4421fa..a281566 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "SkRecord.h"
 #include "SkRecords.h"
+#include "Test.h"
 
 // If the command we're reading is a U, set ptr to it, otherwise set it to nullptr.
 template <typename U>