Send SkPicture deletion message lazily.

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
This commit is contained in:
mtklein 2015-04-07 06:34:05 -07:00 committed by Commit bot
parent 6cad1da6ef
commit e35268ef4c
2 changed files with 29 additions and 19 deletions

View 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;

View 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;
}