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(); |
} |