Add SkChunkAlloc::unalloc() to undo the last allocation, useful if the caller wants to treat the allocats like temp memory (see PictureRecord)

Call unalloc if a paint (or other cached object) is already in our list for picture recording
Use correct CompareType macro in SkCanvas::quickReject



git-svn-id: http://skia.googlecode.com/svn/trunk@138 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@android.com 2009-03-30 21:02:14 +00:00
parent f459a4949d
commit aefd2bc757
7 changed files with 185 additions and 49 deletions

View File

@ -46,6 +46,14 @@ public:
return this->alloc(bytes, kThrow_AllocFailType);
}
/** Call this to unalloc the most-recently allocated ptr by alloc(). On
success, the number of bytes freed is returned, or 0 if the block could
not be unallocated. This is a hint to the underlying allocator that
the previous allocation may be reused, but the implementation is free
to ignore this call (and return 0).
*/
size_t unalloc(void* ptr);
size_t totalCapacity() const { return fTotalCapacity; }
private:

View File

@ -299,12 +299,12 @@ void SampleWindow::afterChildren(SkCanvas* orig) {
case kRaster_CanvasType:
break;
case kPicture_CanvasType:
if (false) {
if (true) {
SkPicture* pict = new SkPicture(*fPicture);
fPicture->unref();
orig->drawPicture(*pict);
pict->unref();
} if (true) {
} else if (true) {
SkDynamicMemoryWStream ostream;
fPicture->serialize(&ostream);
fPicture->unref();

View File

@ -943,8 +943,8 @@ bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
return true;
}
SkScalarCompareType userT = SkScalarAs2sCompliment(top);
SkScalarCompareType userB = SkScalarAs2sCompliment(bottom);
SkScalarCompareType userT = SkScalarToCompareType(top);
SkScalarCompareType userB = SkScalarToCompareType(bottom);
// check for invalid user Y coordinates (i.e. empty)
if (userT >= userB) {

View File

@ -23,6 +23,10 @@ struct SkChunkAlloc::Block {
char* fFreePtr;
// data[] follows
char* startOfData() {
return reinterpret_cast<char*>(this + 1);
}
void freeChain() { // this can be null
Block* block = this;
while (block) {
@ -89,7 +93,7 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
if (block) {
// block->fNext = fBlock;
block->fFreeSize = size;
block->fFreePtr = (char*)block + sizeof(Block);
block->fFreePtr = block->startOfData();
fTotalCapacity += size;
}
@ -118,3 +122,18 @@ void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
return ptr;
}
size_t SkChunkAlloc::unalloc(void* ptr) {
size_t bytes = 0;
Block* block = fBlock;
if (block) {
char* cPtr = reinterpret_cast<char*>(ptr);
char* start = block->startOfData();
if (start <= cPtr && cPtr < block->fFreePtr) {
bytes = block->fFreePtr - cPtr;
block->fFreeSize += bytes;
block->fFreePtr = cPtr;
}
}
return bytes;
}

View File

@ -1278,50 +1278,143 @@ SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
#include "SkStream.h"
static uintptr_t asint(const void* p) {
return reinterpret_cast<uintptr_t>(p);
}
union Scalar32 {
SkScalar fScalar;
uint32_t f32;
};
static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
Scalar32 tmp;
tmp.fScalar = value;
*ptr = tmp.f32;
return ptr + 1;
}
static SkScalar read_scalar(const uint32_t*& ptr) {
SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
Scalar32 tmp;
tmp.f32 = *ptr++;
return tmp.fScalar;
}
static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
SkASSERT(a == (uint8_t)a);
SkASSERT(b == (uint8_t)b);
SkASSERT(c == (uint8_t)c);
SkASSERT(d == (uint8_t)d);
return (a << 24) | (b << 16) | (c << 8) | d;
}
enum FlatFlags {
kHasTypeface_FlatFlag = 0x01,
kHasEffects_FlatFlag = 0x02
};
// The size of a flat paint's POD fields
static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
1 * sizeof(SkColor) +
1 * sizeof(uint16_t) +
6 * sizeof(uint8_t);
/* To save space/time, we analyze the paint, and write a truncated version of
it if there are not tricky elements like shaders, etc.
*/
void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
buffer.writeTypeface(this->getTypeface());
buffer.writeScalar(this->getTextSize());
buffer.writeScalar(this->getTextScaleX());
buffer.writeScalar(this->getTextSkewX());
buffer.writeFlattenable(this->getPathEffect());
buffer.writeFlattenable(this->getShader());
buffer.writeFlattenable(this->getXfermode());
buffer.writeFlattenable(this->getMaskFilter());
buffer.writeFlattenable(this->getColorFilter());
buffer.writeFlattenable(this->getRasterizer());
buffer.writeFlattenable(this->getLooper());
buffer.write32(this->getColor());
buffer.writeScalar(this->getStrokeWidth());
buffer.writeScalar(this->getStrokeMiter());
buffer.write16(this->getFlags());
buffer.write8(this->getTextAlign());
buffer.write8(this->getStrokeCap());
buffer.write8(this->getStrokeJoin());
buffer.write8(this->getStyle());
buffer.write8(this->getTextEncoding());
uint8_t flatFlags = 0;
if (this->getTypeface()) {
flatFlags |= kHasTypeface_FlatFlag;
}
if (asint(this->getPathEffect()) |
asint(this->getShader()) |
asint(this->getXfermode()) |
asint(this->getMaskFilter()) |
asint(this->getColorFilter()) |
asint(this->getRasterizer()) |
asint(this->getLooper())) {
flatFlags |= kHasEffects_FlatFlag;
}
SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
uint32_t* ptr = buffer.reserve(kPODPaintSize);
ptr = write_scalar(ptr, this->getTextSize());
ptr = write_scalar(ptr, this->getTextScaleX());
ptr = write_scalar(ptr, this->getTextSkewX());
ptr = write_scalar(ptr, this->getStrokeWidth());
ptr = write_scalar(ptr, this->getStrokeMiter());
*ptr++ = this->getColor();
*ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
*ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
this->getStyle(), this->getTextEncoding());
// now we're done with ptr and the (pre)reserved space. If we need to write
// additional fields, use the buffer directly
if (flatFlags & kHasTypeface_FlatFlag) {
buffer.writeTypeface(this->getTypeface());
}
if (flatFlags & kHasEffects_FlatFlag) {
buffer.writeFlattenable(this->getPathEffect());
buffer.writeFlattenable(this->getShader());
buffer.writeFlattenable(this->getXfermode());
buffer.writeFlattenable(this->getMaskFilter());
buffer.writeFlattenable(this->getColorFilter());
buffer.writeFlattenable(this->getRasterizer());
buffer.writeFlattenable(this->getLooper());
}
}
void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
this->setTypeface(buffer.readTypeface());
this->setTextSize(buffer.readScalar());
this->setTextScaleX(buffer.readScalar());
this->setTextSkewX(buffer.readScalar());
this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
this->setColor(buffer.readU32());
this->setStrokeWidth(buffer.readScalar());
this->setStrokeMiter(buffer.readScalar());
this->setFlags(buffer.readU16());
this->setTextAlign((SkPaint::Align) buffer.readU8());
this->setStrokeCap((SkPaint::Cap) buffer.readU8());
this->setStrokeJoin((SkPaint::Join) buffer.readU8());
this->setStyle((SkPaint::Style) buffer.readU8());
this->setTextEncoding((SkPaint::TextEncoding) buffer.readU8());
SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
const void* podData = buffer.skip(kPODPaintSize);
const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
// the order we read must match the order we wrote in flatten()
this->setTextSize(read_scalar(pod));
this->setTextScaleX(read_scalar(pod));
this->setTextSkewX(read_scalar(pod));
this->setStrokeWidth(read_scalar(pod));
this->setStrokeMiter(read_scalar(pod));
this->setColor(*pod++);
uint32_t tmp = *pod++;
this->setFlags(tmp >> 16);
this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
uint8_t flatFlags = tmp & 0xFF;
tmp = *pod++;
this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
if (flatFlags & kHasTypeface_FlatFlag) {
this->setTypeface(buffer.readTypeface());
} else {
this->setTypeface(NULL);
}
if (flatFlags & kHasEffects_FlatFlag) {
this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
} else {
this->setPathEffect(NULL);
this->setShader(NULL);
this->setXfermode(NULL);
this->setMaskFilter(NULL);
this->setColorFilter(NULL);
this->setRasterizer(NULL);
this->setLooper(NULL);
}
}
///////////////////////////////////////////////////////////////////////////////

