option to return drawable from recording
patch from issue 747033005 at patchset 80001 (http://crrev.com/747033005#ps80001) BUG=skia: Review URL: https://codereview.chromium.org/732653004
This commit is contained in:
parent
89ff0846fd
commit
1bdfd3f4f0
@ -268,9 +268,9 @@ private:
|
||||
const uint32_t fUniqueID;
|
||||
const SkRect fCullRect;
|
||||
mutable SkAutoTUnref<const AccelData> fAccelData;
|
||||
SkAutoTDelete<const SkRecord> fRecord;
|
||||
SkAutoTUnref<const SkBBoxHierarchy> fBBH;
|
||||
SkAutoTDelete<const SnapshotArray> fDrawablePicts;
|
||||
SkAutoTUnref<const SkRecord> fRecord;
|
||||
SkAutoTUnref<const SkBBoxHierarchy> fBBH;
|
||||
SkAutoTDelete<const SnapshotArray> fDrawablePicts;
|
||||
|
||||
// helpers for fDrawablePicts
|
||||
int drawableCount() const;
|
||||
@ -298,6 +298,7 @@ private:
|
||||
friend class GrLayerHoister; // access to fRecord
|
||||
friend class ReplaceDraw;
|
||||
friend class SkPictureUtils;
|
||||
friend class SkRecordedDrawable;
|
||||
};
|
||||
SK_COMPILE_ASSERT(sizeof(SkPicture) <= 96, SkPictureSize);
|
||||
|
||||
|
@ -19,6 +19,7 @@ namespace android {
|
||||
#endif
|
||||
|
||||
class SkCanvas;
|
||||
class SkCanvasDrawable;
|
||||
class SkPictureRecord;
|
||||
class SkRecord;
|
||||
class SkRecorder;
|
||||
@ -65,12 +66,32 @@ public:
|
||||
*/
|
||||
SkCanvas* getRecordingCanvas();
|
||||
|
||||
/** Signal that the caller is done recording. This invalidates the canvas
|
||||
returned by beginRecording/getRecordingCanvas, and returns the
|
||||
created SkPicture. Note that the returned picture has its creation
|
||||
ref which the caller must take ownership of.
|
||||
*/
|
||||
SkPicture* endRecording();
|
||||
/**
|
||||
* Signal that the caller is done recording. This invalidates the canvas returned by
|
||||
* beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
|
||||
* must call unref() when they are done using it.
|
||||
*
|
||||
* The returned picture is immutable. If during recording drawables were added to the canvas,
|
||||
* these will have been "drawn" into a recording canvas, so that this resulting picture will
|
||||
* reflect their current state, but will not contain a live reference to the drawables
|
||||
* themselves.
|
||||
*/
|
||||
SkPicture* endRecordingAsPicture();
|
||||
|
||||
/**
|
||||
* Signal that the caller is done recording. This invalidates the canvas returned by
|
||||
* beginRecording/getRecordingCanvas. Ownership of the object is passed to the caller, who
|
||||
* must call unref() when they are done using it.
|
||||
*
|
||||
* Unlike endRecordingAsPicture(), which returns an immutable picture, the returned drawable
|
||||
* may contain live references to other drawables (if they were added to the recording canvas)
|
||||
* and therefore this drawable will reflect the current state of those nested drawables anytime
|
||||
* it is drawn or a new picture is snapped from it (by calling drawable->newPictureSnapshot()).
|
||||
*/
|
||||
SkCanvasDrawable* EXPERIMENTAL_endRecordingAsDrawable();
|
||||
|
||||
// Legacy API -- use endRecordingAsPicture instead.
|
||||
SkPicture* endRecording() { return this->endRecordingAsPicture(); }
|
||||
|
||||
private:
|
||||
void reset();
|
||||
@ -88,7 +109,8 @@ private:
|
||||
SkRect fCullRect;
|
||||
SkAutoTUnref<SkBBoxHierarchy> fBBH;
|
||||
SkAutoTUnref<SkRecorder> fRecorder;
|
||||
SkAutoTDelete<SkRecord> fRecord;
|
||||
SkAutoTUnref<SkRecord> fRecord;
|
||||
SkBBHFactory* fBBHFactory;
|
||||
|
||||
typedef SkNoncopyable INHERITED;
|
||||
};
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "Sk1DPathEffect.h"
|
||||
#include "SkCornerPathEffect.h"
|
||||
#include "SkPathMeasure.h"
|
||||
#include "SkPictureRecorder.h"
|
||||
#include "SkRandom.h"
|
||||
#include "SkColorPriv.h"
|
||||
#include "SkColorFilter.h"
|
||||
@ -42,8 +43,7 @@ class ArcsView : public SampleView {
|
||||
SkRect fR;
|
||||
SkScalar fSweep;
|
||||
public:
|
||||
MyDrawable(const SkRect& r) : fR(r), fSweep(0) {
|
||||
}
|
||||
MyDrawable(const SkRect& r) : fR(r), fSweep(0) {}
|
||||
|
||||
void setSweep(SkScalar sweep) {
|
||||
if (fSweep != sweep) {
|
||||
@ -82,7 +82,8 @@ class ArcsView : public SampleView {
|
||||
|
||||
public:
|
||||
SkRect fRect;
|
||||
MyDrawable* fDrawable;
|
||||
MyDrawable* fAnimatingDrawable;
|
||||
SkCanvasDrawable* fRootDrawable;
|
||||
|
||||
ArcsView() {
|
||||
testparse();
|
||||
@ -91,16 +92,21 @@ public:
|
||||
|
||||
fRect.set(0, 0, SkIntToScalar(200), SkIntToScalar(200));
|
||||
fRect.offset(SkIntToScalar(20), SkIntToScalar(20));
|
||||
fDrawable = SkNEW_ARGS(MyDrawable, (fRect));
|
||||
fAnimatingDrawable = SkNEW_ARGS(MyDrawable, (fRect));
|
||||
|
||||
SkPictureRecorder recorder;
|
||||
this->drawRoot(recorder.beginRecording(SkRect::MakeWH(800, 500)));
|
||||
fRootDrawable = recorder.EXPERIMENTAL_endRecordingAsDrawable();
|
||||
}
|
||||
|
||||
virtual ~ArcsView() SK_OVERRIDE {
|
||||
fDrawable->unref();
|
||||
fAnimatingDrawable->unref();
|
||||
fRootDrawable->unref();
|
||||
}
|
||||
|
||||
protected:
|
||||
// overrides from SkEventSink
|
||||
virtual bool onQuery(SkEvent* evt) {
|
||||
bool onQuery(SkEvent* evt) SK_OVERRIDE {
|
||||
if (SampleCode::TitleQ(*evt)) {
|
||||
SampleCode::TitleR(evt, "Arcs");
|
||||
return true;
|
||||
@ -108,7 +114,7 @@ protected:
|
||||
return this->INHERITED::onQuery(evt);
|
||||
}
|
||||
|
||||
static void drawRectWithLines(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
||||
static void DrawRectWithLines(SkCanvas* canvas, const SkRect& r, const SkPaint& p) {
|
||||
canvas->drawRect(r, p);
|
||||
canvas->drawLine(r.fLeft, r.fTop, r.fRight, r.fBottom, p);
|
||||
canvas->drawLine(r.fLeft, r.fBottom, r.fRight, r.fTop, p);
|
||||
@ -116,7 +122,7 @@ protected:
|
||||
canvas->drawLine(r.centerX(), r.fTop, r.centerX(), r.fBottom, p);
|
||||
}
|
||||
|
||||
static void draw_label(SkCanvas* canvas, const SkRect& rect,
|
||||
static void DrawLabel(SkCanvas* canvas, const SkRect& rect,
|
||||
int start, int sweep) {
|
||||
SkPaint paint;
|
||||
|
||||
@ -132,7 +138,7 @@ protected:
|
||||
rect.fBottom + paint.getTextSize() * 5/4, paint);
|
||||
}
|
||||
|
||||
static void drawArcs(SkCanvas* canvas) {
|
||||
static void DrawArcs(SkCanvas* canvas) {
|
||||
SkPaint paint;
|
||||
SkRect r;
|
||||
SkScalar w = SkIntToScalar(75);
|
||||
@ -161,13 +167,13 @@ protected:
|
||||
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gAngles); i += 2) {
|
||||
paint.setColor(SK_ColorBLACK);
|
||||
drawRectWithLines(canvas, r, paint);
|
||||
DrawRectWithLines(canvas, r, paint);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
canvas->drawArc(r, SkIntToScalar(gAngles[i]),
|
||||
SkIntToScalar(gAngles[i+1]), false, paint);
|
||||
|
||||
draw_label(canvas, r, gAngles[i], gAngles[i+1]);
|
||||
DrawLabel(canvas, r, gAngles[i], gAngles[i+1]);
|
||||
|
||||
canvas->translate(w * 8 / 7, 0);
|
||||
}
|
||||
@ -175,34 +181,31 @@ protected:
|
||||
canvas->restore();
|
||||
}
|
||||
|
||||
virtual void onDrawContent(SkCanvas* canvas) {
|
||||
fDrawable->setSweep(SampleCode::GetAnimScalar(SkIntToScalar(360)/24,
|
||||
SkIntToScalar(360)));
|
||||
|
||||
void drawRoot(SkCanvas* canvas) {
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setStrokeWidth(SkIntToScalar(2));
|
||||
paint.setStyle(SkPaint::kStroke_Style);
|
||||
|
||||
drawRectWithLines(canvas, fRect, paint);
|
||||
DrawRectWithLines(canvas, fRect, paint);
|
||||
|
||||
canvas->EXPERIMENTAL_drawDrawable(fDrawable);
|
||||
canvas->EXPERIMENTAL_drawDrawable(fAnimatingDrawable);
|
||||
|
||||
drawArcs(canvas);
|
||||
DrawArcs(canvas);
|
||||
}
|
||||
|
||||
void onDrawContent(SkCanvas* canvas) SK_OVERRIDE {
|
||||
fAnimatingDrawable->setSweep(SampleCode::GetAnimScalar(360/24, 360));
|
||||
canvas->EXPERIMENTAL_drawDrawable(fRootDrawable);
|
||||
this->inval(NULL);
|
||||
}
|
||||
|
||||
virtual SkView::Click* onFindClickHandler(SkScalar x, SkScalar y,
|
||||
unsigned modi) {
|
||||
SkView::Click* onFindClickHandler(SkScalar x, SkScalar y, unsigned modi) SK_OVERRIDE {
|
||||
// fSweep += SK_Scalar1;
|
||||
this->inval(NULL);
|
||||
return this->INHERITED::onFindClickHandler(x, y, modi);
|
||||
}
|
||||
|
||||
virtual bool onClick(Click* click) {
|
||||
return this->INHERITED::onClick(click);
|
||||
}
|
||||
|
||||
private:
|
||||
SkScalar fSweep;
|
||||
|
||||
|
@ -41,8 +41,8 @@ void SkCanvasDrawable::draw(SkCanvas* canvas) {
|
||||
}
|
||||
}
|
||||
|
||||
SkPicture* SkCanvasDrawable::newPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags) {
|
||||
return this->onNewPictureSnapshot(bbhFactory, recordFlags);
|
||||
SkPicture* SkCanvasDrawable::newPictureSnapshot() {
|
||||
return this->onNewPictureSnapshot();
|
||||
}
|
||||
|
||||
uint32_t SkCanvasDrawable::getGenerationID() {
|
||||
@ -64,11 +64,11 @@ void SkCanvasDrawable::notifyDrawingChanged() {
|
||||
|
||||
#include "SkPictureRecorder.h"
|
||||
|
||||
SkPicture* SkCanvasDrawable::onNewPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags) {
|
||||
SkPicture* SkCanvasDrawable::onNewPictureSnapshot() {
|
||||
SkPictureRecorder recorder;
|
||||
|
||||
const SkRect bounds = this->getBounds();
|
||||
SkCanvas* canvas = recorder.beginRecording(bounds, bbhFactory, recordFlags);
|
||||
SkCanvas* canvas = recorder.beginRecording(bounds, NULL, 0);
|
||||
this->draw(canvas);
|
||||
if (false) {
|
||||
draw_bbox(canvas, bounds);
|
||||
|
@ -10,8 +10,8 @@
|
||||
|
||||
#include "SkRefCnt.h"
|
||||
|
||||
class SkBBHFactory;
|
||||
class SkCanvas;
|
||||
class SkPicture;
|
||||
struct SkRect;
|
||||
|
||||
/**
|
||||
@ -32,10 +32,7 @@ public:
|
||||
*/
|
||||
void draw(SkCanvas*);
|
||||
|
||||
SkPicture* newPictureSnapshot(SkBBHFactory* bbhFactory, uint32_t recordFlags);
|
||||
SkPicture* newPictureSnapshot() {
|
||||
return this->newPictureSnapshot(NULL, 0);
|
||||
}
|
||||
SkPicture* newPictureSnapshot();
|
||||
|
||||
/**
|
||||
* Return a unique value for this instance. If two calls to this return the same value,
|
||||
@ -63,7 +60,7 @@ public:
|
||||
protected:
|
||||
virtual SkRect onGetBounds() = 0;
|
||||
virtual void onDraw(SkCanvas*) = 0;
|
||||
virtual SkPicture* onNewPictureSnapshot(SkBBHFactory*, uint32_t recordFlags);
|
||||
virtual SkPicture* onNewPictureSnapshot();
|
||||
|
||||
private:
|
||||
int32_t fGenerationID;
|
||||
|
@ -319,7 +319,7 @@ void SkPicture::playback(SkCanvas* canvas, SkDrawPictureCallback* callback) cons
|
||||
(void)canvas->getClipBounds(&clipBounds);
|
||||
const bool useBBH = !clipBounds.contains(this->cullRect());
|
||||
|
||||
SkRecordDraw(*fRecord, canvas, this->drawablePicts(), this->drawableCount(),
|
||||
SkRecordDraw(*fRecord, canvas, this->drawablePicts(), NULL, this->drawableCount(),
|
||||
useBBH ? fBBH.get() : NULL, callback);
|
||||
}
|
||||
|
||||
@ -474,7 +474,7 @@ 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, drawablePicts, drawableCount, NULL/*bbh*/, NULL/*callback*/);
|
||||
SkRecordDraw(src, &rec, drawablePicts, NULL, drawableCount, NULL/*bbh*/, NULL/*callback*/);
|
||||
rec.endRecording();
|
||||
return SkNEW_ARGS(SkPictureData, (rec, info, false/*deep copy ops?*/));
|
||||
}
|
||||
@ -526,8 +526,8 @@ SkPicture::SkPicture(const SkRect& cullRect, SkRecord* record, SnapshotArray* dr
|
||||
SkBBoxHierarchy* bbh)
|
||||
: fUniqueID(next_picture_generation_id())
|
||||
, fCullRect(cullRect)
|
||||
, fRecord(record)
|
||||
, fRecord(SkRef(record))
|
||||
, fBBH(SkSafeRef(bbh))
|
||||
, fDrawablePicts(drawablePicts)
|
||||
, fDrawablePicts(drawablePicts) // take ownership
|
||||
, fAnalysis(*fRecord)
|
||||
{}
|
||||
|
@ -5,6 +5,7 @@
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkCanvasDrawable.h"
|
||||
#include "SkData.h"
|
||||
#include "SkLayerInfo.h"
|
||||
#include "SkPictureRecorder.h"
|
||||
@ -14,7 +15,7 @@
|
||||
#include "SkRecordOpts.h"
|
||||
#include "SkTypes.h"
|
||||
|
||||
SkPictureRecorder::SkPictureRecorder() {}
|
||||
SkPictureRecorder::SkPictureRecorder() : fBBHFactory(NULL) {}
|
||||
|
||||
SkPictureRecorder::~SkPictureRecorder() {}
|
||||
|
||||
@ -22,6 +23,7 @@ SkCanvas* SkPictureRecorder::beginRecording(const SkRect& cullRect,
|
||||
SkBBHFactory* bbhFactory /* = NULL */,
|
||||
uint32_t recordFlags /* = 0 */) {
|
||||
fCullRect = cullRect;
|
||||
fBBHFactory = bbhFactory;
|
||||
fFlags = recordFlags;
|
||||
|
||||
if (bbhFactory) {
|
||||
@ -38,7 +40,7 @@ SkCanvas* SkPictureRecorder::getRecordingCanvas() {
|
||||
return fRecorder.get();
|
||||
}
|
||||
|
||||
SkPicture* SkPictureRecorder::endRecording() {
|
||||
SkPicture* SkPictureRecorder::endRecordingAsPicture() {
|
||||
// TODO: delay as much of this work until just before first playback?
|
||||
SkRecordOptimize(fRecord);
|
||||
|
||||
@ -50,26 +52,23 @@ SkPicture* SkPictureRecorder::endRecording() {
|
||||
saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
|
||||
}
|
||||
|
||||
SkCanvasDrawableList* drawableList = fRecorder->getDrawableList();
|
||||
SkPicture::SnapshotArray* pictList = drawableList ? drawableList->newDrawableSnapshot() : NULL;
|
||||
|
||||
if (fBBH.get()) {
|
||||
if (saveLayerData) {
|
||||
SkRecordComputeLayers(fCullRect, *fRecord, fBBH.get(), saveLayerData);
|
||||
SkRecordComputeLayers(fCullRect, *fRecord, pictList, fBBH.get(), saveLayerData);
|
||||
} else {
|
||||
SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: we should remember these from our caller
|
||||
SkBBHFactory* factory = NULL;
|
||||
uint32_t recordFlags = 0;
|
||||
SkAutoTDelete<SkPicture::SnapshotArray> drawablePicts(
|
||||
fRecorder->newDrawableSnapshot(factory, recordFlags));
|
||||
SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord.detach(),
|
||||
drawablePicts.detach(), fBBH.get()));
|
||||
SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH));
|
||||
|
||||
if (saveLayerData) {
|
||||
pict->EXPERIMENTAL_addAccelData(saveLayerData);
|
||||
}
|
||||
|
||||
|
||||
return pict;
|
||||
}
|
||||
|
||||
@ -79,5 +78,86 @@ void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
|
||||
}
|
||||
|
||||
int drawableCount = 0;
|
||||
SkRecordDraw(*fRecord, canvas, NULL, drawableCount, NULL/*bbh*/, NULL/*callback*/);
|
||||
SkCanvasDrawable* const* drawables = NULL;
|
||||
SkCanvasDrawableList* drawableList = fRecorder->getDrawableList();
|
||||
if (drawableList) {
|
||||
drawableCount = drawableList->count();
|
||||
drawables = drawableList->begin();
|
||||
}
|
||||
SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, NULL/*bbh*/, NULL/*callback*/);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SkRecordedDrawable : public SkCanvasDrawable {
|
||||
SkAutoTUnref<SkRecord> fRecord;
|
||||
SkAutoTUnref<SkBBoxHierarchy> fBBH;
|
||||
SkAutoTDelete<SkCanvasDrawableList> fDrawableList;
|
||||
const SkRect fBounds;
|
||||
const bool fDoSaveLayerInfo;
|
||||
|
||||
public:
|
||||
SkRecordedDrawable(SkRecord* record, SkBBoxHierarchy* bbh, SkCanvasDrawableList* drawableList,
|
||||
const SkRect& bounds, bool doSaveLayerInfo)
|
||||
: fRecord(SkRef(record))
|
||||
, fBBH(SkSafeRef(bbh))
|
||||
, fDrawableList(drawableList) // we take ownership
|
||||
, fBounds(bounds)
|
||||
, fDoSaveLayerInfo(doSaveLayerInfo)
|
||||
{}
|
||||
|
||||
protected:
|
||||
SkRect onGetBounds() SK_OVERRIDE { return fBounds; }
|
||||
|
||||
void onDraw(SkCanvas* canvas) SK_OVERRIDE {
|
||||
SkCanvasDrawable* const* drawables = NULL;
|
||||
int drawableCount = 0;
|
||||
if (fDrawableList) {
|
||||
drawables = fDrawableList->begin();
|
||||
drawableCount = fDrawableList->count();
|
||||
}
|
||||
SkRecordDraw(*fRecord, canvas, NULL, drawables, drawableCount, fBBH, NULL/*callback*/);
|
||||
}
|
||||
|
||||
SkPicture* onNewPictureSnapshot() SK_OVERRIDE {
|
||||
SkPicture::SnapshotArray* pictList = NULL;
|
||||
if (fDrawableList) {
|
||||
// TODO: should we plumb-down the BBHFactory and recordFlags from our host
|
||||
// PictureRecorder?
|
||||
pictList = fDrawableList->newDrawableSnapshot();
|
||||
}
|
||||
|
||||
SkAutoTUnref<SkLayerInfo> saveLayerData;
|
||||
|
||||
if (fBBH && fDoSaveLayerInfo) {
|
||||
SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
|
||||
|
||||
saveLayerData.reset(SkNEW_ARGS(SkLayerInfo, (key)));
|
||||
|
||||
SkBBoxHierarchy* bbh = NULL; // we've already computed fBBH (received in constructor)
|
||||
// TODO: update saveLayer info computation to reuse the already computed
|
||||
// bounds in 'fBBH'
|
||||
SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData);
|
||||
}
|
||||
|
||||
SkPicture* pict = SkNEW_ARGS(SkPicture, (fBounds, fRecord, pictList, fBBH));
|
||||
|
||||
if (saveLayerData) {
|
||||
pict->EXPERIMENTAL_addAccelData(saveLayerData);
|
||||
}
|
||||
return pict;
|
||||
}
|
||||
};
|
||||
|
||||
SkCanvasDrawable* SkPictureRecorder::EXPERIMENTAL_endRecordingAsDrawable() {
|
||||
// TODO: delay as much of this work until just before first playback?
|
||||
SkRecordOptimize(fRecord);
|
||||
|
||||
if (fBBH.get()) {
|
||||
SkRecordFillBounds(fCullRect, *fRecord, fBBH.get());
|
||||
}
|
||||
|
||||
return SkNEW_ARGS(SkRecordedDrawable, (fRecord, fBBH, fRecorder->detachDrawableList(),
|
||||
fCullRect,
|
||||
SkToBool(fFlags & kComputeSaveLayerInfo_RecordFlag)));
|
||||
}
|
||||
|
@ -25,7 +25,7 @@
|
||||
// only with SkRecords::* structs defined in SkRecords.h. Your compiler will helpfully yell if you
|
||||
// get this wrong.
|
||||
|
||||
class SkRecord : SkNoncopyable {
|
||||
class SkRecord : public SkNVRefCnt<SkRecord> {
|
||||
enum {
|
||||
kFirstReserveCount = 64 / sizeof(void*),
|
||||
};
|
||||
@ -240,6 +240,6 @@ private:
|
||||
// Strangely the order of these fields matters. If the unsigneds don't go first we're 56 bytes.
|
||||
// tomhudson and mtklein have no idea why.
|
||||
};
|
||||
SK_COMPILE_ASSERT(sizeof(SkRecord) <= 48, SkRecordSize);
|
||||
SK_COMPILE_ASSERT(sizeof(SkRecord) <= 56, SkRecordSize);
|
||||
|
||||
#endif//SkRecord_DEFINED
|
||||
|
@ -11,7 +11,9 @@
|
||||
|
||||
void SkRecordDraw(const SkRecord& record,
|
||||
SkCanvas* canvas,
|
||||
SkPicture const* const drawablePicts[], int drawableCount,
|
||||
SkPicture const* const drawablePicts[],
|
||||
SkCanvasDrawable* const drawables[],
|
||||
int drawableCount,
|
||||
const SkBBoxHierarchy* bbh,
|
||||
SkDrawPictureCallback* callback) {
|
||||
SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
|
||||
@ -32,7 +34,7 @@ void SkRecordDraw(const SkRecord& record,
|
||||
SkTDArray<unsigned> ops;
|
||||
bbh->search(query, &ops);
|
||||
|
||||
SkRecords::Draw draw(canvas, drawablePicts, drawableCount);
|
||||
SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
|
||||
for (int i = 0; i < ops.count(); i++) {
|
||||
if (callback && callback->abortDrawing()) {
|
||||
return;
|
||||
@ -44,7 +46,7 @@ void SkRecordDraw(const SkRecord& record,
|
||||
}
|
||||
} else {
|
||||
// Draw all ops.
|
||||
SkRecords::Draw draw(canvas, drawablePicts, drawableCount);
|
||||
SkRecords::Draw draw(canvas, drawablePicts, drawables, drawableCount);
|
||||
for (unsigned i = 0; i < record.count(); i++) {
|
||||
if (callback && callback->abortDrawing()) {
|
||||
return;
|
||||
@ -133,7 +135,12 @@ DRAW(DrawData, drawData(r.data, r.length));
|
||||
template <> void Draw::draw(const DrawDrawable& r) {
|
||||
SkASSERT(r.index >= 0);
|
||||
SkASSERT(r.index < fDrawableCount);
|
||||
fCanvas->drawPicture(fDrawablePicts[r.index]);
|
||||
if (fDrawables) {
|
||||
SkASSERT(NULL == fDrawablePicts);
|
||||
fCanvas->EXPERIMENTAL_drawDrawable(fDrawables[r.index]);
|
||||
} else {
|
||||
fCanvas->drawPicture(fDrawablePicts[r.index]);
|
||||
}
|
||||
}
|
||||
|
||||
// This is an SkRecord visitor that fills an SkBBoxHierarchy.
|
||||
@ -159,7 +166,8 @@ public:
|
||||
FillBounds(const SkRect& cullRect, const SkRecord& record)
|
||||
: fNumRecords(record.count())
|
||||
, fCullRect(cullRect)
|
||||
, fBounds(record.count()) {
|
||||
, fBounds(record.count())
|
||||
{
|
||||
// Calculate bounds for all ops. This won't go quite in order, so we'll need
|
||||
// to store the bounds separately then feed them in to the BBH later in order.
|
||||
fCTM = &SkMatrix::I();
|
||||
@ -591,11 +599,13 @@ private:
|
||||
// SkRecord visitor to gather saveLayer/restore information.
|
||||
class CollectLayers : SkNoncopyable {
|
||||
public:
|
||||
CollectLayers(const SkRect& cullRect, const SkRecord& record, SkLayerInfo* accelData)
|
||||
CollectLayers(const SkRect& cullRect, const SkRecord& record,
|
||||
const SkPicture::SnapshotArray* pictList, SkLayerInfo* accelData)
|
||||
: fSaveLayersInStack(0)
|
||||
, fAccelData(accelData)
|
||||
, fFillBounds(cullRect, record) {
|
||||
}
|
||||
, fPictList(pictList)
|
||||
, fFillBounds(cullRect, record)
|
||||
{}
|
||||
|
||||
void setCurrentOp(unsigned currentOp) { fFillBounds.setCurrentOp(currentOp); }
|
||||
|
||||
@ -638,13 +648,13 @@ private:
|
||||
void trackSaveLayers(const SaveLayer& sl) { this->pushSaveLayerInfo(true, sl.paint); }
|
||||
void trackSaveLayers(const Restore& r) { this->popSaveLayerInfo(); }
|
||||
|
||||
void trackSaveLayers(const DrawPicture& dp) {
|
||||
void trackSaveLayersForPicture(const SkPicture* picture, const SkPaint* paint) {
|
||||
// For sub-pictures, we wrap their layer information within the parent
|
||||
// picture's rendering hierarchy
|
||||
SkPicture::AccelData::Key key = SkLayerInfo::ComputeKey();
|
||||
|
||||
const SkLayerInfo* childData =
|
||||
static_cast<const SkLayerInfo*>(dp.picture->EXPERIMENTAL_getAccelData(key));
|
||||
static_cast<const SkLayerInfo*>(picture->EXPERIMENTAL_getAccelData(key));
|
||||
if (!childData) {
|
||||
// If the child layer hasn't been generated with saveLayer data we
|
||||
// assume the worst (i.e., that it does contain layers which nest
|
||||
@ -658,7 +668,7 @@ private:
|
||||
for (int i = 0; i < childData->numBlocks(); ++i) {
|
||||
const SkLayerInfo::BlockInfo& src = childData->block(i);
|
||||
|
||||
FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, dp.paint);
|
||||
FillBounds::Bounds newBound = fFillBounds.adjustAndMap(src.fBounds, paint);
|
||||
if (newBound.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
@ -669,7 +679,7 @@ private:
|
||||
|
||||
// If src.fPicture is NULL the layer is in dp.picture; otherwise
|
||||
// it belongs to a sub-picture.
|
||||
dst.fPicture = src.fPicture ? src.fPicture : static_cast<const SkPicture*>(dp.picture);
|
||||
dst.fPicture = src.fPicture ? src.fPicture : picture;
|
||||
dst.fPicture->ref();
|
||||
dst.fBounds = newBound;
|
||||
dst.fLocalMat = src.fLocalMat;
|
||||
@ -685,6 +695,17 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void trackSaveLayers(const DrawPicture& dp) {
|
||||
this->trackSaveLayersForPicture(dp.picture, dp.paint);
|
||||
}
|
||||
|
||||
void trackSaveLayers(const DrawDrawable& dp) {
|
||||
SkASSERT(fPictList);
|
||||
SkASSERT(dp.index >= 0 && dp.index < fPictList->count());
|
||||
const SkPaint* paint = NULL; // drawables don't get a side-car paint
|
||||
this->trackSaveLayersForPicture(fPictList->begin()[dp.index], paint);
|
||||
}
|
||||
|
||||
// Inform all the saveLayers already on the stack that they now have a
|
||||
// nested saveLayer inside them
|
||||
void updateStackForSaveLayer() {
|
||||
@ -743,6 +764,7 @@ private:
|
||||
int fSaveLayersInStack;
|
||||
SkTDArray<SaveLayerInfo> fSaveLayerStack;
|
||||
SkLayerInfo* fAccelData;
|
||||
const SkPicture::SnapshotArray* fPictList;
|
||||
|
||||
SkRecords::FillBounds fFillBounds;
|
||||
};
|
||||
@ -761,8 +783,9 @@ void SkRecordFillBounds(const SkRect& cullRect, const SkRecord& record, SkBBoxHi
|
||||
}
|
||||
|
||||
void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
|
||||
SkBBoxHierarchy* bbh, SkLayerInfo* data) {
|
||||
SkRecords::CollectLayers visitor(cullRect, record, data);
|
||||
const SkPicture::SnapshotArray* pictList, SkBBoxHierarchy* bbh,
|
||||
SkLayerInfo* data) {
|
||||
SkRecords::CollectLayers visitor(cullRect, record, pictList, data);
|
||||
|
||||
for (unsigned curOp = 0; curOp < record.count(); curOp++) {
|
||||
visitor.setCurrentOp(curOp);
|
||||
|
@ -14,16 +14,19 @@
|
||||
#include "SkMatrix.h"
|
||||
#include "SkRecord.h"
|
||||
|
||||
class SkCanvasDrawable;
|
||||
class SkLayerInfo;
|
||||
|
||||
// Fill a BBH to be used by SkRecordDraw to accelerate playback.
|
||||
void SkRecordFillBounds(const SkRect& cullRect, const SkRecord&, SkBBoxHierarchy*);
|
||||
|
||||
void SkRecordComputeLayers(const SkRect& cullRect, const SkRecord& record,
|
||||
const SkPicture::SnapshotArray*,
|
||||
SkBBoxHierarchy* bbh, SkLayerInfo* data);
|
||||
|
||||
// Draw an SkRecord into an SkCanvas. A convenience wrapper around SkRecords::Draw.
|
||||
void SkRecordDraw(const SkRecord&, SkCanvas*, SkPicture const* const drawablePicts[], int drawableCount,
|
||||
void SkRecordDraw(const SkRecord&, SkCanvas*, SkPicture const* const drawablePicts[],
|
||||
SkCanvasDrawable* const drawables[], int drawableCount,
|
||||
const SkBBoxHierarchy*, SkDrawPictureCallback*);
|
||||
|
||||
// Draw a portion of an SkRecord into an SkCanvas while replacing clears with drawRects.
|
||||
@ -41,11 +44,13 @@ namespace SkRecords {
|
||||
// This is an SkRecord visitor that will draw that SkRecord to an SkCanvas.
|
||||
class Draw : SkNoncopyable {
|
||||
public:
|
||||
explicit Draw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
|
||||
explicit Draw(SkCanvas* canvas, SkPicture const* const drawablePicts[],
|
||||
SkCanvasDrawable* const drawables[], int drawableCount,
|
||||
const SkMatrix* initialCTM = NULL)
|
||||
: fInitialCTM(initialCTM ? *initialCTM : canvas->getTotalMatrix())
|
||||
, fCanvas(canvas)
|
||||
, fDrawablePicts(drawablePicts)
|
||||
, fDrawables(drawables)
|
||||
, fDrawableCount(drawableCount)
|
||||
{}
|
||||
|
||||
@ -67,6 +72,7 @@ private:
|
||||
const SkMatrix fInitialCTM;
|
||||
SkCanvas* fCanvas;
|
||||
SkPicture const* const* fDrawablePicts;
|
||||
SkCanvasDrawable* const* fDrawables;
|
||||
int fDrawableCount;
|
||||
};
|
||||
|
||||
@ -75,7 +81,8 @@ class PartialDraw : public Draw {
|
||||
public:
|
||||
PartialDraw(SkCanvas* canvas, SkPicture const* const drawablePicts[], int drawableCount,
|
||||
const SkRect& clearRect, const SkMatrix& initialCTM)
|
||||
: INHERITED(canvas, drawablePicts, drawableCount, &initialCTM), fClearRect(clearRect) {}
|
||||
: INHERITED(canvas, drawablePicts, NULL, drawableCount, &initialCTM), fClearRect(clearRect)
|
||||
{}
|
||||
|
||||
// Same as Draw for all ops except Clear.
|
||||
template <typename T> void operator()(const T& r) {
|
||||
|
@ -9,6 +9,28 @@
|
||||
#include "SkPatchUtils.h"
|
||||
#include "SkPicture.h"
|
||||
|
||||
SkCanvasDrawableList::~SkCanvasDrawableList() {
|
||||
fArray.unrefAll();
|
||||
}
|
||||
|
||||
SkPicture::SnapshotArray* SkCanvasDrawableList::newDrawableSnapshot() {
|
||||
const int count = fArray.count();
|
||||
if (0 == count) {
|
||||
return NULL;
|
||||
}
|
||||
SkAutoTMalloc<const SkPicture*> pics(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
pics[i] = fArray[i]->newPictureSnapshot();
|
||||
}
|
||||
return SkNEW_ARGS(SkPicture::SnapshotArray, (pics.detach(), count));
|
||||
}
|
||||
|
||||
void SkCanvasDrawableList::append(SkCanvasDrawable* drawable) {
|
||||
*fArray.append() = SkRef(drawable);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SkRecorder::SkRecorder(SkRecord* record, int width, int height)
|
||||
: SkCanvas(SkIRect::MakeWH(width, height), SkCanvas::kConservativeRasterClip_InitFlag)
|
||||
, fRecord(record)
|
||||
@ -19,29 +41,11 @@ SkRecorder::SkRecorder(SkRecord* record, const SkRect& bounds)
|
||||
, fRecord(record)
|
||||
, fSaveLayerCount(0) {}
|
||||
|
||||
SkRecorder::~SkRecorder() {
|
||||
fDrawableList.unrefAll();
|
||||
}
|
||||
|
||||
void SkRecorder::forgetRecord() {
|
||||
fDrawableList.unrefAll();
|
||||
fDrawableList.reset();
|
||||
fDrawableList.reset(NULL);
|
||||
fRecord = NULL;
|
||||
}
|
||||
|
||||
SkPicture::SnapshotArray* SkRecorder::newDrawableSnapshot(SkBBHFactory* factory,
|
||||
uint32_t recordFlags) {
|
||||
const int count = fDrawableList.count();
|
||||
if (0 == count) {
|
||||
return NULL;
|
||||
}
|
||||
SkAutoTMalloc<const SkPicture*> pics(count);
|
||||
for (int i = 0; i < count; ++i) {
|
||||
pics[i] = fDrawableList[i]->newPictureSnapshot(factory, recordFlags);
|
||||
}
|
||||
return SkNEW_ARGS(SkPicture::SnapshotArray, (pics.detach(), count));
|
||||
}
|
||||
|
||||
// To make appending to fRecord a little less verbose.
|
||||
#define APPEND(T, ...) \
|
||||
SkNEW_PLACEMENT_ARGS(fRecord->append<SkRecords::T>(), SkRecords::T, (__VA_ARGS__))
|
||||
@ -146,8 +150,11 @@ void SkRecorder::onDrawDRRect(const SkRRect& outer, const SkRRect& inner, const
|
||||
}
|
||||
|
||||
void SkRecorder::onDrawDrawable(SkCanvasDrawable* drawable) {
|
||||
*fDrawableList.append() = SkRef(drawable);
|
||||
APPEND(DrawDrawable, drawable->getBounds(), fDrawableList.count() - 1);
|
||||
if (!fDrawableList) {
|
||||
fDrawableList.reset(SkNEW(SkCanvasDrawableList));
|
||||
}
|
||||
fDrawableList->append(drawable);
|
||||
APPEND(DrawDrawable, drawable->getBounds(), fDrawableList->count() - 1);
|
||||
}
|
||||
|
||||
void SkRecorder::drawPath(const SkPath& path, const SkPaint& paint) {
|
||||
|
@ -13,6 +13,24 @@
|
||||
#include "SkRecords.h"
|
||||
#include "SkTDArray.h"
|
||||
|
||||
class SkBBHFactory;
|
||||
|
||||
class SkCanvasDrawableList : SkNoncopyable {
|
||||
public:
|
||||
~SkCanvasDrawableList();
|
||||
|
||||
int count() const { return fArray.count(); }
|
||||
SkCanvasDrawable* const* begin() const { return fArray.begin(); }
|
||||
|
||||
void append(SkCanvasDrawable* drawable);
|
||||
|
||||
// Return a new or ref'd array of pictures that were snapped from our drawables.
|
||||
SkPicture::SnapshotArray* newDrawableSnapshot();
|
||||
|
||||
private:
|
||||
SkTDArray<SkCanvasDrawable*> fArray;
|
||||
};
|
||||
|
||||
// SkRecorder provides an SkCanvas interface for recording into an SkRecord.
|
||||
|
||||
class SkRecorder : public SkCanvas {
|
||||
@ -20,10 +38,9 @@ public:
|
||||
// Does not take ownership of the SkRecord.
|
||||
SkRecorder(SkRecord*, int width, int height); // legacy version
|
||||
SkRecorder(SkRecord*, const SkRect& bounds);
|
||||
virtual ~SkRecorder() SK_OVERRIDE;
|
||||
|
||||
// Return a new or ref'd array of pictures that were snapped from our drawables.
|
||||
SkPicture::SnapshotArray* newDrawableSnapshot(SkBBHFactory*, uint32_t recordFlags);
|
||||
SkCanvasDrawableList* getDrawableList() const { return fDrawableList.get(); }
|
||||
SkCanvasDrawableList* detachDrawableList() { return fDrawableList.detach(); }
|
||||
|
||||
// Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
|
||||
void forgetRecord();
|
||||
@ -145,7 +162,7 @@ private:
|
||||
|
||||
int fSaveLayerCount;
|
||||
SkTDArray<SkBool8> fSaveIsSaveLayer;
|
||||
SkTDArray<SkCanvasDrawable*> fDrawableList;
|
||||
SkAutoTDelete<SkCanvasDrawableList> fDrawableList;
|
||||
};
|
||||
|
||||
#endif//SkRecorder_DEFINED
|
||||
|
@ -60,7 +60,7 @@ public:
|
||||
const GrReplacements* replacements,
|
||||
const SkMatrix& initialMatrix,
|
||||
SkDrawPictureCallback* callback)
|
||||
: INHERITED(canvas, drawablePicts, drawableCount)
|
||||
: INHERITED(canvas, drawablePicts, NULL, drawableCount)
|
||||
, fCanvas(canvas)
|
||||
, fPicture(picture)
|
||||
, fReplacements(replacements)
|
||||
|
@ -1733,7 +1733,8 @@ static void test_bytes_used(skiatest::Reporter* reporter) {
|
||||
sizeof(SkPicture) + sizeof(SkRecord));
|
||||
|
||||
// Protect against any unintentional bloat.
|
||||
REPORTER_ASSERT(reporter, SkPictureUtils::ApproximateBytesUsed(empty.get()) <= 128);
|
||||
size_t approxUsed = SkPictureUtils::ApproximateBytesUsed(empty.get());
|
||||
REPORTER_ASSERT(reporter, approxUsed <= 136);
|
||||
|
||||
// Sanity check of nested SkPictures.
|
||||
SkPictureRecorder r2;
|
||||
@ -1905,11 +1906,16 @@ DEF_TEST(Picture_BitmapLeak, r) {
|
||||
REPORTER_ASSERT(r, mut.pixelRef()->unique());
|
||||
REPORTER_ASSERT(r, immut.pixelRef()->unique());
|
||||
|
||||
SkPictureRecorder rec;
|
||||
SkCanvas* canvas = rec.beginRecording(1920, 1200);
|
||||
canvas->drawBitmap(mut, 0, 0);
|
||||
canvas->drawBitmap(immut, 800, 600);
|
||||
SkAutoTUnref<const SkPicture> pic(rec.endRecording());
|
||||
SkAutoTUnref<const SkPicture> pic;
|
||||
{
|
||||
// we want the recorder to go out of scope before our subsequent checks, so we
|
||||
// place it inside local braces.
|
||||
SkPictureRecorder rec;
|
||||
SkCanvas* canvas = rec.beginRecording(1920, 1200);
|
||||
canvas->drawBitmap(mut, 0, 0);
|
||||
canvas->drawBitmap(immut, 800, 600);
|
||||
pic.reset(rec.endRecording());
|
||||
}
|
||||
|
||||
// The picture shares the immutable pixels but copies the mutable ones.
|
||||
REPORTER_ASSERT(r, mut.pixelRef()->unique());
|
||||
|
@ -41,7 +41,7 @@ DEF_TEST(RecordDraw_Abort, r) {
|
||||
SkRecorder canvas(&rerecord, W, H);
|
||||
|
||||
JustOneDraw callback;
|
||||
SkRecordDraw(record, &canvas, NULL, 0, NULL/*bbh*/, &callback);
|
||||
SkRecordDraw(record, &canvas, NULL, 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, 0, NULL/*bbh*/, NULL/*callback*/);
|
||||
SkRecordDraw(record, &canvas, NULL, 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, 0, NULL/*bbh*/, NULL/*callback*/);
|
||||
SkRecordDraw(scaleRecord, &translateCanvas, NULL, 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);
|
||||
@ -320,7 +320,7 @@ DEF_TEST(RecordDraw_drawImage, r){
|
||||
SkRecord record;
|
||||
SkRecorder recorder(&record, 10, 10);
|
||||
recorder.drawImage(image, 0, 0);
|
||||
SkRecordDraw(record, &canvas, NULL, 0, NULL, 0);
|
||||
SkRecordDraw(record, &canvas, NULL, NULL, 0, NULL, 0);
|
||||
}
|
||||
REPORTER_ASSERT(r, canvas.fDrawImageCalled);
|
||||
canvas.resetTestValues();
|
||||
@ -329,7 +329,7 @@ DEF_TEST(RecordDraw_drawImage, r){
|
||||
SkRecord record;
|
||||
SkRecorder recorder(&record, 10, 10);
|
||||
recorder.drawImageRect(image, 0, SkRect::MakeWH(10, 10));
|
||||
SkRecordDraw(record, &canvas, NULL, 0, NULL, 0);
|
||||
SkRecordDraw(record, &canvas, NULL, NULL, 0, NULL, 0);
|
||||
}
|
||||
REPORTER_ASSERT(r, canvas.fDrawImageRectCalled);
|
||||
|
||||
|
@ -21,7 +21,7 @@ public:
|
||||
: fDigits(0)
|
||||
, fIndent(0)
|
||||
, fIndex(0)
|
||||
, fDraw(canvas, NULL, 0, NULL)
|
||||
, fDraw(canvas, NULL, NULL, 0, NULL)
|
||||
, fTimeWithCommand(timeWithCommand) {
|
||||
while (count > 0) {
|
||||
count /= 10;
|
||||
|
Loading…
Reference in New Issue
Block a user