| Index: src/gpu/GrRecordReplaceDraw.cpp
|
| diff --git a/src/gpu/GrRecordReplaceDraw.cpp b/src/gpu/GrRecordReplaceDraw.cpp
|
| index acdc63fb849c519f6c12995a02b8f83c0fee5342..c8b2670943e4ed39a251d4c99adcdfe4487ea345 100644
|
| --- a/src/gpu/GrRecordReplaceDraw.cpp
|
| +++ b/src/gpu/GrRecordReplaceDraw.cpp
|
| @@ -6,49 +6,34 @@
|
| */
|
|
|
| #include "GrRecordReplaceDraw.h"
|
| +#include "SkCanvasPriv.h"
|
| #include "SkImage.h"
|
| #include "SkRecordDraw.h"
|
| -
|
| -GrReplacements::ReplacementInfo* GrReplacements::push() {
|
| - SkDEBUGCODE(this->validate());
|
| - return fReplacements.push();
|
| +#include "SkRecords.h"
|
| +
|
| +GrReplacements::ReplacementInfo* GrReplacements::newReplacement(uint32_t pictureID,
|
| + unsigned int start,
|
| + const SkMatrix& ctm) {
|
| + ReplacementInfo* replacement = SkNEW_ARGS(ReplacementInfo, (pictureID, start, ctm));
|
| + fReplacementHash.add(replacement);
|
| + return replacement;
|
| }
|
|
|
| void GrReplacements::freeAll() {
|
| - for (int i = 0; i < fReplacements.count(); ++i) {
|
| - fReplacements[i].fImage->unref();
|
| - SkDELETE(fReplacements[i].fPaint);
|
| - }
|
| - fReplacements.reset();
|
| -}
|
| + SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key>::Iter iter(&fReplacementHash);
|
|
|
| -#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);
|
| - }
|
| + for (; !iter.done(); ++iter) {
|
| + ReplacementInfo* replacement = &(*iter);
|
| + SkDELETE(replacement);
|
| }
|
| +
|
| + fReplacementHash.reset();
|
| }
|
| -#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;
|
| +const GrReplacements::ReplacementInfo* GrReplacements::lookupByStart(uint32_t pictureID,
|
| + size_t start,
|
| + const SkMatrix& ctm) const {
|
| + return fReplacementHash.find(ReplacementInfo::Key(pictureID, start, ctm));
|
| }
|
|
|
| static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
|
| @@ -66,65 +51,130 @@ static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo
|
| canvas->restore();
|
| }
|
|
|
| -void GrRecordReplaceDraw(const SkPicture* picture,
|
| - SkCanvas* canvas,
|
| - const GrReplacements* replacements,
|
| - const SkMatrix& initialMatrix,
|
| - SkDrawPictureCallback* callback) {
|
| - SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
|
| -
|
| - const SkBBoxHierarchy* bbh = picture->fBBH.get();
|
| - const SkRecord* record = picture->fRecord.get();
|
| - if (NULL == record) {
|
| - return;
|
| +// Used by GrRecordReplaceDraw. It intercepts nested drawPicture calls and
|
| +// also draws them with replaced layers.
|
| +class ReplaceDraw : public SkRecords::Draw {
|
| +public:
|
| + ReplaceDraw(SkCanvas* canvas,
|
| + const SkPicture* picture,
|
| + const GrReplacements* replacements,
|
| + const SkMatrix& initialMatrix,
|
| + SkDrawPictureCallback* callback)
|
| + : INHERITED(canvas)
|
| + , fCanvas(canvas)
|
| + , fPicture(picture)
|
| + , fReplacements(replacements)
|
| + , fInitialMatrix(initialMatrix)
|
| + , fCallback(callback)
|
| + , fIndex(0) {
|
| }
|
|
|
| - SkRecords::Draw draw(canvas);
|
| - const GrReplacements::ReplacementInfo* ri = NULL;
|
| - int searchStart = 0;
|
| -
|
| - if (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 (callback && callback->abortDrawing()) {
|
| - return;
|
| + void draw() {
|
| + const SkBBoxHierarchy* bbh = fPicture->fBBH.get();
|
| + const SkRecord* record = fPicture->fRecord.get();
|
| + if (NULL == record) {
|
| + return;
|
| + }
|
| +
|
| + fOps.rewind();
|
| +
|
| + if (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)fCanvas->getClipBounds(&query);
|
| +
|
| + bbh->search(query, &fOps);
|
| +
|
| + for (fIndex = 0; fIndex < fOps.count(); ++fIndex) {
|
| + if (fCallback && fCallback->abortDrawing()) {
|
| + return;
|
| + }
|
| +
|
| + record->visit<void>((uintptr_t)fOps[fIndex], *this);
|
| }
|
| - ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart);
|
| - if (ri) {
|
| - draw_replacement_bitmap(ri, canvas, initialMatrix);
|
|
|
| - while ((uintptr_t)ops[i] < ri->fStop) {
|
| - ++i;
|
| + } else {
|
| + for (fIndex = 0; fIndex < (int) record->count(); ++fIndex) {
|
| + if (fCallback && fCallback->abortDrawing()) {
|
| + return;
|
| }
|
| - SkASSERT((uintptr_t)ops[i] == ri->fStop);
|
| - continue;
|
| +
|
| + record->visit<void>(fIndex, *this);
|
| }
|
| + }
|
| + }
|
| +
|
| + // Same as Draw for all ops except DrawPicture and SaveLayer.
|
| + template <typename T> void operator()(const T& r) {
|
| + this->INHERITED::operator()(r);
|
| + }
|
| + void operator()(const SkRecords::DrawPicture& dp) {
|
| + SkAutoCanvasMatrixPaint acmp(fCanvas, dp.matrix, dp.paint, dp.picture->cullRect());
|
|
|
| - record->visit<void>((uintptr_t)ops[i], draw);
|
| + // Draw sub-pictures with the same replacement list but a different picture
|
| + ReplaceDraw draw(fCanvas, dp.picture, fReplacements, fInitialMatrix, fCallback);
|
| +
|
| + draw.draw();
|
| + }
|
| + void operator()(const SkRecords::SaveLayer& sl) {
|
| +
|
| + // For a saveLayer command, check if it can be replaced by a drawBitmap
|
| + // call and, if so, draw it and then update the current op index accordingly.
|
| + size_t startOffset;
|
| + if (fOps.count()) {
|
| + startOffset = (uintptr_t)fOps[fIndex];
|
| + } else {
|
| + startOffset = fIndex;
|
| }
|
| - } else {
|
| - for (unsigned int i = 0; i < record->count(); ++i) {
|
| - if (callback && callback->abortDrawing()) {
|
| - return;
|
| - }
|
| - ri = replacements->lookupByStart(i, &searchStart);
|
| - if (ri) {
|
| - draw_replacement_bitmap(ri, canvas, initialMatrix);
|
| - i = ri->fStop;
|
| - continue;
|
| - }
|
|
|
| - record->visit<void>(i, draw);
|
| + const GrReplacements::ReplacementInfo* ri = fReplacements->lookupByStart(
|
| + fPicture->uniqueID(),
|
| + startOffset,
|
| + fCanvas->getTotalMatrix());
|
| +
|
| + if (ri) {
|
| + draw_replacement_bitmap(ri, fCanvas, fInitialMatrix);
|
| +
|
| + if (fPicture->fBBH.get()) {
|
| + while ((uintptr_t)fOps[fIndex] < ri->fStop) {
|
| + ++fIndex;
|
| + }
|
| + SkASSERT((uintptr_t)fOps[fIndex] == ri->fStop);
|
| + } else {
|
| + fIndex = ri->fStop;
|
| + }
|
| + return;
|
| }
|
| +
|
| + // This is a fail for layer hoisting
|
| + this->INHERITED::operator()(sl);
|
| }
|
| +
|
| +private:
|
| + SkCanvas* fCanvas;
|
| + const SkPicture* fPicture;
|
| + const GrReplacements* fReplacements;
|
| + const SkMatrix fInitialMatrix;
|
| + SkDrawPictureCallback* fCallback;
|
| +
|
| + SkTDArray<void*> fOps;
|
| + int fIndex;
|
| +
|
| + typedef Draw INHERITED;
|
| +};
|
| +
|
| +void GrRecordReplaceDraw(const SkPicture* picture,
|
| + SkCanvas* canvas,
|
| + const GrReplacements* replacements,
|
| + const SkMatrix& initialMatrix,
|
| + SkDrawPictureCallback* callback) {
|
| + SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
|
| +
|
| + ReplaceDraw draw(canvas, picture, replacements, initialMatrix, callback);
|
| +
|
| + draw.draw();
|
| }
|
|
|