export flags on the state of the world when a picture was serialized.

e.g. don't read/write functionptrs in that case (sizeof may be different for one)
Review URL: https://codereview.appspot.com/6331050

git-svn-id: http://skia.googlecode.com/svn/trunk@4318 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-06-25 14:36:28 +00:00
Родитель ec95a4ae45
Коммит 34342f6f51
8 изменённых файлов: 66 добавлений и 14 удалений

Просмотреть файл

@ -127,9 +127,21 @@ class SkTypeface;
class SkFlattenableReadBuffer {
public:
enum Flags {
kCrossProcess_Flag = 1 << 0,
kScalarIsFloat_Flag = 1 << 1,
kPtrIs64Bit_Flag = 1 << 2,
};
SkFlattenableReadBuffer();
virtual ~SkFlattenableReadBuffer() {}
void setFlags(uint32_t flags) { fFlags = flags; }
uint32_t getFlags() const { return fFlags; }
bool isCrossProcess() const { return SkToBool(fFlags & kCrossProcess_Flag); }
bool isScalarFloat() const { return SkToBool(fFlags & kScalarIsFloat_Flag); }
bool isPtr64Bit() const { return SkToBool(fFlags & kPtrIs64Bit_Flag); }
virtual uint8_t readU8() = 0;
virtual uint16_t readU16() = 0;
@ -192,7 +204,7 @@ public:
virtual SkRefCnt* readRefCnt() = 0;
virtual void* readFunctionPtr() = 0;
virtual SkFlattenable* readFlattenable() = 0;
protected:
SkRefCnt** fRCArray;
int fRCCount;
@ -203,6 +215,9 @@ protected:
SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
SkFlattenable::Factory* fFactoryArray;
int fFactoryCount;
private:
uint32_t fFlags;
};
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -37,6 +37,10 @@ public:
this call, those elements will not appear in this picture.
*/
SkPicture(const SkPicture& src);
/**
* Recreate a picture that was serialized into a stream. If an error occurs
* the picture will be "empty" : width and height == 0
*/
explicit SkPicture(SkStream*);
virtual ~SkPicture();

Просмотреть файл

@ -32,6 +32,16 @@ SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
fFactoryTDArray = NULL;
fFactoryArray = NULL;
fFactoryCount = 0;
// Set default values. These should be explicitly set by our client
// via setFlags() if the buffer came from serialization.
fFlags = 0;
#ifdef SK_SCALAR_IS_FLOAT
fFlags |= kScalarIsFloat_Flag;
#endif
if (8 == sizeof(void*)) {
fFlags |= kPtrIs64Bit_Flag;
}
}
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -99,6 +99,8 @@ SkFlattenable* SkOrderedReadBuffer::readFlattenable() {
}
void* SkOrderedReadBuffer::readFunctionPtr() {
SkASSERT(!this->isCrossProcess());
void* proc;
fReader.read(&proc, sizeof(proc));
return proc;

Просмотреть файл

@ -95,11 +95,7 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
}
void SkOrderedWriteBuffer::writeFunctionPtr(void* proc) {
// enable this to catch writers who's function-ptrs will break if the
// serialized buffer is read-back in a diff process
#if 0
SkASSERT(!proc || !this->isCrossProcess());
#endif
SkASSERT(!this->isCrossProcess());
*(void**)this->reserve(sizeof(void*)) = proc;
}

Просмотреть файл

@ -202,7 +202,8 @@ void SkPicture::draw(SkCanvas* surface) {
// V2 : adds SkPixelRef's generation ID.
// V3 : PictInfo tag at beginning, and EOF tag at the end
// V4 : move SkPictInfo to be the header
#define PICTURE_VERSION 4
// V5 : don't read/write FunctionPtr on cross-process (we can detect that)
#define PICTURE_VERSION 5
SkPicture::SkPicture(SkStream* stream) : SkRefCnt() {
fRecord = NULL;

Просмотреть файл

@ -337,6 +337,7 @@ void SkPicturePlayback::serialize(SkWStream* stream) const {
buffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
buffer.setTypefaceRecorder(&typefaceSet);
buffer.setFactoryRecorder(&factSet);
this->flattenToBuffer(buffer);
// We have to write these to sets into the stream *before* we write
@ -354,6 +355,29 @@ void SkPicturePlayback::serialize(SkWStream* stream) const {
///////////////////////////////////////////////////////////////////////////////
/**
* Return the corresponding SkFlattenableReadBuffer flags, given a set of
* SkPictInfo flags.
*/
static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
static const struct {
uint32_t fSrc;
uint32_t fDst;
} gSD[] = {
{ SkPictInfo::kCrossProcess_Flag, SkFlattenableReadBuffer::kCrossProcess_Flag },
{ SkPictInfo::kScalarIsFloat_Flag, SkFlattenableReadBuffer::kScalarIsFloat_Flag },
{ SkPictInfo::kPtrIs64Bit_Flag, SkFlattenableReadBuffer::kPtrIs64Bit_Flag },
};
uint32_t rbMask = 0;
for (size_t i = 0; i < SK_ARRAY_COUNT(gSD); ++i) {
if (pictInfoFlags & gSD[i].fSrc) {
rbMask |= gSD[i].fDst;
}
}
return rbMask;
}
bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
uint32_t tag, size_t size) {
/*
@ -403,6 +427,8 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream, const SkPictInfo& info,
stream->read(storage.get(), size);
SkOrderedReadBuffer buffer(storage.get(), size);
buffer.setFlags(pictInfoFlagsToReadBufferFlags(info.fFlags));
fFactoryPlayback->setupBuffer(buffer);
fTFPlayback.setupBuffer(buffer);

Просмотреть файл

@ -681,17 +681,15 @@ void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
: SkXfermode(buffer) {
// Might be a NULL if the Xfermode is recorded using the CrossProcess flag
fProc = (SkXfermodeProc)buffer.readFunctionPtr();
fProc = NULL;
if (!buffer.isCrossProcess()) {
fProc = (SkXfermodeProc)buffer.readFunctionPtr();
}
}
void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
if (buffer.isCrossProcess()) {
// function pointer is only valid in the current process. Write a NULL
// so it can't be accidentally used
buffer.writeFunctionPtr(NULL);
} else {
if (!buffer.isCrossProcess()) {
buffer.writeFunctionPtr((void*)fProc);
}
}