diff options
author | mtklein <mtklein@chromium.org> | 2015-05-20 10:16:49 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-20 10:16:49 -0700 |
commit | d41ea1d1cf0358e8b147c30c2dd168b631cc9b47 (patch) | |
tree | 70e5b6df6da3992cb75c9a9356d14cce7bb8e4bc | |
parent | 22483d9ca6e393635ffdf371c35026f0e8ec429c (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.cpp | 24 | ||||
-rw-r--r-- | src/core/SkMiniRecorder.h | 6 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 6 |
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); } } |