For non-opaque SkBitmapDevices, replace malloc-then-zero with calloc.
authormtklein <mtklein@chromium.org>
Thu, 5 Nov 2015 17:46:23 +0000 (09:46 -0800)
committerCommit bot <commit-bot@chromium.org>
Thu, 5 Nov 2015 17:46:23 +0000 (09:46 -0800)
There seem about a zillion possible ways to slice this.
This adds and uses SkMallocPixelRef::ZeroedPRFactory.
I'm not married to it.

This appears to clear up a hot spot in the benchmark referenced in this bug:
BUG=516426
I'm not confident enough on Windows to declare that definitively yet.

It probably helps all other non-opaque layers too.  Possibly significantly.

So I don't forget, I profiled this:
out/Release/performance_browser_tests.exe  --gtest_filter=TabCapturePerformanceTest.Performance/2 --single-process

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

TBR=reed@google.com

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

include/core/SkMallocPixelRef.h
src/core/SkBitmapDevice.cpp
src/core/SkMallocPixelRef.cpp

index 1baceae1667fad1a772292dabb301afe6d23c08a..ab337b9241ec72a9364b0d35cbbe70f257b45fc0 100644 (file)
@@ -42,6 +42,12 @@ public:
     static SkMallocPixelRef* NewAllocate(const SkImageInfo& info,
                                          size_t rowBytes, SkColorTable*);
 
+    /**
+     *  Identical to NewAllocate, except all pixel bytes are zeroed.
+     */
+    static SkMallocPixelRef* NewZeroed(const SkImageInfo& info,
+                                       size_t rowBytes, SkColorTable*);
+
     /**
      *  Return a new SkMallocPixelRef with the provided pixel storage,
      *  rowBytes, and optional colortable. On destruction, ReleaseProc
@@ -81,9 +87,12 @@ public:
 
     class PRFactory : public SkPixelRefFactory {
     public:
-        virtual SkPixelRef* create(const SkImageInfo&,
-                                   size_t rowBytes,
-                                   SkColorTable*) override;
+        SkPixelRef* create(const SkImageInfo&, size_t rowBytes, SkColorTable*) override;
+    };
+
+    class ZeroedPRFactory : public SkPixelRefFactory {
+    public:
+        SkPixelRef* create(const SkImageInfo&, size_t rowBytes, SkColorTable*) override;
     };
 
 protected:
@@ -97,6 +106,12 @@ protected:
     size_t getAllocatedSizeInBytes() const override;
 
 private:
+    // Uses alloc to implement NewAllocate or NewZeroed.
+    static SkMallocPixelRef* NewUsing(void*(*alloc)(size_t),
+                                      const SkImageInfo&,
+                                      size_t rowBytes,
+                                      SkColorTable*);
+
     void*           fStorage;
     SkColorTable*   fCTable;
     size_t          fRB;
index b7df9a4c25890c3a3c3fde7e544817bdff226d21..ac3b9df0827ed51aedfb5f5520c7457ced5e7a8a 100644 (file)
@@ -8,6 +8,7 @@
 #include "SkBitmapDevice.h"
 #include "SkConfig8888.h"
 #include "SkDraw.h"
+#include "SkMallocPixelRef.h"
 #include "SkMatrix.h"
 #include "SkPaint.h"
 #include "SkPath.h"
@@ -94,12 +95,18 @@ SkBitmapDevice* SkBitmapDevice::Create(const SkImageInfo& origInfo,
         if (!bitmap.setInfo(info)) {
             return nullptr;
         }
-    } else {
+    } else if (bitmap.info().isOpaque()) {
+        // If this bitmap is opaque, we don't have any sensible default color,
+        // so we just return uninitialized pixels.
         if (!bitmap.tryAllocPixels(info)) {
             return nullptr;
         }
-        if (!bitmap.info().isOpaque()) {
-            bitmap.eraseColor(SK_ColorTRANSPARENT);
+    } else {
+        // This bitmap has transparency, so we'll zero the pixels (to transparent).
+        // We use a ZeroedPRFactory as a faster alloc-then-eraseColor(SK_ColorTRANSPARENT).
+        SkMallocPixelRef::ZeroedPRFactory factory;
+        if (!bitmap.tryAllocPixels(info, &factory, nullptr/*color table*/)) {
+            return nullptr;
         }
     }
 
index 0196e046b17061505f63572e699c3552937791a3..fffc0448486cb26ad96d4b5a09da5f0a6724b2f6 100644 (file)
@@ -48,9 +48,10 @@ SkMallocPixelRef* SkMallocPixelRef::NewDirect(const SkImageInfo& info,
 }
 
 
-SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
-                                                size_t requestedRowBytes,
-                                                SkColorTable* ctable) {
+ SkMallocPixelRef* SkMallocPixelRef::NewUsing(void*(*alloc)(size_t),
+                                              const SkImageInfo& info,
+                                              size_t requestedRowBytes,
+                                              SkColorTable* ctable) {
     if (!is_valid(info, ctable)) {
         return nullptr;
     }
@@ -78,7 +79,7 @@ SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
 
     size_t size = sk_64_asS32(bigSize);
     SkASSERT(size >= info.getSafeSize(rowBytes));
-    void* addr = sk_malloc_flags(size, 0);
+    void* addr = alloc(size);
     if (nullptr == addr) {
         return nullptr;
     }
@@ -86,6 +87,19 @@ SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
     return new SkMallocPixelRef(info, addr, rowBytes, ctable, sk_free_releaseproc, nullptr);
 }
 
+SkMallocPixelRef* SkMallocPixelRef::NewAllocate(const SkImageInfo& info,
+                                                size_t rowBytes,
+                                                SkColorTable* ctable) {
+    auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
+    return NewUsing(sk_malloc_nothrow, info, rowBytes, ctable);
+}
+
+SkMallocPixelRef* SkMallocPixelRef::NewZeroed(const SkImageInfo& info,
+                                              size_t rowBytes,
+                                              SkColorTable* ctable) {
+    return NewUsing(sk_calloc, info, rowBytes, ctable);
+}
+
 SkMallocPixelRef* SkMallocPixelRef::NewWithProc(const SkImageInfo& info,
                                                 size_t rowBytes,
                                                 SkColorTable* ctable,
@@ -201,3 +215,8 @@ SkPixelRef* SkMallocPixelRef::PRFactory::create(const SkImageInfo& info, size_t
                                                 SkColorTable* ctable) {
     return SkMallocPixelRef::NewAllocate(info, rowBytes, ctable);
 }
+
+SkPixelRef* SkMallocPixelRef::ZeroedPRFactory::create(const SkImageInfo& info, size_t rowBytes,
+                                                      SkColorTable* ctable) {
+    return SkMallocPixelRef::NewZeroed(info, rowBytes, ctable);
+}