diff options
author | 2014-09-03 11:04:30 -0700 | |
---|---|---|
committer | 2014-09-03 11:04:31 -0700 | |
commit | d982eb22d7bce655a609e9b481b3ddfeff361067 (patch) | |
tree | 30864835861825a9ec9f69c1d7a045c9e5c8a3a7 /src | |
parent | 74364c97740eb48c86d6e7b42520c77130eb1486 (diff) |
Replace SkPictureReplacementPlayback with GrRecordReplaceDraw
I think this is sufficiently specialized to keep it in Ganesh for the time being.
R=bsalomon@google.com, mtklein@google.com
Author: robertphillips@google.com
Review URL: https://codereview.chromium.org/535953002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrRecordReplaceDraw.cpp | 119 | ||||
-rw-r--r-- | src/gpu/GrRecordReplaceDraw.h | 69 |
2 files changed, 188 insertions, 0 deletions
diff --git a/src/gpu/GrRecordReplaceDraw.cpp b/src/gpu/GrRecordReplaceDraw.cpp new file mode 100644 index 0000000000..8291ccb828 --- /dev/null +++ b/src/gpu/GrRecordReplaceDraw.cpp @@ -0,0 +1,119 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrRecordReplaceDraw.h" +#include "SkImage.h" +#include "SkRecordDraw.h" + +GrReplacements::ReplacementInfo* GrReplacements::push() { + SkDEBUGCODE(this->validate()); + return fReplacements.push(); +} + +void GrReplacements::freeAll() { + for (int i = 0; i < fReplacements.count(); ++i) { + fReplacements[i].fImage->unref(); + } + fReplacements.reset(); +} + +#ifdef SK_DEBUG +void GrReplacements::validate() const { + // Check that the ranges are monotonically increasing and non-overlapping + if (fReplacements.count() > 0) { + SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop); + + for (int i = 1; i < fReplacements.count(); ++i) { + SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop); + SkASSERT(fReplacements[i - 1].fStop < fReplacements[i].fStart); + } + } +} +#endif + +const GrReplacements::ReplacementInfo* +GrReplacements::lookupByStart(size_t start, int* searchStart) const { + SkDEBUGCODE(this->validate()); + for (int i = *searchStart; i < fReplacements.count(); ++i) { + if (start == fReplacements[i].fStart) { + *searchStart = i + 1; + return &fReplacements[i]; + } else if (start < fReplacements[i].fStart) { + return NULL; // the ranges are monotonically increasing and non-overlapping + } + } + + return NULL; +} + +static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri, + SkCanvas* canvas) { + SkRect src = SkRect::Make(ri->fSrcRect); + SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX), + SkIntToScalar(ri->fPos.fY), + SkIntToScalar(ri->fSrcRect.width()), + SkIntToScalar(ri->fSrcRect.height())); + ri->fImage->draw(canvas, &src, dst, ri->fPaint); +} + +void GrRecordReplaceDraw(const SkRecord& record, + SkCanvas* canvas, + const SkBBoxHierarchy* bbh, + const GrReplacements* replacements, + SkDrawPictureCallback* callback) { + SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/); + + SkRecords::Draw draw(canvas); + const GrReplacements::ReplacementInfo* ri = NULL; + int searchStart = 0; + + if (NULL != bbh) { + // Draw only ops that affect pixels in the canvas's current clip. + // The SkRecord and BBH were recorded in identity space. This canvas + // is not necessarily in that same space. getClipBounds() returns us + // this canvas' clip bounds transformed back into identity space, which + // lets us query the BBH. + SkRect query = { 0, 0, 0, 0 }; + (void)canvas->getClipBounds(&query); + + SkTDArray<void*> ops; + bbh->search(query, &ops); + + for (int i = 0; i < ops.count(); i++) { + if (NULL != callback && callback->abortDrawing()) { + return; + } + ri = replacements->lookupByStart(i, &searchStart); + if (NULL != ri) { + draw_replacement_bitmap(ri, canvas); + + while ((uintptr_t)ops[i] < ri->fStop) { + ++i; + } + SkASSERT((uintptr_t)ops[i] == ri->fStop); + continue; + } + + record.visit<void>((uintptr_t)ops[i], draw); + } + } else { + for (unsigned int i = 0; i < record.count(); ++i) { + if (NULL != callback && callback->abortDrawing()) { + return; + } + ri = replacements->lookupByStart(i, &searchStart); + if (NULL != ri) { + draw_replacement_bitmap(ri, canvas); + + i = ri->fStop; + continue; + } + + record.visit<void>(i, draw); + } + } +} diff --git a/src/gpu/GrRecordReplaceDraw.h b/src/gpu/GrRecordReplaceDraw.h new file mode 100644 index 0000000000..f59e44883e --- /dev/null +++ b/src/gpu/GrRecordReplaceDraw.h @@ -0,0 +1,69 @@ +/* + * Copyright 2014 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrRecordReplaceDraw_DEFINED +#define GrRecordReplaceDraw_DEFINED + +#include "SkDrawPictureCallback.h" +#include "SkRect.h" +#include "SkTDArray.h" + +class SkBBoxHierarchy; +class SkBitmap; +class SkCanvas; +class SkImage; +class SkPaint; +class SkRecord; + +// GrReplacements collects op ranges that can be replaced with +// a single drawBitmap call (using a precomputed bitmap). +class GrReplacements { +public: + // All the operations between fStart and fStop (inclusive) will be replaced with + // a single drawBitmap call using fPos, fBM and fPaint. + struct ReplacementInfo { + unsigned fStart; + unsigned fStop; + SkIPoint fPos; + SkImage* fImage; // Owns a ref + const SkPaint* fPaint; // Note: this object doesn't own the paint + + SkIRect fSrcRect; + }; + + ~GrReplacements() { this->freeAll(); } + + // Add a new replacement range. The replacement ranges should be + // sorted in increasing order and non-overlapping (esp. no nested + // saveLayers). + ReplacementInfo* push(); + + // look up a replacement range by its start offset. + // lastLookedUp is an in/out parameter that is used to speed up the search. + // It should be initialized to 0 on the first call and then passed back in + // unmodified on subsequent calls. + const ReplacementInfo* lookupByStart(size_t start, int* lastLookedUp) const; + +private: + SkTDArray<ReplacementInfo> fReplacements; + + void freeAll(); + +#ifdef SK_DEBUG + void validate() const; +#endif +}; + +// Draw an SkRecord into an SkCanvas replacing saveLayer/restore blocks with +// drawBitmap calls. A convenience wrapper around SkRecords::Draw. +void GrRecordReplaceDraw(const SkRecord&, + SkCanvas*, + const SkBBoxHierarchy*, + const GrReplacements*, + SkDrawPictureCallback*); + +#endif // GrRecordReplaceDraw_DEFINED |