First pass at splitting out SkPictureRecord from SkPicture

This patch begins the process of splitting apart SkPicture, SkPicturePlayback and SkPictureRecord.

This is still a bit messy. In a follow up CL I hope to delay the creation of SkPictureRecorder's SkPicture until endRecording time.

R=reed@google.com, mtklein@google.com

Author: robertphillips@google.com

Review URL: https://codereview.chromium.org/318763004
This commit is contained in:
robertphillips 2014-06-08 05:55:05 -07:00 committed by Commit bot
parent 52e4f413ff
commit 643b8bd661
4 changed files with 68 additions and 144 deletions

View File

@ -147,8 +147,7 @@ public:
kUsePathBoundsForClip_RecordingFlag = 0x01
};
/** Replays the drawing commands on the specified canvas. This internally
calls endRecording() if that has not already been called.
/** Replays the drawing commands on the specified canvas.
@param canvas the canvas receiving the drawing commands.
*/
void draw(SkCanvas* canvas, SkDrawPictureCallback* = NULL) const;
@ -225,14 +224,6 @@ public:
static bool InternalOnly_StreamIsSKP(SkStream*, SkPictInfo*);
static bool InternalOnly_BufferIsSKP(SkReadBuffer&, SkPictInfo*);
/** Enable/disable all the picture recording optimizations (i.e.,
those in SkPictureRecord). It is mainly intended for testing the
existing optimizations (i.e., to actually have the pattern
appear in an .skp we have to disable the optimization). Call right
after 'beginRecording'.
*/
void internalOnly_EnableOpts(bool enableOpts);
/** Return true if the picture is suitable for rendering on the GPU.
*/
@ -284,7 +275,6 @@ protected:
// install their own SkPicturePlayback-derived players,SkPictureRecord-derived
// recorders and set the picture size
SkPicturePlayback* fPlayback;
SkPictureRecord* fRecord;
int fWidth, fHeight;
mutable const AccelData* fAccelData;
@ -419,31 +409,6 @@ private:
friend class GrGatherDevice;
friend class SkDebugCanvas;
// TODO: beginRecording, getRecordingCanvas & endRecording can now be
// be moved out of SkPicture (and, presumably, be directly implemented
// in SkPictureRecorder)
/** Returns the canvas that records the drawing commands.
@param width the base width for the picture, as if the recording
canvas' bitmap had this width.
@param height the base width for the picture, as if the recording
canvas' bitmap had this height.
@param factory if non-NULL, the factory used to the BBH for the recorded picture
@param recordFlags optional flags that control recording.
@return the picture canvas.
*/
SkCanvas* beginRecording(int width, int height, SkBBHFactory* factory, uint32_t recordFlags);
/** Returns the recording canvas if one is active, or NULL if recording is
not active. This does not alter the refcnt on the canvas (if present).
*/
SkCanvas* getRecordingCanvas() const;
/** Signal that the caller is done recording. This invalidates the canvas
returned by beginRecording/getRecordingCanvas, and prepares the picture
for drawing. Note: this happens implicitly the first time the picture
is drawn.
*/
void endRecording();
typedef SkRefCnt INHERITED;
};

View File

@ -13,9 +13,13 @@
#include "SkRefCnt.h"
class SkCanvas;
class SkPictureRecord;
class SK_API SkPictureRecorder : SkNoncopyable {
public:
SkPictureRecorder() : fCanvas(NULL) { }
~SkPictureRecorder();
/** Returns the canvas that records the drawing commands.
@param width the base width for the picture, as if the recording
canvas' bitmap had this width.
@ -33,25 +37,14 @@ public:
/** Returns the recording canvas if one is active, or NULL if recording is
not active. This does not alter the refcnt on the canvas (if present).
*/
SkCanvas* getRecordingCanvas() {
if (NULL != fPicture.get()) {
return fPicture->getRecordingCanvas();
}
return NULL;
}
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() {
if (NULL != fPicture.get()) {
fPicture->endRecording();
return fPicture.detach();
}
return NULL;
}
SkPicture* endRecording();
/** Enable/disable all the picture recording optimizations (i.e.,
those in SkPictureRecord). It is mainly intended for testing the
@ -59,11 +52,7 @@ public:
appear in an .skp we have to disable the optimization). Call right
after 'beginRecording'.
*/
void internalOnly_EnableOpts(bool enableOpts) {
if (NULL != fPicture.get()) {
fPicture->internalOnly_EnableOpts(enableOpts);
}
}
void internalOnly_EnableOpts(bool enableOpts);
private:
#ifdef SK_BUILD_FOR_ANDROID
@ -75,7 +64,8 @@ private:
void partialReplay(SkCanvas* canvas) const;
#endif
SkAutoTUnref<SkPicture> fPicture;
SkAutoTUnref<SkPicture> fPicture;
SkPictureRecord* fCanvas; // ref counted
typedef SkNoncopyable INHERITED;
};