View File

@ -514,8 +514,7 @@ int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitm
int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
if (index >= 0) {
// SkBitmap bitmap;
// flat->unflatten(&bitmap); // balance ref count
(void)fHeap.unalloc(flat);
return bitmaps[index]->index();
}
index = ~index;
@ -529,8 +528,10 @@ int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMat
SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
if (index >= 0)
if (index >= 0) {
(void)fHeap.unalloc(flat);
return matrices[index]->index();
}
index = ~index;
*matrices.insert(index) = flat;
return fMatrixIndex++;
@ -546,6 +547,7 @@ int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint*
int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
if (index >= 0) {
(void)fHeap.unalloc(flat);
return paints[index]->index();
}
@ -558,8 +560,10 @@ int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegi
SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
if (index >= 0)
if (index >= 0) {
(void)fHeap.unalloc(flat);
return regions[index]->index();
}
index = ~index;
*regions.insert(index) = flat;
return fRegionIndex++;

View File

@ -68,6 +68,8 @@
008C4D980F77DAEE0056981C /* SampleHairline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008C4D970F77DAEE0056981C /* SampleHairline.cpp */; };
009CC9190F65918A002185BE /* SampleFontScalerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */; };
00A41E4B0EFC312F00C9CBEB /* SampleArc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A41E4A0EFC312F00C9CBEB /* SampleArc.cpp */; };
00FACE3C0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */; };
00FACE680F7D23DD00F8A7FF /* SkWriter32_largeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */; };
0156F80407C56A3000C6122B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0156F80307C56A3000C6122B /* Foundation.framework */; };
01FC44D507BD3BB800D228F4 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01FC44D407BD3BB800D228F4 /* Quartz.framework */; };
8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
@ -184,6 +186,10 @@
009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFontScalerTest.cpp; path = ../../samplecode/SampleFontScalerTest.cpp; sourceTree = SOURCE_ROOT; };
00A41E4A0EFC312F00C9CBEB /* SampleArc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleArc.cpp; path = ../../samplecode/SampleArc.cpp; sourceTree = SOURCE_ROOT; };
00D6B5CB0F72DC4300C466B9 /* SampleFuzz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFuzz.cpp; path = ../../samplecode/SampleFuzz.cpp; sourceTree = SOURCE_ROOT; };
00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLargeBlock_malloc.cpp; path = ../../src/utils/SkLargeBlock_malloc.cpp; sourceTree = SOURCE_ROOT; };
00FACE3F0F7D167400F8A7FF /* SkLargeBlock_remap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLargeBlock_remap.cpp; path = ../../src/utils/SkLargeBlock_remap.cpp; sourceTree = SOURCE_ROOT; };
00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkWriter32_largeBlock.cpp; path = ../../src/utils/SkWriter32_largeBlock.cpp; sourceTree = SOURCE_ROOT; };
00FACE600F7D22CF00F8A7FF /* SkWriter32_noLargeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkWriter32_noLargeBlock.cpp; path = ../../src/utils/SkWriter32_noLargeBlock.cpp; sourceTree = SOURCE_ROOT; };
0156F80307C56A3000C6122B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
01FC44D407BD3BB800D228F4 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = /System/Library/Frameworks/Quartz.framework; sourceTree = "<absolute>"; };
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@ -331,6 +337,10 @@
002884490EFAA35C0083E387 /* core.xcodeproj */,
002884B40EFAB69F0083E387 /* maccore.xcodeproj */,
00003C8C0EFC230E000FF73A /* effects.xcodeproj */,
00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */,
00FACE3F0F7D167400F8A7FF /* SkLargeBlock_remap.cpp */,
00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */,
00FACE600F7D22CF00F8A7FF /* SkWriter32_noLargeBlock.cpp */,
);
name = CICarbonSample;
sourceTree = "<group>";
@ -519,6 +529,8 @@
007A7CB30F01658C00A2D6EE /* SamplePicture.cpp in Sources */,
0041CE440F00A12400695E8C /* SampleLines.cpp in Sources */,
008C4D980F77DAEE0056981C /* SampleHairline.cpp in Sources */,
00FACE3C0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp in Sources */,
00FACE680F7D23DD00F8A7FF /* SkWriter32_largeBlock.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};