diff options
author | 2014-09-03 11:04:30 -0700 | |
---|---|---|
committer | 2014-09-03 11:04:31 -0700 | |
commit | d982eb22d7bce655a609e9b481b3ddfeff361067 (patch) | |
tree | 30864835861825a9ec9f69c1d7a045c9e5c8a3a7 /src/gpu/GrRecordReplaceDraw.cpp | |
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/gpu/GrRecordReplaceDraw.cpp')
-rw-r--r-- | src/gpu/GrRecordReplaceDraw.cpp | 119 |
1 files changed, 119 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); + } + } +} |