View File

@ -126,7 +126,6 @@ static void validateMatrix(const SkMatrix* matrix) {
SkPicture::SkPicture()
: fAccelData(NULL) {
this->needsNewGenID();
fRecord = NULL;
fPlayback = NULL;
fWidth = fHeight = 0;
}
@ -149,7 +148,6 @@ SkPicture::SkPicture(const SkPicture& src)
this->needsNewGenID();
fWidth = src.fWidth;
fHeight = src.fHeight;
fRecord = NULL;
/* We want to copy the src's playback. However, if that hasn't been built
yet, we need to fake a call to endRecording() without actually calling
@ -157,10 +155,7 @@ SkPicture::SkPicture(const SkPicture& src)
*/
if (src.fPlayback) {
fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *src.fPlayback));
SkASSERT(NULL == src.fRecord);
fUniqueID = src.uniqueID(); // need to call method to ensure != 0
} else if (src.fRecord) {
fPlayback = FakeEndRecording(this, *src.fRecord, false);
} else {
fPlayback = NULL;
}
@ -198,20 +193,12 @@ void SkPicture::dumpSize() const {
}
SkPicture::~SkPicture() {
SkSafeUnref(fRecord);
SkDELETE(fPlayback);
SkSafeUnref(fAccelData);
}
void SkPicture::internalOnly_EnableOpts(bool enableOpts) {
if (NULL != fRecord) {
fRecord->internalOnly_EnableOpts(enableOpts);
}
}
void SkPicture::swap(SkPicture& other) {
SkTSwap(fUniqueID, other.fUniqueID);
SkTSwap(fRecord, other.fRecord);
SkTSwap(fPlayback, other.fPlayback);
SkTSwap(fAccelData, other.fAccelData);
SkTSwap(fWidth, other.fWidth);
@ -235,7 +222,6 @@ void SkPicture::clone(SkPicture* pictures, int count) const {
clone->needsNewGenID();
clone->fWidth = fWidth;
clone->fHeight = fHeight;
SkSafeSetNull(clone->fRecord);
SkDELETE(clone->fPlayback);
clone->fContentInfo.set(fContentInfo);
@ -287,10 +273,7 @@ void SkPicture::clone(SkPicture* pictures, int count) const {
}
clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (clone, *fPlayback, &copyInfo));
SkASSERT(NULL == fRecord);
clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
} else if (fRecord) {
clone->fPlayback = FakeEndRecording(clone, *fRecord, true);
} else {
clone->fPlayback = NULL;
}
@ -312,62 +295,13 @@ SkPicture::AccelData::Domain SkPicture::AccelData::GenerateDomain() {
///////////////////////////////////////////////////////////////////////////////
SkCanvas* SkPicture::beginRecording(int width, int height,
SkBBHFactory* bbhFactory,
uint32_t recordingFlags) {
if (fPlayback) {
SkDELETE(fPlayback);
fPlayback = NULL;
}
SkSafeUnref(fAccelData);
SkSafeSetNull(fRecord);
SkASSERT(NULL == fPathHeap);
fContentInfo.reset();
this->needsNewGenID();
fWidth = width;
fHeight = height;
const SkISize size = SkISize::Make(width, height);
if (NULL != bbhFactory) {
SkAutoTUnref<SkBBoxHierarchy> tree((*bbhFactory)(width, height));
SkASSERT(NULL != tree);
fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (this, size, recordingFlags, tree.get()));
} else {
fRecord = SkNEW_ARGS(SkPictureRecord, (this, size, recordingFlags));
}
fRecord->beginRecording();
return fRecord;
}
SkCanvas* SkPicture::getRecordingCanvas() const {
// will be null if we are not recording
return fRecord;
}
void SkPicture::endRecording() {
if (NULL == fPlayback) {
if (NULL != fRecord) {
fRecord->endRecording();
SkPictInfo info;
this->createHeader(&info);
fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info));
SkSafeSetNull(fRecord);
}
}
SkASSERT(NULL == fRecord);
}
const SkPicture::OperationList& SkPicture::OperationList::InvalidList() {
static OperationList gInvalid;
return gInvalid;
}
const SkPicture::OperationList& SkPicture::EXPERIMENTAL_getActiveOps(const SkIRect& queryRect) const {
SkASSERT(NULL != fPlayback && NULL == fRecord);
SkASSERT(NULL != fPlayback);
if (NULL != fPlayback) {
return fPlayback->getActiveOps(queryRect);
}
@ -382,7 +316,7 @@ size_t SkPicture::EXPERIMENTAL_curOpID() const {
}
void SkPicture::draw(SkCanvas* surface, SkDrawPictureCallback* callback) const {
SkASSERT(NULL != fPlayback && NULL == fRecord);
SkASSERT(NULL != fPlayback);
if (NULL != fPlayback) {
fPlayback->draw(*surface, callback);
}
@ -441,7 +375,6 @@ bool SkPicture::InternalOnly_BufferIsSKP(SkReadBuffer& buffer, SkPictInfo* pInfo
SkPicture::SkPicture(SkPicturePlayback* playback, int width, int height)
: fPlayback(playback)
, fRecord(NULL)
, fWidth(width)
, fHeight(height)
, fAccelData(NULL) {
@ -515,10 +448,6 @@ void SkPicture::createHeader(SkPictInfo* info) const {
void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
SkPicturePlayback* playback = fPlayback;
if (NULL == playback && fRecord) {
playback = FakeEndRecording(this, *fRecord, false);
}
SkPictInfo info;
this->createHeader(&info);
stream->write(&info, sizeof(info));
@ -573,10 +502,6 @@ void SkPicture::flattenToBuffer(SkWriteBuffer& buffer) const {
void SkPicture::flatten(SkWriteBuffer& buffer) const {
SkPicturePlayback* playback = fPlayback;
if (NULL == playback && fRecord) {
playback = FakeEndRecording(this, *fRecord, false);
}
SkPictInfo info;
this->createHeader(&info);
buffer.writeByteArray(&info, sizeof(info));
@ -642,11 +567,6 @@ static int32_t next_picture_generation_id() {
}
uint32_t SkPicture::uniqueID() const {
if (NULL != fRecord) {
SkASSERT(NULL == fPlayback);
return SK_InvalidGenID;
}
if (SK_InvalidGenID == fUniqueID) {
fUniqueID = next_picture_generation_id();
}

View File

@ -5,18 +5,67 @@
* found in the LICENSE file.
*/
// Need to include SkTypes first, so that SK_BUILD_FOR_ANDROID is defined.
#include "SkTypes.h"
#ifdef SK_BUILD_FOR_ANDROID
#include "SkBBoxHierarchyRecord.h"
#include "SkPicturePlayback.h"
#endif
#include "SkPictureRecord.h"
#include "SkPictureRecorder.h"
#include "SkTypes.h"
SkPictureRecorder::~SkPictureRecorder() {
SkSafeSetNull(fCanvas);
}
SkCanvas* SkPictureRecorder::beginRecording(int width, int height,
SkBBHFactory* bbhFactory /* = NULL */,
uint32_t recordFlags /* = 0 */) {
SkSafeSetNull(fCanvas);
fPicture.reset(SkNEW(SkPicture));
return fPicture->beginRecording(width, height, bbhFactory, recordFlags);
fPicture->fWidth = width;
fPicture->fHeight = height;
const SkISize size = SkISize::Make(width, height);
if (NULL != bbhFactory) {
SkAutoTUnref<SkBBoxHierarchy> tree((*bbhFactory)(width, height));
SkASSERT(NULL != tree);
fCanvas = SkNEW_ARGS(SkBBoxHierarchyRecord, (fPicture, size, recordFlags, tree.get()));
} else {
fCanvas = SkNEW_ARGS(SkPictureRecord, (fPicture, size, recordFlags));
}
fCanvas->beginRecording();
return fCanvas;
}
SkCanvas* SkPictureRecorder::getRecordingCanvas() {
return fCanvas;
}
SkPicture* SkPictureRecorder::endRecording() {
if (NULL == fPicture.get()) {
return NULL;
}
SkASSERT(NULL == fPicture->fPlayback);
SkASSERT(NULL != fCanvas);
fCanvas->endRecording();
SkPictInfo info;
fPicture->createHeader(&info);
fPicture->fPlayback = SkNEW_ARGS(SkPicturePlayback, (fPicture, *fCanvas, info));
SkSafeSetNull(fCanvas);
return fPicture.detach();
}
void SkPictureRecorder::internalOnly_EnableOpts(bool enableOpts) {
if (NULL != fCanvas) {
fCanvas->internalOnly_EnableOpts(enableOpts);
}
}
#ifdef SK_BUILD_FOR_ANDROID
@ -26,10 +75,10 @@ void SkPictureRecorder::partialReplay(SkCanvas* canvas) const {
return;
}
SkASSERT(NULL != fPicture->fRecord);
SkASSERT(NULL != fCanvas);
SkAutoTDelete<SkPicturePlayback> playback(SkPicture::FakeEndRecording(fPicture.get(),
*fPicture->fRecord,
*fCanvas,
false));
playback->draw(*canvas, NULL);
}