Pipe factory names independently from the flattenables using them.

Avoids an issue where a flattenable written twice might be written
differently (the first time the flat data may have a name, whereas
the second time it will have an index).

Also add a test which confirms that identical flattenables will have
the same SkFlatData representation.

BUG=https://code.google.com/p/skia/issues/detail?id=721
TEST=FlatDataTest.cpp

Review URL: https://codereview.appspot.com/6431057

git-svn-id: http://skia.googlecode.com/svn/trunk@4896 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
scroggo@google.com 2012-08-01 19:34:20 +00:00
Родитель 4605a3f3ff
Коммит 0c3e5fe728
12 изменённых файлов: 267 добавлений и 103 удалений

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

@ -40,6 +40,7 @@
'../tests/DrawTextTest.cpp', '../tests/DrawTextTest.cpp',
'../tests/EmptyPathTest.cpp', '../tests/EmptyPathTest.cpp',
'../tests/FillPathTest.cpp', '../tests/FillPathTest.cpp',
'../tests/FlatDataTest.cpp',
'../tests/FlateTest.cpp', '../tests/FlateTest.cpp',
'../tests/FontHostStreamTest.cpp', '../tests/FontHostStreamTest.cpp',
'../tests/FontHostTest.cpp', '../tests/FontHostTest.cpp',

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

@ -191,8 +191,8 @@ public:
/** /**
* Call this with an initially empty array, so the reader can cache each * Call this with an initially empty array, so the reader can cache each
* factory it sees by name. Used by the pipe code in conjunction with * factory it sees by name. Used by the pipe code in combination with
* the writer's kInlineFactoryNames_Flag. * setNamedFactoryRecorder.
*/ */
void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) { void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
fFactoryTDArray = array; fFactoryTDArray = array;
@ -241,6 +241,33 @@ protected:
class SkFactorySet : public SkTPtrSet<SkFlattenable::Factory> {}; class SkFactorySet : public SkTPtrSet<SkFlattenable::Factory> {};
/**
* Similar to SkFactorySet, but only allows Factorys that have registered names.
* Also has a function to return the next added Factory's name.
*/
class SkNamedFactorySet : public SkRefCnt {
public:
SkNamedFactorySet();
/**
* Find the specified Factory in the set. If it is not already in the set,
* and has registered its name, add it to the set, and return its index.
* If the Factory has no registered name, return 0.
*/
uint32_t find(SkFlattenable::Factory);
/**
* If new Factorys have been added to the set, return the name of the first
* Factory added after the Factory name returned by the last call to this
* function.
*/
const char* getNextAddedFactoryName();
private:
int fNextAddedFactory;
SkFactorySet fFactorySet;
SkTDArray<const char*> fNames;
};
class SkFlattenableWriteBuffer { class SkFlattenableWriteBuffer {
public: public:
SkFlattenableWriteBuffer(); SkFlattenableWriteBuffer();
@ -285,13 +312,11 @@ public:
SkFactorySet* getFactoryRecorder() const { return fFactorySet; } SkFactorySet* getFactoryRecorder() const { return fFactorySet; }
SkFactorySet* setFactoryRecorder(SkFactorySet*); SkFactorySet* setFactoryRecorder(SkFactorySet*);
SkNamedFactorySet* getNamedFactoryRecorder() const { return fNamedFactorySet; }
SkNamedFactorySet* setNamedFactoryRecorder(SkNamedFactorySet*);
enum Flags { enum Flags {
kCrossProcess_Flag = 0x01, kCrossProcess_Flag = 0x01,
/**
* Instructs the writer to inline Factory names as there are seen the
* first time (after that we store an index). The pipe code uses this.
*/
kInlineFactoryNames_Flag = 0x02,
/** /**
* Instructs the writer to always serialize bitmap pixel data. * Instructs the writer to always serialize bitmap pixel data.
*/ */
@ -304,9 +329,6 @@ public:
bool isCrossProcess() const { bool isCrossProcess() const {
return SkToBool(fFlags & kCrossProcess_Flag); return SkToBool(fFlags & kCrossProcess_Flag);
} }
bool inlineFactoryNames() const {
return SkToBool(fFlags & kInlineFactoryNames_Flag);
}
bool persistBitmapPixels() const { bool persistBitmapPixels() const {
return (fFlags & (kCrossProcess_Flag | kForceFlattenBitmapPixels_Flag)) != 0; return (fFlags & (kCrossProcess_Flag | kForceFlattenBitmapPixels_Flag)) != 0;
@ -326,6 +348,8 @@ protected:
SkRefCntSet* fTFSet; SkRefCntSet* fTFSet;
SkRefCntSet* fRCSet; SkRefCntSet* fRCSet;
SkFactorySet* fFactorySet; SkFactorySet* fFactorySet;
SkNamedFactorySet* fNamedFactorySet;
}; };
#endif #endif

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

@ -128,7 +128,6 @@ public:
private: private:
SkGPipeCanvas* fCanvas; SkGPipeCanvas* fCanvas;
SkFactorySet* fFactorySet;
SkWriter32 fWriter; SkWriter32 fWriter;
}; };

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

@ -46,17 +46,43 @@ SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
uint32_t index = fFactorySet.find(factory);
if (index > 0) {
return index;
}
const char* name = SkFlattenable::FactoryToName(factory);
if (NULL == name) {
return 0;
}
*fNames.append() = name;
return fFactorySet.add(factory);
}
const char* SkNamedFactorySet::getNextAddedFactoryName() {
if (fNextAddedFactory < fNames.count()) {
return fNames[fNextAddedFactory++];
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////
SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() { SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() {
fFlags = (Flags)0; fFlags = (Flags)0;
fRCSet = NULL; fRCSet = NULL;
fTFSet = NULL; fTFSet = NULL;
fFactorySet = NULL; fFactorySet = NULL;
fNamedFactorySet = NULL;
} }
SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
SkSafeUnref(fRCSet); SkSafeUnref(fRCSet);
SkSafeUnref(fTFSet); SkSafeUnref(fTFSet);
SkSafeUnref(fFactorySet); SkSafeUnref(fFactorySet);
SkSafeUnref(fNamedFactorySet);
} }
SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) { SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
@ -71,6 +97,20 @@ SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
SkRefCnt_SafeAssign(fFactorySet, rec); SkRefCnt_SafeAssign(fFactorySet, rec);
if (fNamedFactorySet != NULL) {
fNamedFactorySet->unref();
fNamedFactorySet = NULL;
}
return rec;
}
SkNamedFactorySet* SkFlattenableWriteBuffer::setNamedFactoryRecorder(
SkNamedFactorySet* rec) {
SkRefCnt_SafeAssign(fNamedFactorySet, rec);
if (fFactorySet != NULL) {
fFactorySet->unref();
fFactorySet = NULL;
}
return rec; return rec;
} }

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

