Send SkPicture deletion message lazily.
authormtklein <mtklein@chromium.org>
Tue, 7 Apr 2015 13:34:05 +0000 (06:34 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 7 Apr 2015 13:34:05 +0000 (06:34 -0700)
If no one has read the picture's unique ID, there's no point invalidating it.

This is the same trick we pull with SkPixelRefs.

Before:
  26M 1 1.49µs 1.6µs 1.77µs 6.25µs 42% picture_overhead_draw
  13M 32 742ns 749ns 756ns 823ns 2% picture_overhead_nodraw

After:
  26M 1 1.27µs 1.33µs 1.49µs 5.51µs 45% picture_overhead_draw
  14M 43 677ns 680ns 681ns 701ns 1% picture_overhead_nodraw

BUG=skia:

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

include/core/SkPicture.h
src/core/SkPicture.cpp

index a62bedb..2dc9258 100644 (file)
@@ -136,7 +136,7 @@ public:
 
     /** Return a non-zero, unique value representing the picture.
      */
-    uint32_t uniqueID() const { return fUniqueID; }
+    uint32_t uniqueID() const;
 
     /**
      *  Serialize to a stream. If non NULL, serializer will be used to serialize
@@ -263,7 +263,7 @@ private:
                                    SkPicture const* const drawablePics[], int drawableCount);
 
     // uint32_t fRefCnt; from SkNVRefCnt<SkPicture>
-    const uint32_t                        fUniqueID;
+    mutable uint32_t                      fUniqueID;
     const SkRect                          fCullRect;
     mutable SkAutoTUnref<const AccelData> fAccelData;
     SkAutoTUnref<const SkRecord>          fRecord;
index c7e36e7..a8ddfe6 100644 (file)
@@ -12,6 +12,7 @@
 #include "SkPictureRecord.h"
 #include "SkPictureRecorder.h"
 
+#include "SkAtomics.h"
 #include "SkBitmapDevice.h"
 #include "SkCanvas.h"
 #include "SkChunkAlloc.h"
@@ -46,18 +47,6 @@ template <typename T> int SafeCount(const T* obj) {
     return obj ? obj->count() : 0;
 }
 
-static int32_t gPictureGenerationID;
-
-// never returns a 0
-static int32_t next_picture_generation_id() {
-    // Loop in case our global wraps around.
-    int32_t genID;
-    do {
-        genID = sk_atomic_inc(&gPictureGenerationID) + 1;
-    } while (0 == genID);
-    return genID;
-}
-
 ///////////////////////////////////////////////////////////////////////////////
 
 namespace {
@@ -247,7 +236,7 @@ bool SkPicture::Analysis::suitableForGpuRasterization(const char** reason,
         numSlowPathDashedPaths -= fNumFastPathDashEffects;
     }
 
-    int numSlowPaths = fNumAAConcavePaths - 
+    int numSlowPaths = fNumAAConcavePaths -
                        fNumAAHairlineConcavePaths -
                        fNumAADFEligibleConcavePaths;
 
@@ -270,9 +259,13 @@ SkPicture const* const* SkPicture::drawablePicts() const {
 }
 
 SkPicture::~SkPicture() {
-    SkPicture::DeletionMessage msg;
-    msg.fUniqueID = this->uniqueID();
-    SkMessageBus<SkPicture::DeletionMessage>::Post(msg);
+    // If the ID is still zero, no one has read it, so no need to send this message.
+    uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
+    if (id != 0) {
+        SkPicture::DeletionMessage msg;
+        msg.fUniqueID = id;
+        SkMessageBus<SkPicture::DeletionMessage>::Post(msg);
+    }
 }
 
 void SkPicture::EXPERIMENTAL_addAccelData(const SkPicture::AccelData* data) const {
@@ -488,10 +481,27 @@ int  SkPicture::approximateOpCount()  const { return fRecord->count(); }
 
 SkPicture::SkPicture(const SkRect& cullRect, SkRecord* record, SnapshotArray* drawablePicts,
                      SkBBoxHierarchy* bbh)
-    : fUniqueID(next_picture_generation_id())
+    : fUniqueID(0)
     , fCullRect(cullRect)
     , fRecord(SkRef(record))
     , fBBH(SkSafeRef(bbh))
     , fDrawablePicts(drawablePicts)     // take ownership
     , fAnalysis(*fRecord)
 {}
+
+
+static uint32_t gNextID = 1;
+uint32_t SkPicture::uniqueID() const {
+    uint32_t id = sk_atomic_load(&fUniqueID, sk_memory_order_relaxed);
+    while (id == 0) {
+        uint32_t next = sk_atomic_fetch_add(&gNextID, 1u);
+        if (sk_atomic_compare_exchange(&fUniqueID, &id, next,
+                                       sk_memory_order_relaxed,
+                                       sk_memory_order_relaxed)) {
+            id = next;
+        } else {
+            // sk_atomic_compare_exchange replaced id with the current value of fUniqueID.
+        }
+    }
+    return id;
+}