Index: src/gpu/GrRecordReplaceDraw.cpp |
diff --git a/src/gpu/GrRecordReplaceDraw.cpp b/src/gpu/GrRecordReplaceDraw.cpp |
index acdc63fb849c519f6c12995a02b8f83c0fee5342..f44baa7a00499c212655fdd080515bafe268ff55 100644 |
--- a/src/gpu/GrRecordReplaceDraw.cpp |
+++ b/src/gpu/GrRecordReplaceDraw.cpp |
@@ -8,47 +8,31 @@ |
#include "GrRecordReplaceDraw.h" |
#include "SkImage.h" |
#include "SkRecordDraw.h" |
- |
-GrReplacements::ReplacementInfo* GrReplacements::push() { |
- SkDEBUGCODE(this->validate()); |
- return fReplacements.push(); |
+#include "SkRecords.h" |
+#include "SkCanvasPriv.h" |
+ |
+GrReplacements::ReplacementInfo* GrReplacements::newReplacement(uint32_t pictureID, |
+ unsigned int start, |
+ const SkMatrix& ctm) { |
+ ReplacementInfo* replacement = SkNEW_ARGS(ReplacementInfo, (pictureID, start, ctm, true)); |
+ 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; |
+GrReplacements::lookupByStart(uint32_t pictureID, size_t start, const SkMatrix& ctm) const { |
+ return fReplacementHash.find(ReplacementInfo::Key(pictureID, start, ctm, true)); |
} |
static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri, |
@@ -66,6 +50,68 @@ static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo |
canvas->restore(); |
} |
+// 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 GrReplacements* replacements, |
+ const SkMatrix& initialMatrix, |
+ SkDrawPictureCallback* callback, |
+ const SkRecord* record, |
+ uint32_t pictureID) |
+ : INHERITED(canvas) |
+ , fCanvas(canvas) |
+ , fReplacements(replacements) |
+ , fInitialMatrix(initialMatrix) |
+ , fCallback(callback) |
+ , fIndex(0) |
+ , fRecord(record) |
+ , fPictureID(pictureID) { |
+ } |
+ |
+ bool done() const { return fIndex >= fRecord->count(); } |
+ void drawCur() { fRecord->visit<void>(fIndex, *this); fIndex++; } |
+ |
+ // Same as Draw for all ops except DrawPicture. |
+ 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()); |
+ |
+ GrRecordReplaceDraw(dp.picture, |
+ fCanvas, |
+ fReplacements, |
+ fInitialMatrix, |
+ fCallback); |
+ } |
+ void operator()(const SkRecords::SaveLayer& sl) { |
+ const GrReplacements::ReplacementInfo* ri; |
+ |
+ ri = fReplacements->lookupByStart(fPictureID, fIndex, fCanvas->getTotalMatrix()); |
+ if (ri) { |
+ draw_replacement_bitmap(ri, fCanvas, fInitialMatrix); |
+ fIndex = ri->fStop; |
+ return; |
+ } |
+ |
+ // This is a fail for layer hoisting |
+ this->INHERITED::operator()(sl); |
+ } |
+ |
+private: |
+ SkCanvas* fCanvas; |
+ const GrReplacements* fReplacements; |
+ const SkMatrix fInitialMatrix; |
+ SkDrawPictureCallback* fCallback; |
+ unsigned int fIndex; |
+ const SkRecord* fRecord; |
+ uint32_t fPictureID; |
+ |
+ typedef Draw INHERITED; |
+}; |
+ |
void GrRecordReplaceDraw(const SkPicture* picture, |
SkCanvas* canvas, |
const GrReplacements* replacements, |
@@ -79,9 +125,8 @@ void GrRecordReplaceDraw(const SkPicture* picture, |
return; |
} |
- SkRecords::Draw draw(canvas); |
+ ReplaceDraw draw(canvas, replacements, initialMatrix, callback, record, picture->uniqueID()); |
const GrReplacements::ReplacementInfo* ri = NULL; |
- int searchStart = 0; |
if (bbh) { |
// Draw only ops that affect pixels in the canvas's current clip. |
@@ -99,7 +144,9 @@ void GrRecordReplaceDraw(const SkPicture* picture, |
if (callback && callback->abortDrawing()) { |
return; |
} |
- ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart); |
+ ri = replacements->lookupByStart(picture->uniqueID(), |
+ (uintptr_t)ops[i], |
+ canvas->getTotalMatrix()); |
if (ri) { |
draw_replacement_bitmap(ri, canvas, initialMatrix); |
@@ -113,18 +160,12 @@ void GrRecordReplaceDraw(const SkPicture* picture, |
record->visit<void>((uintptr_t)ops[i], draw); |
} |
} else { |
- for (unsigned int i = 0; i < record->count(); ++i) { |
+ while (!draw.done()) { |
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); |
+ draw.drawCur(); |
} |
} |
} |