@ -45,32 +45,16 @@ SkFlattenable* SkOrderedReadBuffer::readFlattenable() {
if (0 == index) { if (0 == index) {
return NULL; // writer failed to give us the flattenable return NULL; // writer failed to give us the flattenable
} }
index = -index; // we stored the negative of the index
index -= 1; // we stored the index-base-1 index -= 1; // we stored the index-base-1
SkASSERT(index < fFactoryCount); SkASSERT(index < fFactoryCount);
factory = fFactoryArray[index]; factory = fFactoryArray[index];
} else if (fFactoryTDArray) { } else if (fFactoryTDArray) {
const int32_t* peek = (const int32_t*)fReader.peek();
if (*peek <= 0) {
int32_t index = fReader.readU32(); int32_t index = fReader.readU32();
if (0 == index) { if (0 == index) {
return NULL; // writer failed to give us the flattenable return NULL; // writer failed to give us the flattenable
} }
index = -index; // we stored the negative of the index
index -= 1; // we stored the index-base-1 index -= 1; // we stored the index-base-1
factory = (*fFactoryTDArray)[index]; factory = (*fFactoryTDArray)[index];
} else {
const char* name = fReader.readString();
factory = SkFlattenable::NameToFactory(name);
if (factory) {
SkASSERT(fFactoryTDArray->find(factory) < 0);
*fFactoryTDArray->append() = factory;
} else {
// SkDebugf("can't find factory for [%s]\n", name);
}
// if we didn't find a factory, that's our failure, not the writer's,
// so we fall through, so we can skip the sizeRecorded data.
}
} else { } else {
factory = (SkFlattenable::Factory)readFunctionPtr(); factory = (SkFlattenable::Factory)readFunctionPtr();
if (NULL == factory) { if (NULL == factory) {

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

@ -23,8 +23,7 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
/* /*
* If we have a factoryset, then the first 32bits tell us... * If we have a factoryset, then the first 32bits tell us...
* 0: failure to write the flattenable * 0: failure to write the flattenable
* <0: we store the negative of the (1-based) index * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet
* >0: the length of the name
* If we don't have a factoryset, then the first "ptr" is either the * If we don't have a factoryset, then the first "ptr" is either the
* factory, or null for failure. * factory, or null for failure.
* *
@ -37,7 +36,7 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
factory = flattenable->getFactory(); factory = flattenable->getFactory();
} }
if (NULL == factory) { if (NULL == factory) {
if (fFactorySet) { if (fFactorySet != NULL || fNamedFactorySet != NULL) {
this->write32(0); this->write32(0);
} else { } else {
this->writeFunctionPtr(NULL); this->writeFunctionPtr(NULL);
@ -53,32 +52,18 @@ void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
* resolve the function-ptrs into strings for its reader. SkPicture * resolve the function-ptrs into strings for its reader. SkPicture
* does exactly this, by writing a table of names (matching the indices) * does exactly this, by writing a table of names (matching the indices)
* up front in its serialized form. * up front in its serialized form.
* 3. names : Reuse fFactorySet to store indices, but only after we've * 3. index into fNamedFactorySet. fNamedFactorySet will also store the
* written the name the first time. SkGPipe uses this technique, as it * name. SkGPipe uses this technique so it can write the name to its
* doesn't require the reader to be told to know the table of names * stream before writing the flattenable.
* up front.
*/ */
if (fFactorySet) { if (fFactorySet) {
if (this->inlineFactoryNames()) { this->write32(fFactorySet->add(factory));
int index = fFactorySet->find(factory); } else if (fNamedFactorySet) {
if (index) { int32_t index = fNamedFactorySet->find(factory);
// we write the negative of the index, to distinguish it from this->write32(index);
// the length of a string if (0 == index) {
this->write32(-index);
} else {
const char* name = SkFlattenable::FactoryToName(factory);
if (NULL == name) {
this->write32(0);
return; return;
} }
this->writeString(name);
index = fFactorySet->add(factory);
}
} else {
// we write the negative of the index, to distinguish it from
// the length of a string
this->write32(-(int)fFactorySet->add(factory));
}
} else { } else {
this->writeFunctionPtr((void*)factory); this->writeFunctionPtr((void*)factory);
} }

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

@ -63,7 +63,7 @@ SkRefCnt* SkRefCntPlayback::set(int index, SkRefCnt* obj) {
SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj, SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj,
int index, void (*flattenProc)(SkOrderedWriteBuffer&, const void*), int index, void (*flattenProc)(SkOrderedWriteBuffer&, const void*),
SkRefCntSet* refCntRecorder, SkRefCntSet* faceRecorder, SkRefCntSet* refCntRecorder, SkRefCntSet* faceRecorder,
uint32_t writeBufferflags, SkFactorySet* fset) { uint32_t writeBufferflags, SkNamedFactorySet* fset) {
// a buffer of 256 bytes should be sufficient for most paints, regions, // a buffer of 256 bytes should be sufficient for most paints, regions,
// and matrices. // and matrices.
intptr_t storage[256]; intptr_t storage[256];
@ -75,7 +75,7 @@ SkFlatData* SkFlatData::Create(SkFlatController* controller, const void* obj,
buffer.setTypefaceRecorder(faceRecorder); buffer.setTypefaceRecorder(faceRecorder);
} }
buffer.setFlags(writeBufferflags); buffer.setFlags(writeBufferflags);
buffer.setFactoryRecorder(fset); buffer.setNamedFactoryRecorder(fset);
flattenProc(buffer, obj); flattenProc(buffer, obj);
uint32_t size = buffer.size(); uint32_t size = buffer.size();

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

@ -175,6 +175,7 @@ public:
* provided. * provided.
*/ */
virtual void unalloc(void* ptr) = 0; virtual void unalloc(void* ptr) = 0;
}; };
class SkFlatData { class SkFlatData {
@ -241,7 +242,7 @@ public:
SkRefCntSet* refCntRecorder = NULL, SkRefCntSet* refCntRecorder = NULL,
SkRefCntSet* faceRecorder = NULL, SkRefCntSet* faceRecorder = NULL,
uint32_t writeBufferflags = 0, uint32_t writeBufferflags = 0,
SkFactorySet* fset = NULL); SkNamedFactorySet* fset = NULL);
void unflatten(void* result, void unflatten(void* result,
void (*unflattenProc)(SkOrderedReadBuffer&, void*), void (*unflattenProc)(SkOrderedReadBuffer&, void*),
@ -291,7 +292,7 @@ class SkFlatDictionary {
public: public:
SkFlatDictionary(SkFlatController* controller, SkRefCntSet* refSet = NULL, SkFlatDictionary(SkFlatController* controller, SkRefCntSet* refSet = NULL,
SkRefCntSet* typeFaceSet = NULL, SkRefCntSet* typeFaceSet = NULL,
SkFactorySet* factorySet = NULL) SkNamedFactorySet* factorySet = NULL)
: fController(controller), fRefSet(refSet), fTypefaceSet(typeFaceSet) : fController(controller), fRefSet(refSet), fTypefaceSet(typeFaceSet)
, fFactorySet(factorySet) { , fFactorySet(factorySet) {
fFlattenProc = NULL; fFlattenProc = NULL;
@ -444,7 +445,7 @@ private:
SkTDArray<const SkFlatData*> fData; SkTDArray<const SkFlatData*> fData;
SkRefCntSet* fRefSet; SkRefCntSet* fRefSet;
SkRefCntSet* fTypefaceSet; SkRefCntSet* fTypefaceSet;
SkFactorySet* fFactorySet; SkNamedFactorySet* fFactorySet;
const SkFlatData* findAndReturnFlat(const T& element, const SkFlatData* findAndReturnFlat(const T& element,
uint32_t writeBufferflags) { uint32_t writeBufferflags) {
@ -540,7 +541,7 @@ class SkBitmapDictionary : public SkFlatDictionary<SkBitmap> {
public: public:
SkBitmapDictionary(SkFlatController* controller, SkRefCntSet* refSet = NULL, SkBitmapDictionary(SkFlatController* controller, SkRefCntSet* refSet = NULL,
SkRefCntSet* typefaceSet = NULL, SkRefCntSet* typefaceSet = NULL,
SkFactorySet* factorySet = NULL) SkNamedFactorySet* factorySet = NULL)
: SkFlatDictionary<SkBitmap>(controller, refSet, typefaceSet, factorySet) { : SkFlatDictionary<SkBitmap>(controller, refSet, typefaceSet, factorySet) {
fFlattenProc = &SkFlattenObjectProc<SkBitmap>; fFlattenProc = &SkFlattenObjectProc<SkBitmap>;
fUnflattenProc = &SkUnflattenObjectProc<SkBitmap>; fUnflattenProc = &SkUnflattenObjectProc<SkBitmap>;

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

@ -70,6 +70,7 @@ enum DrawOps {
kDef_Typeface_DrawOp, kDef_Typeface_DrawOp,
kDef_Flattenable_DrawOp, kDef_Flattenable_DrawOp,
kDef_Bitmap_DrawOp, kDef_Bitmap_DrawOp,
kDef_Factory_DrawOp,
// these are signals to playback, not drawing verbs // these are signals to playback, not drawing verbs
kReportFlags_DrawOp, kReportFlags_DrawOp,

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

@ -104,6 +104,14 @@ public:
} }
} }
void defFactory(const char* name) {
SkFlattenable::Factory factory = SkFlattenable::NameToFactory(name);
if (factory) {
SkASSERT(fFactoryArray.find(factory) < 0);
*fFactoryArray.append() = factory;
}
}
void addBitmap(int index) { void addBitmap(int index) {
index--; index--;
SkBitmap* bm; SkBitmap* bm;
@ -551,6 +559,11 @@ static void def_Bitmap_rp(SkCanvas*, SkReader32*, uint32_t op32,
state->addBitmap(index); state->addBitmap(index);
} }
static void def_Factory_rp(SkCanvas*, SkReader32* reader, uint32_t,
SkGPipeState* state) {
state->defFactory(reader->readString());
}
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) { static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) {
@ -605,6 +618,7 @@ static const ReadProc gReadTable[] = {
def_Typeface_rp, def_Typeface_rp,
def_PaintFlat_rp, def_PaintFlat_rp,
def_Bitmap_rp, def_Bitmap_rp,
def_Factory_rp,
reportflags_rp, reportflags_rp,
done_rp done_rp

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

@ -28,6 +28,10 @@
#include "SkOrderedWriteBuffer.h" #include "SkOrderedWriteBuffer.h"
#include "SkPictureFlat.h" #include "SkPictureFlat.h"
static bool isCrossProcess(uint32_t flags) {
return SkToBool(flags & SkGPipeWriter::kCrossProcess_Flag);
}
static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) { static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
SkASSERT(paintFlat < kCount_PaintFlats); SkASSERT(paintFlat < kCount_PaintFlats);
switch (paintFlat) { switch (paintFlat) {
@ -61,7 +65,9 @@ static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
class FlattenableHeap : public SkFlatController { class FlattenableHeap : public SkFlatController {
public: public:
FlattenableHeap(int numFlatsToKeep) : fNumFlatsToKeep(numFlatsToKeep) {} FlattenableHeap(int numFlatsToKeep)
: fNumFlatsToKeep(numFlatsToKeep) {
}
~FlattenableHeap() { ~FlattenableHeap() {
fPointers.freeAll(); fPointers.freeAll();
@ -132,7 +138,7 @@ const SkFlatData* FlattenableHeap::flatToReplace() const {
class FlatDictionary : public SkFlatDictionary<SkFlattenable> { class FlatDictionary : public SkFlatDictionary<SkFlattenable> {
public: public:
FlatDictionary(FlattenableHeap* heap, SkFactorySet* factorySet) FlatDictionary(FlattenableHeap* heap, SkNamedFactorySet* factorySet)
: SkFlatDictionary<SkFlattenable>(heap, NULL, NULL, factorySet) { : SkFlatDictionary<SkFlattenable>(heap, NULL, NULL, factorySet) {
fFlattenProc = &flattenFlattenableProc; fFlattenProc = &flattenFlattenableProc;
// No need to define fUnflattenProc since the writer will never // No need to define fUnflattenProc since the writer will never
@ -365,7 +371,7 @@ BitmapInfo* SharedHeap::bitmapToReplace(const SkBitmap& bm) const {
class SkGPipeCanvas : public SkCanvas { class SkGPipeCanvas : public SkCanvas {
public: public:
SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*, uint32_t flags); SkGPipeCanvas(SkGPipeController*, SkWriter32*, uint32_t flags);
virtual ~SkGPipeCanvas(); virtual ~SkGPipeCanvas();
void finish() { void finish() {
@ -439,6 +445,7 @@ private:
enum { enum {
kNoSaveLayer = -1, kNoSaveLayer = -1,
}; };
SkNamedFactorySet* fFactorySet;
int fFirstSaveLayerStackLevel; int fFirstSaveLayerStackLevel;
SharedHeap fSharedHeap; SharedHeap fSharedHeap;
SkGPipeController* fController; SkGPipeController* fController;
@ -472,6 +479,10 @@ private:
} }
} }
// Should be called after any calls to an SkFlatDictionary::findAndReplace
// if a new SkFlatData was added when in cross process mode
void flattenFactoryNames();
// These are only used when in cross process, but with no shared address // These are only used when in cross process, but with no shared address
// space, so bitmaps are flattened. // space, so bitmaps are flattened.
FlattenableHeap fBitmapHeap; FlattenableHeap fBitmapHeap;
@ -509,18 +520,32 @@ private:
typedef SkCanvas INHERITED; typedef SkCanvas INHERITED;
}; };
void SkGPipeCanvas::flattenFactoryNames() {
const char* name;
while ((name = fFactorySet->getNextAddedFactoryName()) != NULL) {
size_t len = strlen(name);
if (this->needOpBytes(len)) {
this->writeOp(kDef_Factory_DrawOp);
fWriter.writeString(name, len);
}
}
}
int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) { int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
SkASSERT(shouldFlattenBitmaps(fFlags)); SkASSERT(shouldFlattenBitmaps(fFlags));
uint32_t flags = SkFlattenableWriteBuffer::kInlineFactoryNames_Flag uint32_t flags = SkFlattenableWriteBuffer::kCrossProcess_Flag;
| SkFlattenableWriteBuffer::kCrossProcess_Flag;
bool added, replaced; bool added, replaced;
const SkFlatData* flat = fBitmapDictionary.findAndReplace( const SkFlatData* flat = fBitmapDictionary.findAndReplace(
bitmap, flags, fBitmapHeap.flatToReplace(), &added, &replaced); bitmap, flags, fBitmapHeap.flatToReplace(), &added, &replaced);
int index = flat->index(); int index = flat->index();
if (added && this->needOpBytes(flat->flatSize())) { if (added) {
this->flattenFactoryNames();
size_t flatSize = flat->flatSize();
if (this->needOpBytes(flatSize)) {
this->writeOp(kDef_Bitmap_DrawOp, 0, index); this->writeOp(kDef_Bitmap_DrawOp, 0, index);
fWriter.write(flat->data(), flat->flatSize()); fWriter.write(flat->data(), flatSize);
}
} }
return index; return index;
} }
@ -533,9 +558,8 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
} }
uint32_t writeBufferFlags; uint32_t writeBufferFlags;
if (SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag)) { if (isCrossProcess(fFlags)) {
writeBufferFlags = (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag writeBufferFlags = SkFlattenableWriteBuffer::kCrossProcess_Flag;
| SkFlattenableWriteBuffer::kCrossProcess_Flag);
} else { } else {
// Needed for bitmap shaders. // Needed for bitmap shaders.
writeBufferFlags = SkFlattenableWriteBuffer::kForceFlattenBitmapPixels_Flag; writeBufferFlags = SkFlattenableWriteBuffer::kForceFlattenBitmapPixels_Flag;
@ -545,9 +569,15 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
const SkFlatData* flat = fFlatDictionary.findAndReplace( const SkFlatData* flat = fFlatDictionary.findAndReplace(
*obj, writeBufferFlags, fFlattenableHeap.flatToReplace(), &added, &replaced); *obj, writeBufferFlags, fFlattenableHeap.flatToReplace(), &added, &replaced);
int index = flat->index(); int index = flat->index();
if (added && this->needOpBytes(flat->flatSize())) { if (added) {
if (isCrossProcess(fFlags)) {
this->flattenFactoryNames();
}
size_t flatSize = flat->flatSize();
if (this->needOpBytes(flatSize)) {
this->writeOp(kDef_Flattenable_DrawOp, paintflat, index); this->writeOp(kDef_Flattenable_DrawOp, paintflat, index);
fWriter.write(flat->data(), flat->flatSize()); fWriter.write(flat->data(), flatSize);
}
} }
if (replaced) { if (replaced) {
index = ~index; index = ~index;
@ -562,11 +592,15 @@ int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
#define FLATTENABLES_TO_KEEP 10 #define FLATTENABLES_TO_KEEP 10
SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller, SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
SkWriter32* writer, SkFactorySet* fset, uint32_t flags) SkWriter32* writer, uint32_t flags)
: fSharedHeap(!(flags & SkGPipeWriter::kCrossProcess_Flag), controller->numberOfReaders()) : fFactorySet(isCrossProcess(flags) ? SkNEW(SkNamedFactorySet) : NULL)
, fWriter(*writer), fFlags(flags) , fSharedHeap(!isCrossProcess(flags), controller->numberOfReaders())
, fBitmapHeap(BITMAPS_TO_KEEP), fBitmapDictionary(&fBitmapHeap, NULL, NULL, fset) , fWriter(*writer)
, fFlattenableHeap(FLATTENABLES_TO_KEEP), fFlatDictionary(&fFlattenableHeap, fset) { , fFlags(flags)
, fBitmapHeap(BITMAPS_TO_KEEP)
, fBitmapDictionary(&fBitmapHeap, NULL, NULL, fFactorySet)
, fFlattenableHeap(FLATTENABLES_TO_KEEP)
, fFlatDictionary(&fFlattenableHeap, fFactorySet) {
fController = controller; fController = controller;
fDone = false; fDone = false;
fBlockSize = 0; // need first block from controller fBlockSize = 0; // need first block from controller
@ -589,6 +623,7 @@ SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
SkGPipeCanvas::~SkGPipeCanvas() { SkGPipeCanvas::~SkGPipeCanvas() {
this->finish(); this->finish();
SkSafeUnref(fFactorySet);
} }
bool SkGPipeCanvas::needOpBytes(size_t needed) { bool SkGPipeCanvas::needOpBytes(size_t needed) {
@ -1196,7 +1231,7 @@ void SkGPipeCanvas::writePaint(const SkPaint& paint) {
} }
if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) { if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
if (SkToBool(fFlags & SkGPipeWriter::kCrossProcess_Flag)) { if (isCrossProcess(fFlags)) {
uint32_t id = this->getTypefaceID(paint.getTypeface()); uint32_t id = this->getTypefaceID(paint.getTypeface());
*ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id); *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
} else if (this->needOpBytes(sizeof(void*))) { } else if (this->needOpBytes(sizeof(void*))) {
@ -1255,23 +1290,18 @@ void SkGPipeController::setCanvas(SkGPipeCanvas* canvas) {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SkGPipeWriter::SkGPipeWriter() SkGPipeWriter::SkGPipeWriter()
: fFactorySet(SkNEW(SkFactorySet)) : fWriter(0) {
, fWriter(0) {
fCanvas = NULL; fCanvas = NULL;
} }
SkGPipeWriter::~SkGPipeWriter() { SkGPipeWriter::~SkGPipeWriter() {
this->endRecording(); this->endRecording();
fFactorySet->unref();
} }
SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) { SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) {
if (NULL == fCanvas) { if (NULL == fCanvas) {
fWriter.reset(NULL, 0); fWriter.reset(NULL, 0);
fFactorySet->reset(); fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter, flags));
fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
(flags & kCrossProcess_Flag) ?
fFactorySet : NULL, flags));
} }
controller->setCanvas(fCanvas); controller->setCanvas(fCanvas);
return fCanvas; return fCanvas;

85
tests/FlatDataTest.cpp Normal file
Просмотреть файл

@ -0,0 +1,85 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkColor.h"
#include "SkColorFilter.h"
#include "SkGradientShader.h"
#include "SkPaint.h"
#include "SkPictureFlat.h"
#include "SkShader.h"
#include "SkXfermode.h"
#include "Test.h"
static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer,
const void* obj) {
buffer.writeFlattenable((SkFlattenable*)obj);
}
/**
* Verify that two SkFlatData objects that created from the same object are
* identical when using an SkNamedFactorySet.
* @param reporter Object to report failures.
* @param obj Flattenable object to be flattened.
* @param flattenProc Function that flattens objects with the same type as obj.
*/
static void testCreate(skiatest::Reporter* reporter, const void* obj,
void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) {
SkChunkFlatController controller(1024);
SkNamedFactorySet factorySet;
// No need to delete data because that will be taken care of by the
// controller.
SkFlatData* data1 = SkFlatData::Create(&controller, obj, 0, flattenProc,
NULL, NULL, 0, &factorySet);
data1->setSentinelInCache();
SkFlatData* data2 = SkFlatData::Create(&controller, obj, 0, flattenProc,
NULL, NULL, 0, &factorySet);
data2->setSentinelAsCandidate();
REPORTER_ASSERT(reporter, SkFlatData::Compare(data1, data2) == 0);
}
static void Tests(skiatest::Reporter* reporter) {
// Test flattening SkShader
SkPoint points[2];
points[0].set(0, 0);
points[1].set(SkIntToScalar(20), SkIntToScalar(20));
SkColor colors[2];
colors[0] = SK_ColorRED;
colors[1] = SK_ColorBLUE;
SkShader* shader = SkGradientShader::CreateLinear(points, colors, NULL,
2, SkShader::kRepeat_TileMode);
SkAutoUnref aur(shader);
testCreate(reporter, shader, flattenFlattenableProc);
// Test SkBitmap
{
SkBitmap bm;
bm.setConfig(SkBitmap::kARGB_8888_Config, 50, 50);
bm.allocPixels();
SkCanvas canvas(bm);
SkPaint paint;
paint.setShader(shader);
canvas.drawPaint(paint);
testCreate(reporter, &bm, &SkFlattenObjectProc<SkBitmap>);
}
// Test SkColorFilter
SkColorFilter* cf = SkColorFilter::CreateLightingFilter(SK_ColorBLUE,
SK_ColorRED);
SkAutoUnref aurcf(cf);
testCreate(reporter, cf, &flattenFlattenableProc);
// Test SkXfermode
SkXfermode* xfer = SkXfermode::Create(SkXfermode::kDstOver_Mode);
SkAutoUnref aurxf(xfer);
testCreate(reporter, xfer, &flattenFlattenableProc);
}
#include "TestClassDef.h"
DEFINE_TESTCLASS("FlatData", FlatDataClass, Tests)