aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar reed <reed@google.com>2014-11-18 11:08:05 -0800
committerGravatar Commit bot <commit-bot@chromium.org>2014-11-18 11:08:05 -0800
commit6be2aa9a251bf6022570a03140f956655b3ef1da (patch)
tree52ccd2b4fd1fde02617f08ee03d30faee917c38f
parentad3a8846f8963e03faa6de647502e1c553161ecb (diff)
wip for drawables
Idea: 1. in its mutable recording state, keep a table of drawables on the side, and store an index in the record list. 2. In "immediate-mode" draw, just call the clients drawable directly (need access to our private list to turn the stored index into a proc) 3. when we "snap", we replace the list of drawables with a list of (sub) pictures, and then during playback of the snapped picture, we invoke a private drawable which just calls "drawPicture" on the index'd subpicture. Review URL: https://codereview.chromium.org/727363003
-rw-r--r--include/core/SkPicture.h19
-rw-r--r--samplecode/SampleArc.cpp6
-rw-r--r--src/core/SkCanvas.cpp7
-rw-r--r--src/core/SkCanvasDrawable.cpp21
-rw-r--r--src/core/SkCanvasDrawable.h18
-rw-r--r--src/core/SkPicture.cpp34
-rw-r--r--src/core/SkPictureRecorder.cpp12
-rw-r--r--src/core/SkRecordDraw.cpp21
-rw-r--r--src/core/SkRecordDraw.h26
-rw-r--r--src/core/SkRecorder.cpp50
-rw-r--r--src/core/SkRecorder.h7
-rw-r--r--src/core/SkRecords.h3
-rw-r--r--src/gpu/GrLayerHoister.cpp10
-rw-r--r--src/gpu/GrRecordReplaceDraw.cpp9
-rw-r--r--tests/RecordDrawTest.cpp14
-rw-r--r--tools/DumpRecord.cpp2
16 files changed, 202 insertions, 57 deletions
diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h
index c4c6f20326..99bca367d9 100644
--- a/include/core/SkPicture.h
+++ b/include/core/SkPicture.h
@@ -259,11 +259,13 @@ private:
void createHeader(SkPictInfo* info) const;
static bool IsValidPictInfo(const SkPictInfo& info);
- // Takes ownership of the SkRecord, refs the (optional) BBH.
- SkPicture(SkScalar width, SkScalar height, SkRecord*, SkBBoxHierarchy*);
+ // Takes ownership of the SkRecord, refs the (optional) drawablePicts and BBH.
+ SkPicture(SkScalar width, SkScalar height, SkRecord*, SkData* drawablePicts,
+ SkBBoxHierarchy*);
static SkPicture* Forwardport(const SkPictInfo&, const SkPictureData*);
- static SkPictureData* Backport(const SkRecord&, const SkPictInfo&);
+ static SkPictureData* Backport(const SkRecord&, const SkPictInfo&,
+ SkPicture const* const drawablePics[], int drawableCount);
const SkScalar fCullWidth;
const SkScalar fCullHeight;
@@ -271,6 +273,15 @@ private:
mutable SkTDArray<DeletionListener*> fDeletionListeners; // pointers are refed
SkAutoTDelete<SkRecord> fRecord;
SkAutoTUnref<SkBBoxHierarchy> fBBH;
+ SkAutoTUnref<SkData> fDrawablePicts;
+
+ // helpers for fDrawablePicts
+ int drawableCount() const;
+ // will return NULL if drawableCount() returns 0
+ SkPicture const* const* drawablePicts() const;
+
+ struct PathCounter;
+
struct Analysis {
Analysis() {} // Only used by SkPictureData codepath.
explicit Analysis(const SkRecord&);
@@ -287,8 +298,6 @@ private:
} fAnalysis;
mutable uint32_t fUniqueID;
- struct PathCounter;
-
friend class SkPictureRecorder; // SkRecord-based constructor.
friend class GrLayerHoister; // access to fRecord
friend class ReplaceDraw;
diff --git a/samplecode/SampleArc.cpp b/samplecode/SampleArc.cpp
index c9310d6dd6..a44eeb59ba 100644
--- a/samplecode/SampleArc.cpp
+++ b/samplecode/SampleArc.cpp
@@ -72,6 +72,12 @@ class ArcsView : public SampleView {
paint.setColor(SK_ColorBLUE);
canvas->drawArc(fR, 0, fSweep, false, paint);
}
+
+ SkRect onGetBounds() SK_OVERRIDE {
+ SkRect r(fR);
+ r.outset(2, 2);
+ return r;
+ }
};
public:
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 6cd6dda322..8d17be7bfe 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -2299,11 +2299,8 @@ void SkCanvas::onDrawPatch(const SkPoint cubics[12], const SkColor colors[4],
}
void SkCanvas::EXPERIMENTAL_drawDrawable(SkCanvasDrawable* dr) {
- if (dr) {
- SkRect bounds;
- if (!dr->getBounds(&bounds) || !this->quickReject(bounds)) {
- this->onDrawDrawable(dr);
- }
+ if (dr && !this->quickReject(dr->getBounds())) {
+ this->onDrawDrawable(dr);
}
}
diff --git a/src/core/SkCanvasDrawable.cpp b/src/core/SkCanvasDrawable.cpp
index 7c01738dd6..0065d430f9 100644
--- a/src/core/SkCanvasDrawable.cpp
+++ b/src/core/SkCanvasDrawable.cpp
@@ -28,6 +28,10 @@ void SkCanvasDrawable::draw(SkCanvas* canvas) {
this->onDraw(canvas);
}
+SkPicture* SkCanvasDrawable::newPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags) {
+ return this->onNewPictureSnapshot(bbhFactory, recordFlags);
+}
+
uint32_t SkCanvasDrawable::getGenerationID() {
if (0 == fGenerationID) {
fGenerationID = next_generation_id();
@@ -35,16 +39,21 @@ uint32_t SkCanvasDrawable::getGenerationID() {
return fGenerationID;
}
-bool SkCanvasDrawable::getBounds(SkRect* boundsPtr) {
- SkRect bounds;
- if (!boundsPtr) {
- boundsPtr = &bounds;
- }
- return this->onGetBounds(boundsPtr);
+SkRect SkCanvasDrawable::getBounds() {
+ return this->onGetBounds();
}
void SkCanvasDrawable::notifyDrawingChanged() {
fGenerationID = 0;
}
+/////////////////////////////////////////////////////////////////////////////////////////
+#include "SkPictureRecorder.h"
+
+SkPicture* SkCanvasDrawable::onNewPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags) {
+ const SkRect bounds = this->getBounds();
+ SkPictureRecorder recorder;
+ this->draw(recorder.beginRecording(bounds.width(), bounds.height(), bbhFactory, recordFlags));
+ return recorder.endRecording();
+}
diff --git a/src/core/SkCanvasDrawable.h b/src/core/SkCanvasDrawable.h
index 807bbc7ab1..f189f2d2cc 100644
--- a/src/core/SkCanvasDrawable.h
+++ b/src/core/SkCanvasDrawable.h
@@ -10,6 +10,7 @@
#include "SkRefCnt.h"
+class SkBBHFactory;
class SkCanvas;
struct SkRect;
@@ -31,6 +32,11 @@ public:
*/
void draw(SkCanvas*);
+ SkPicture* newPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags);
+ SkPicture* newPictureSnapshot() {
+ return this->newPictureSnapshot(NULL, 0);
+ }
+
/**
* Return a unique value for this instance. If two calls to this return the same value,
* it is presumed that calling the draw() method will render the same thing as well.
@@ -41,11 +47,11 @@ public:
uint32_t getGenerationID();
/**
- * If the drawable knows a bounds that will contains all of its drawing, return true and
- * set the parameter to that rectangle. If one is not known, ignore the parameter and
- * return false.
+ * Return the (conservative) bounds of what the drawable will draw. If the drawable can
+ * change what it draws (e.g. animation or in response to some external change), then this
+ * must return a bounds that is always valid for all possible states.
*/
- bool getBounds(SkRect*);
+ SkRect getBounds();
/**
* Calling this invalidates the previous generation ID, and causes a new one to be computed
@@ -55,9 +61,9 @@ public:
void notifyDrawingChanged();
protected:
+ virtual SkRect onGetBounds() = 0;
virtual void onDraw(SkCanvas*) = 0;
-
- virtual bool onGetBounds(SkRect*) { return false; }
+ virtual SkPicture* onNewPictureSnapshot(SkBBHFactory*, uint32_t recordFlags);
private:
int32_t fGenerationID;
diff --git a/src/core/SkPicture.cpp b/src/core/SkPicture.cpp
index e2514c67d6..4c97cb71b9 100644
--- a/src/core/SkPicture.cpp
+++ b/src/core/SkPicture.cpp
@@ -257,6 +257,21 @@ bool SkPicture::Analysis::suitableForGpuRasterization(const char** reason,
///////////////////////////////////////////////////////////////////////////////
+int SkPicture::drawableCount() const {
+ if (fDrawablePicts.get()) {
+ return SkToInt(fDrawablePicts->size() / sizeof(SkPicture*));
+ } else {
+ return 0;
+ }
+}
+
+SkPicture const* const* SkPicture::drawablePicts() const {
+ if (fDrawablePicts) {
+ return reinterpret_cast<SkPicture* const*>(fDrawablePicts->data());
+ }
+ return NULL;
+}
+
SkPicture::~SkPicture() {
this->callDeletionListeners();
}
@@ -294,7 +309,8 @@ void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) cons
(void)canvas->getClipBounds(&clipBounds);
const bool useBBH = !clipBounds.contains(this->cullRect());
- SkRecordDraw(*fRecord, canvas, useBBH ? fBBH.get() : NULL, callback);
+ SkRecordDraw(*fRecord, canvas, this->drawablePicts(), this->drawableCount(),
+ useBBH ? fBBH.get() : NULL, callback);
}
///////////////////////////////////////////////////////////////////////////////
@@ -444,19 +460,20 @@ void SkPicture::createHeader(SkPictInfo* info) const {
}
// This for compatibility with serialization code only. This is not cheap.
-SkPictureData* SkPicture::Backport(const SkRecord& src, const SkPictInfo& info) {
+SkPictureData* SkPicture::Backport(const SkRecord& src, const SkPictInfo& info,
+ SkPicture const* const drawablePicts[], int drawableCount) {
SkPictureRecord rec(SkISize::Make(info.fCullRect.width(), info.fCullRect.height()), 0/*flags*/);
rec.beginRecording();
- SkRecordDraw(src, &rec, NULL/*bbh*/, NULL/*callback*/);
+ SkRecordDraw(src, &rec, drawablePicts, drawableCount, NULL/*bbh*/, NULL/*callback*/);
rec.endRecording();
return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
}
-
void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
SkPictInfo info;
this->createHeader(&info);
- SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info));
+ SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info, this->drawablePicts(),
+ this->drawableCount()));
stream->write(&info, sizeof(info));
if (data) {
@@ -470,7 +487,8 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
void SkPicture::flatten(SkWriteBuffer& buffer) const {
SkPictInfo info;
this->createHeader(&info);
- SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info));
+ SkAutoTDelete<SkPictureData> data(Backport(*fRecord, info, this->drawablePicts(),
+ this->drawableCount()));
buffer.writeByteArray(&info.fMagic, sizeof(info.fMagic));
buffer.writeUInt(info.fVersion);
@@ -512,11 +530,13 @@ uint32_t SkPicture::uniqueID() const {
return fUniqueID;
}
-SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkBBoxHierarchy* bbh)
+SkPicture::SkPicture(SkScalar width, SkScalar height, SkRecord* record, SkData* drawablePicts,
+ SkBBoxHierarchy* bbh)
: fCullWidth(width)
, fCullHeight(height)
, fRecord(record)
, fBBH(SkSafeRef(bbh))
+ , fDrawablePicts(SkSafeRef(drawablePicts))
, fAnalysis(*fRecord) {
this->needsNewGenID();
}
diff --git a/src/core/SkPictureRecorder.cpp b/src/core/SkPictureRecorder.cpp
index 3441a0dfeb..bc8bffb9b3 100644
--- a/src/core/SkPictureRecorder.cpp
+++ b/src/core/SkPictureRecorder.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkData.h"
#include "SkLayerInfo.h"
#include "SkPictureRecorder.h"
#include "SkRecord.h"
@@ -60,7 +61,12 @@ SkPicture* SkPictureRecorder::endRecording() {
}
}
- SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight, fRecord.detach(), fBBH.get()));
+ // TODO: we should remember these from our caller
+ SkBBHFactory* factory = NULL;
+ uint32_t recordFlags = 0;
+ SkAutoDataUnref drawablePicts(fRecorder->newDrawableSnapshot(factory, recordFlags));
+ SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullWidth, fCullHeight, fRecord.detach(),
+ drawablePicts, fBBH.get()));
if (saveLayerData) {
pict->EXPERIMENTAL_addAccelData(saveLayerData);
@@ -73,5 +79,7 @@ void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
if (NULL == canvas) {
return;
}
- SkRecordDraw(*fRecord, canvas, NULL/*bbh*/, NULL/*callback*/);
+
+ int drawableCount = 0;
+ SkRecordDraw(*fRecord, canvas, NULL, drawableCount, NULL/*bbh*/, NULL/*callback*/);
}
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 77235fda41..323ceca0e1 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -11,6 +11,7 @@
void SkRecordDraw(const SkRecord& record,
SkCanvas* canvas,
+ SkPicture const* const drawablePicts[], int drawableCount,
const SkBBoxHierarchy* bbh,
SkDrawPictureCallback* callback) {
SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
@@ -29,7 +30,7 @@ void SkRecordDraw(const SkRecord& record,
SkTDArray<unsigned> ops;
bbh->search(query, &ops);
- SkRecords::Draw draw(canvas);
+ SkRecords::Draw draw(canvas, drawablePicts, drawableCount);
for (int i = 0; i < ops.count(); i++) {
if (callback && callback->abortDrawing()) {
return;
@@ -41,7 +42,7 @@ void SkRecordDraw(const SkRecord& record,
}
} else {
// Draw all ops.
- SkRecords::Draw draw(canvas);
+ SkRecords::Draw draw(canvas, drawablePicts, drawableCount);
for (unsigned i = 0; i < record.count(); i++) {
if (callback && callback->abortDrawing()) {
return;
@@ -54,15 +55,15 @@ void SkRecordDraw(const SkRecord& record,
}
}
-void SkRecordPartialDraw(const SkRecord& record,
- SkCanvas* canvas,
+void SkRecordPartialDraw(const SkRecord& record, SkCanvas* canvas,
+ SkPicture const* const drawablePicts[], int drawableCount,
const SkRect& clearRect,
unsigned start, unsigned stop,
const SkMatrix& initialCTM) {
SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
stop = SkTMin(stop, record.count());
- SkRecords::PartialDraw draw(canvas, clearRect, initialCTM);
+ SkRecords::PartialDraw draw(canvas, NULL, 0, clearRect, initialCTM);
for (unsigned i = start; i < stop; i++) {
record.visit<void>(i, draw);
}
@@ -123,6 +124,12 @@ DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.co
DRAW(DrawData, drawData(r.data, r.length));
#undef DRAW
+template <> void Draw::draw(const DrawDrawable& r) {
+ SkASSERT(r.index >= 0);
+ SkASSERT(r.index < fDrawableCount);
+ fCanvas->drawPicture(fDrawablePicts[r.index]);
+}
+
// This is an SkRecord visitor that fills an SkBBoxHierarchy.
//
// The interesting part here is how to calculate bounds for ops which don't
@@ -502,6 +509,10 @@ private:
return this->adjustAndMap(dst, &op.paint);
}
+ Bounds bounds(const DrawDrawable& op) const {
+ return this->adjustAndMap(op.worstCaseBounds, NULL);
+ }
+
static void AdjustTextForFontMetrics(SkRect* rect, const SkPaint& paint) {
#ifdef SK_DEBUG
SkRect correct = *rect;
diff --git a/src/core/SkRecordDraw.h b/src/core/SkRecordDraw.h
index 9b39dd6adb..8ea1bbd72f 100644
--- a/src/core/SkRecordDraw.h
+++ b/src/core/SkRecordDraw.h
@@ -23,14 +23,17 @@ void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
SkBBoxHierarchy* bbh, SkLayerInfo* data);
// Draw an SkRecord into an SkCanvas. A convenience wrapper around SkRecords::Draw.
-void SkRecordDraw(const SkRecord&, SkCanvas*, const SkBBoxHierarchy*, SkDrawPictureCallback*);
+void SkRecordDraw(const SkRecord&, SkCanvas*, SkPicture const* const drawablePicts[], int drawableCount,
+ const SkBBoxHierarchy*, SkDrawPictureCallback*);
// Draw a portion of an SkRecord into an SkCanvas while replacing clears with drawRects.
// When drawing a portion of an SkRecord the CTM on the passed in canvas must be
// the composition of the replay matrix with the record-time CTM (for the portion
// of the record that is being replayed). For setMatrix calls to behave correctly
// the initialCTM parameter must set to just the replay matrix.
-void SkRecordPartialDraw(const SkRecord&, SkCanvas*, const SkRect&, unsigned start, unsigned stop,
+void SkRecordPartialDraw(const SkRecord&, SkCanvas*,
+ SkPicture const* const drawablePicts[], int drawableCount,
+ const SkRect&, unsigned start, unsigned stop,
const SkMatrix& initialCTM);
namespace SkRecords {
@@ -38,9 +41,13 @@ namespace SkRecords {
// This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
class Draw : SkNoncopyable {
public:
- explicit Draw(SkCanvas* canvas, const SkMatrix* initialCTM = NULL)
+ explicit Draw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
+ const SkMatrix* initialCTM = NULL)
: fInitialCTM(initialCTM ? *initialCTM : canvas->getTotalMatrix())
- , fCanvas(canvas) {}
+ , fCanvas(canvas)
+ , fDrawablePicts(drawablePicts)
+ , fDrawableCount(drawableCount)
+ {}
// This operator calls methods on the |canvas|. The various draw() wrapper
// methods around SkCanvas are defined by the DRAW() macro in
@@ -49,19 +56,26 @@ public:
this->draw(r);
}
+protected:
+ SkPicture const* const* drawablePicts() const { return fDrawablePicts; }
+ int drawableCount() const { return fDrawableCount; }
+
private:
// No base case, so we'll be compile-time checked that we implement all possibilities.
template <typename T> void draw(const T&);
const SkMatrix fInitialCTM;
SkCanvas* fCanvas;
+ SkPicture const* const* fDrawablePicts;
+ int fDrawableCount;
};
// Used by SkRecordPartialDraw.
class PartialDraw : public Draw {
public:
- PartialDraw(SkCanvas* canvas, const SkRect& clearRect, const SkMatrix& initialCTM)
- : INHERITED(canvas, &initialCTM), fClearRect(clearRect) {}
+ PartialDraw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
+ const SkRect& clearRect, const SkMatrix& initialCTM)
+ : INHERITED(canvas, drawablePicts, drawableCount, &initialCTM), fClearRect(clearRect) {}
// Same as Draw for all ops except Clear.
template <typename T> void operator()(const T& r) {
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 8dfce7e7dd..1af328afd2 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -5,6 +5,7 @@
* found in the LICENSE file.
*/
+#include "SkData.h"
#include "SkRecorder.h"
#include "SkPatchUtils.h"
#include "SkPicture.h"
@@ -15,10 +16,54 @@ SkRecorder::SkRecorder(SkRecord* record, int width, int height)
, fRecord(record)
, fSaveLayerCount(0) {}
+SkRecorder::~SkRecorder() {
+ fDrawableList.unrefAll();
+}
+
void SkRecorder::forgetRecord() {
+ fDrawableList.unrefAll();
+ fDrawableList.reset();
fRecord = NULL;
}
+// ReleaseProc for SkData, assuming the data was allocated via sk_malloc, and its contents are an
+// array of SkRefCnt* which need to be unref'd.
+//
+static void unref_all_malloc_releaseProc(const void* ptr, size_t length, void* context) {
+ SkASSERT(ptr == context); // our context is our ptr, allocated via sk_malloc
+ int count = SkToInt(length / sizeof(SkRefCnt*));
+ SkASSERT(count * sizeof(SkRefCnt*) == length); // our length is snug for the array
+
+ SkRefCnt* const* array = reinterpret_cast<SkRefCnt* const*>(ptr);
+ for (int i = 0; i < count; ++i) {
+ SkSafeUnref(array[i]);
+ }
+ sk_free(context);
+}
+
+// Return an uninitialized SkData sized for "count" SkRefCnt pointers. They will be unref'd when
+// the SkData is destroyed.
+//
+static SkData* new_uninitialized_refcnt_ptrs(int count) {
+ size_t length = count * sizeof(SkRefCnt*);
+ void* array = sk_malloc_throw(length);
+ void* context = array;
+ return SkData::NewWithProc(array, length, unref_all_malloc_releaseProc, context);
+}
+
+SkData* SkRecorder::newDrawableSnapshot(SkBBHFactory* factory, uint32_t recordFlags) {
+ const int count = fDrawableList.count();
+ if (0 == count) {
+ return NULL;
+ }
+ SkData* data = new_uninitialized_refcnt_ptrs(count);
+ SkPicture** pics = reinterpret_cast<SkPicture**>(data->writable_data());
+ for (int i = 0; i < count; ++i) {
+ pics[i] = fDrawableList[i]->newPictureSnapshot(factory, recordFlags);
+ }
+ return data;
+}
+
// To make appending to fRecord a little less verbose.
#define APPEND(T, ...) \
SkNEW_PLACEMENT_ARGS(fRecord->append<SkRecords::T>(), SkRecords::T, (__VA_ARGS__))
@@ -122,6 +167,11 @@ void SkRecorder::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const
APPEND(DrawDRRect, delay_copy(paint), outer, inner);
}
+void SkRecorder::onDrawDrawable(SkCanvasDrawable* drawable) {
+ *fDrawableList.append() = SkRef(drawable);
+ APPEND(DrawDrawable, drawable->getBounds(), fDrawableList.count() - 1);
+}
+
void SkRecorder::drawPath(const SkPath& path, const SkPaint& paint) {
APPEND(DrawPath, delay_copy(paint), delay_copy(path));
}
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 6ac8a56475..563f16d124 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -19,6 +19,11 @@ class SkRecorder : public SkCanvas {
public:
// Does not take ownership of the SkRecord.
SkRecorder(SkRecord*, int width, int height);
+ virtual ~SkRecorder() SK_OVERRIDE;
+
+ // return a (new or ref'd) data containing the array of pictures that were
+ // snapped from our drawables.
+ SkData* newDrawableSnapshot(SkBBHFactory*, uint32_t recordFlags);
// Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
void forgetRecord();
@@ -77,6 +82,7 @@ public:
void didSetMatrix(const SkMatrix&) SK_OVERRIDE;
void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) SK_OVERRIDE;
+ void onDrawDrawable(SkCanvasDrawable*) SK_OVERRIDE;
void onDrawText(const void* text,
size_t byteLength,
SkScalar x,
@@ -139,6 +145,7 @@ private:
int fSaveLayerCount;
SkTDArray<SkBool8> fSaveIsSaveLayer;
+ SkTDArray<SkCanvasDrawable*> fDrawableList;
};
#endif//SkRecorder_DEFINED
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index f6292d419b..d303e98915 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -9,6 +9,7 @@
#define SkRecords_DEFINED
#include "SkCanvas.h"
+#include "SkCanvasDrawable.h"
#include "SkPicture.h"
#include "SkTextBlob.h"
@@ -44,6 +45,7 @@ namespace SkRecords {
M(DrawBitmapMatrix) \
M(DrawBitmapNine) \
M(DrawBitmapRectToRect) \
+ M(DrawDrawable) \
M(DrawImage) \
M(DrawImageRect) \
M(DrawDRRect) \
@@ -236,6 +238,7 @@ RECORD5(DrawBitmapRectToRect, Optional<SkPaint>, paint,
SkRect, dst,
SkCanvas::DrawBitmapRectFlags, flags);
RECORD3(DrawDRRect, SkPaint, paint, SkRRect, outer, SkRRect, inner);
+RECORD2(DrawDrawable, SkRect, worstCaseBounds, int32_t, index);
RECORD4(DrawImage, Optional<SkPaint>, paint,
RefBox<const SkImage>, image,
SkScalar, left,
diff --git a/src/gpu/GrLayerHoister.cpp b/src/gpu/GrLayerHoister.cpp
index bc635aea07..b53c1b80cd 100644
--- a/src/gpu/GrLayerHoister.cpp
+++ b/src/gpu/GrLayerHoister.cpp
@@ -266,8 +266,9 @@ void GrLayerHoister::DrawLayersToAtlas(GrContext* context,
atlasCanvas->setMatrix(initialCTM);
atlasCanvas->concat(atlased[i].fLocalMat);
- SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas, bound,
- layer->start() + 1, layer->stop(), initialCTM);
+ SkRecordPartialDraw(*pict->fRecord.get(), atlasCanvas,
+ pict->drawablePicts(), pict->drawableCount(),
+ bound, layer->start() + 1, layer->stop(), initialCTM);
atlasCanvas->restore();
}
@@ -308,8 +309,9 @@ void GrLayerHoister::DrawLayers(GrContext* context, const SkTDArray<GrHoistedLay
layerCanvas->setMatrix(initialCTM);
layerCanvas->concat(layers[i].fLocalMat);
- SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas, bound,
- layer->start()+1, layer->stop(), initialCTM);
+ SkRecordPartialDraw(*pict->fRecord.get(), layerCanvas,
+ pict->drawablePicts(), pict->drawableCount(),
+ bound, layer->start()+1, layer->stop(), initialCTM);
layerCanvas->flush();
}
diff --git a/src/gpu/GrRecordReplaceDraw.cpp b/src/gpu/GrRecordReplaceDraw.cpp
index e4cc00696d..812584f08c 100644
--- a/src/gpu/GrRecordReplaceDraw.cpp
+++ b/src/gpu/GrRecordReplaceDraw.cpp
@@ -56,11 +56,12 @@ static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo
class ReplaceDraw : public SkRecords::Draw {
public:
ReplaceDraw(SkCanvas* canvas,
+ SkPicture const* const drawablePicts[], int drawableCount,
const SkPicture* picture,
const GrReplacements* replacements,
const SkMatrix& initialMatrix,
SkDrawPictureCallback* callback)
- : INHERITED(canvas)
+ : INHERITED(canvas, drawablePicts, drawableCount)
, fCanvas(canvas)
, fPicture(picture)
, fReplacements(replacements)
@@ -121,7 +122,8 @@ public:
SkAutoCanvasMatrixPaint acmp(fCanvas, dp.matrix, dp.paint, dp.picture->cullRect());
// Draw sub-pictures with the same replacement list but a different picture
- ReplaceDraw draw(fCanvas, dp.picture, fReplacements, fInitialMatrix, fCallback);
+ ReplaceDraw draw(fCanvas, this->drawablePicts(), this->drawableCount(),
+ dp.picture, fReplacements, fInitialMatrix, fCallback);
fNumReplaced += draw.draw();
}
@@ -182,7 +184,8 @@ int GrRecordReplaceDraw(const SkPicture* picture,
SkDrawPictureCallback* callback) {
SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
- ReplaceDraw draw(canvas, picture, replacements, initialMatrix, callback);
+ // TODO: drawablePicts?
+ ReplaceDraw draw(canvas, NULL, 0, picture, replacements, initialMatrix, callback);
return draw.draw();
}
diff --git a/tests/RecordDrawTest.cpp b/tests/RecordDrawTest.cpp
index 2346655330..e5dd9fe654 100644
--- a/tests/RecordDrawTest.cpp
+++ b/tests/RecordDrawTest.cpp
@@ -41,7 +41,7 @@ DEF_TEST(RecordDraw_Abort, r) {
SkRecorder canvas(&rerecord, W, H);
JustOneDraw callback;
- SkRecordDraw(record, &canvas, NULL/*bbh*/, &callback);
+ SkRecordDraw(record, &canvas, NULL, 0, NULL/*bbh*/, &callback);
REPORTER_ASSERT(r, 3 == rerecord.count());
assert_type<SkRecords::Save> (r, rerecord, 0);
@@ -56,7 +56,7 @@ DEF_TEST(RecordDraw_Unbalanced, r) {
SkRecord rerecord;
SkRecorder canvas(&rerecord, W, H);
- SkRecordDraw(record, &canvas, NULL/*bbh*/, NULL/*callback*/);
+ SkRecordDraw(record, &canvas, NULL, 0, NULL/*bbh*/, NULL/*callback*/);
REPORTER_ASSERT(r, 4 == rerecord.count());
assert_type<SkRecords::Save> (r, rerecord, 0);
@@ -80,7 +80,7 @@ DEF_TEST(RecordDraw_SetMatrixClobber, r) {
translate.setTranslate(20, 20);
translateCanvas.setMatrix(translate);
- SkRecordDraw(scaleRecord, &translateCanvas, NULL/*bbh*/, NULL/*callback*/);
+ SkRecordDraw(scaleRecord, &translateCanvas, NULL, 0, NULL/*bbh*/, NULL/*callback*/);
REPORTER_ASSERT(r, 4 == translateRecord.count());
assert_type<SkRecords::SetMatrix>(r, translateRecord, 0);
assert_type<SkRecords::Save> (r, translateRecord, 1);
@@ -190,7 +190,7 @@ DEF_TEST(RecordDraw_PartialStartStop, r) {
SkRecord rerecord;
SkRecorder canvas(&rerecord, kWidth, kHeight);
- SkRecordPartialDraw(record, &canvas, r1, 1, 2, SkMatrix::I()); // replay just drawRect of r2
+ SkRecordPartialDraw(record, &canvas, NULL, 0, r1, 1, 2, SkMatrix::I()); // replay just drawRect of r2
REPORTER_ASSERT(r, 3 == rerecord.count());
assert_type<SkRecords::Save> (r, rerecord, 0);
@@ -213,7 +213,7 @@ DEF_TEST(RecordDraw_PartialClear, r) {
SkRecord rerecord;
SkRecorder canvas(&rerecord, kWidth, kHeight);
- SkRecordPartialDraw(record, &canvas, rect, 0, 1, SkMatrix::I()); // replay just the clear
+ SkRecordPartialDraw(record, &canvas, NULL, 0, rect, 0, 1, SkMatrix::I()); // replay just the clear
REPORTER_ASSERT(r, 3 == rerecord.count());
assert_type<SkRecords::Save> (r, rerecord, 0);
@@ -319,7 +319,7 @@ DEF_TEST(RecordDraw_drawImage, r){
SkRecord record;
SkRecorder recorder(&record, 10, 10);
recorder.drawImage(image, 0, 0);
- SkRecordDraw(record, &canvas, 0, 0);
+ SkRecordDraw(record, &canvas, NULL, 0, NULL, 0);
}
REPORTER_ASSERT(r, canvas.fDrawImageCalled);
canvas.resetTestValues();
@@ -328,7 +328,7 @@ DEF_TEST(RecordDraw_drawImage, r){
SkRecord record;
SkRecorder recorder(&record, 10, 10);
recorder.drawImageRect(image, 0, SkRect::MakeWH(10, 10));
- SkRecordDraw(record, &canvas, 0, 0);
+ SkRecordDraw(record, &canvas, NULL, 0, NULL, 0);
}
REPORTER_ASSERT(r, canvas.fDrawImageRectCalled);
diff --git a/tools/DumpRecord.cpp b/tools/DumpRecord.cpp
index c505123acd..2d055169c1 100644
--- a/tools/DumpRecord.cpp
+++ b/tools/DumpRecord.cpp
@@ -21,7 +21,7 @@ public:
: fDigits(0)
, fIndent(0)
, fIndex(0)
- , fDraw(canvas)
+ , fDraw(canvas, NULL, 0, NULL)
, fTimeWithCommand(timeWithCommand) {
while (count > 0) {
count /= 10;