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
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
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:
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;
#include "SkBitmapDevice.h"
#include "SkConfig8888.h"
#include "SkDraw.h"
+#include "SkMallocPixelRef.h"
#include "SkMatrix.h"
#include "SkPaint.h"
#include "SkPath.h"
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;
}
}
}
-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;
}
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;
}
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,
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);
+}