aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2015-05-20 10:16:49 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-05-20 10:16:49 -0700
commitd41ea1d1cf0358e8b147c30c2dd168b631cc9b47 (patch)
tree70e5b6df6da3992cb75c9a9356d14cce7bb8e4bc
parent22483d9ca6e393635ffdf371c35026f0e8ec429c (diff)
More efficient SkRecorder::flushMiniRecorder()
This should involve no mallocs, frees, or memcpys, and less refcounting. BUG=skia: Review URL: https://codereview.chromium.org/1144173002
-rw-r--r--src/core/SkMiniRecorder.cpp24
-rw-r--r--src/core/SkMiniRecorder.h6
-rw-r--r--src/core/SkRecorder.cpp6
3 files changed, 30 insertions, 6 deletions
diff --git a/src/core/SkMiniRecorder.cpp b/src/core/SkMiniRecorder.cpp
index f851e1cac0..6707e863ac 100644
--- a/src/core/SkMiniRecorder.cpp
+++ b/src/core/SkMiniRecorder.cpp
@@ -86,12 +86,13 @@ bool SkMiniRecorder::drawTextBlob(const SkTextBlob* b, SkScalar x, SkScalar y, c
}
#undef TRY_TO_STORE
+
+SkPicture* SkMiniRecorder::detachAsPicture(const SkRect& cull) {
#define CASE(Type) \
case State::k##Type: \
fState = State::kEmpty; \
return SkNEW_ARGS(SkMiniPicture<Type>, (cull, reinterpret_cast<Type*>(fBuffer.get())))
-SkPicture* SkMiniRecorder::detachAsPicture(const SkRect& cull) {
switch (fState) {
case State::kEmpty: return SkNEW(SkEmptyPicture);
CASE(DrawPath);
@@ -99,6 +100,25 @@ SkPicture* SkMiniRecorder::detachAsPicture(const SkRect& cull) {
CASE(DrawTextBlob);
}
SkASSERT(false);
- return NULL;
+ return nullptr;
+#undef CASE
}
+
+void SkMiniRecorder::flushAndReset(SkCanvas* canvas) {
+#define CASE(Type) \
+ case State::k##Type: { \
+ fState = State::kEmpty; \
+ Type* op = reinterpret_cast<Type*>(fBuffer.get()); \
+ SkRecords::Draw(canvas, nullptr, nullptr, 0, nullptr)(*op); \
+ op->~Type(); \
+ } return
+
+ switch (fState) {
+ case State::kEmpty: return;
+ CASE(DrawPath);
+ CASE(DrawRect);
+ CASE(DrawTextBlob);
+ }
+ SkASSERT(false);
#undef CASE
+}
diff --git a/src/core/SkMiniRecorder.h b/src/core/SkMiniRecorder.h
index d01aedacea..914eccc2e3 100644
--- a/src/core/SkMiniRecorder.h
+++ b/src/core/SkMiniRecorder.h
@@ -27,6 +27,12 @@ public:
// Detach anything we've recorded as a picture, resetting this SkMiniRecorder.
SkPicture* detachAsPicture(const SkRect& cull);
+ // Flush anything we've recorded to the canvas, resetting this SkMiniRecorder.
+ // This is logically the same as but rather more efficient than:
+ // SkAutoTUnref<SkPicture> pic(this->detachAsPicture(SkRect::MakeEmpty()));
+ // pic->playback(canvas);
+ void flushAndReset(SkCanvas*);
+
private:
enum class State { kEmpty, kDrawPath, kDrawRect, kDrawTextBlob };
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 45283f8118..0989132cd2 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -136,10 +136,8 @@ char* SkRecorder::copy(const char* src) {
void SkRecorder::flushMiniRecorder() {
if (fMiniRecorder) {
SkMiniRecorder* mr = fMiniRecorder;
- fMiniRecorder = nullptr; // Needs to happen before p->playback(this) or we loop forever.
- // TODO: this can probably be done more efficiently by SkMiniRecorder if it matters.
- SkAutoTUnref<SkPicture> p(mr->detachAsPicture(SkRect::MakeEmpty()));
- p->playback(this);
+ fMiniRecorder = nullptr; // Needs to happen before flushAndReset() or we recurse forever.
+ mr->flushAndReset(this);
}
}