Templetized SkWriter32 readTAt() & overwriteTAt()
Convert SkWriter32::{read,write}32At() to ::{read,overwrite}TAt<>() to allow peeking/updating arbitrary records. BUG=skia: R=mtklein@google.com, reed@google.com, robertphillips@google.com, iancottrell@chromium.org Author: fmalita@chromium.org Review URL: https://codereview.chromium.org/130913018 git-svn-id: http://skia.googlecode.com/svn/trunk@13416 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
14747e58f8
commit
536ac5e20c
@ -73,17 +73,26 @@ public:
|
||||
return (uint32_t*)(fData + offset);
|
||||
}
|
||||
|
||||
// Read or write 4 bytes at offset, which must be a multiple of 4 <= size().
|
||||
uint32_t read32At(size_t offset) {
|
||||
/**
|
||||
* Read a T record at offset, which must be a multiple of 4. Only legal if the record
|
||||
* was writtern atomically using the write methods below.
|
||||
*/
|
||||
template<typename T>
|
||||
const T& readTAt(size_t offset) const {
|
||||
SkASSERT(SkAlign4(offset) == offset);
|
||||
SkASSERT(offset < fUsed);
|
||||
return *(uint32_t*)(fData + offset);
|
||||
return *(T*)(fData + offset);
|
||||
}
|
||||
|
||||
void write32At(size_t offset, uint32_t val) {
|
||||
/**
|
||||
* Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record
|
||||
* was writtern atomically using the write methods below.
|
||||
*/
|
||||
template<typename T>
|
||||
void overwriteTAt(size_t offset, const T& value) {
|
||||
SkASSERT(SkAlign4(offset) == offset);
|
||||
SkASSERT(offset < fUsed);
|
||||
*(uint32_t*)(fData + offset) = val;
|
||||
*(T*)(fData + offset) = value;
|
||||
}
|
||||
|
||||
bool writeBool(bool value) {
|
||||
@ -168,14 +177,11 @@ public:
|
||||
* filled in with zeroes.
|
||||
*/
|
||||
uint32_t* reservePad(size_t size) {
|
||||
uint32_t* p = this->reserve(SkAlign4(size));
|
||||
uint8_t* tail = (uint8_t*)p + size;
|
||||
switch (SkAlign4(size) - size) {
|
||||
default: SkDEBUGFAIL("SkAlign4(x) - x should always be 0, 1, 2, or 3.");
|
||||
case 3: *tail++ = 0x00; // fallthrough is intentional
|
||||
case 2: *tail++ = 0x00; // fallthrough is intentional
|
||||
case 1: *tail++ = 0x00;
|
||||
case 0: ;/*nothing to do*/
|
||||
size_t alignedSize = SkAlign4(size);
|
||||
uint32_t* p = this->reserve(alignedSize);
|
||||
if (alignedSize != size) {
|
||||
SkASSERT(alignedSize >= 4);
|
||||
p[alignedSize / 4 - 1] = 0;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
@ -106,7 +106,7 @@ void SkMatrixClipStateMgr::MatrixClipState::ClipInfo::fillInSkips(SkWriter32* wr
|
||||
}
|
||||
// SkDEBUGCODE(uint32_t peek = writer->read32At(curClip.fOffset);)
|
||||
// SkASSERT(-1 == peek);
|
||||
writer->write32At(curClip.fOffset, restoreOffset);
|
||||
writer->overwriteTAt(curClip.fOffset, restoreOffset);
|
||||
SkDEBUGCODE(curClip.fOffset = -1;)
|
||||
}
|
||||
}
|
||||
|
@ -226,13 +226,13 @@ bool SkPictureRecord::isDrawingToLayer() const {
|
||||
* Read the op code from 'offset' in 'writer' and extract the size too.
|
||||
*/
|
||||
static DrawType peek_op_and_size(SkWriter32* writer, int32_t offset, uint32_t* size) {
|
||||
uint32_t peek = writer->read32At(offset);
|
||||
uint32_t peek = writer->readTAt<uint32_t>(offset);
|
||||
|
||||
uint32_t op;
|
||||
UNPACK_8_24(peek, op, *size);
|
||||
if (MASK_24 == *size) {
|
||||
// size required its own slot right after the op code
|
||||
*size = writer->read32At(offset+kUInt32Size);
|
||||
*size = writer->readTAt<uint32_t>(offset + kUInt32Size);
|
||||
}
|
||||
return (DrawType) op;
|
||||
}
|
||||
@ -335,7 +335,7 @@ static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
|
||||
// back up to the save block
|
||||
// TODO: add a stack to track save*/restore offsets rather than searching backwards
|
||||
while (offset > 0) {
|
||||
offset = writer->read32At(offset);
|
||||
offset = writer->readTAt<uint32_t>(offset);
|
||||
}
|
||||
|
||||
int pattern[] = { SAVE_LAYER, kDRAW_BITMAP_FLAVOR, /* RESTORE */ };
|
||||
@ -359,8 +359,8 @@ static bool remove_save_layer1(SkWriter32* writer, int32_t offset,
|
||||
* field alone so the NOOP can be skipped later.
|
||||
*/
|
||||
static void convert_command_to_noop(SkWriter32* writer, uint32_t offset) {
|
||||
uint32_t command = writer->read32At(offset);
|
||||
writer->write32At(offset, (command & MASK_24) | (NOOP << 24));
|
||||
uint32_t command = writer->readTAt<uint32_t>(offset);
|
||||
writer->overwriteTAt(offset, (command & MASK_24) | (NOOP << 24));
|
||||
}
|
||||
|
||||
/*
|
||||
@ -381,8 +381,8 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
|
||||
uint32_t slPaintOffset = getPaintOffset(SAVE_LAYER, saveLayerInfo.fSize);
|
||||
|
||||
// we have a match, now we need to get the paints involved
|
||||
uint32_t dbmPaintId = writer->read32At(dbmInfo.fOffset+dbmPaintOffset);
|
||||
uint32_t saveLayerPaintId = writer->read32At(saveLayerInfo.fOffset+slPaintOffset);
|
||||
uint32_t dbmPaintId = writer->readTAt<uint32_t>(dbmInfo.fOffset + dbmPaintOffset);
|
||||
uint32_t saveLayerPaintId = writer->readTAt<uint32_t>(saveLayerInfo.fOffset + slPaintOffset);
|
||||
|
||||
if (0 == saveLayerPaintId) {
|
||||
// In this case the saveLayer/restore isn't needed at all - just kill the saveLayer
|
||||
@ -395,7 +395,7 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
|
||||
// In this case just make the DBM* use the saveLayer's paint, kill the saveLayer
|
||||
// and signal the caller (by returning true) to not add the RESTORE op
|
||||
convert_command_to_noop(writer, saveLayerInfo.fOffset);
|
||||
writer->write32At(dbmInfo.fOffset+dbmPaintOffset, saveLayerPaintId);
|
||||
writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, saveLayerPaintId);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -428,7 +428,7 @@ static bool merge_savelayer_paint_into_drawbitmp(SkWriter32* writer,
|
||||
|
||||
// kill the saveLayer and alter the DBMR2R's paint to be the modified one
|
||||
convert_command_to_noop(writer, saveLayerInfo.fOffset);
|
||||
writer->write32At(dbmInfo.fOffset+dbmPaintOffset, data->index());
|
||||
writer->overwriteTAt(dbmInfo.fOffset + dbmPaintOffset, data->index());
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -449,7 +449,7 @@ static bool remove_save_layer2(SkWriter32* writer, int32_t offset,
|
||||
// back up to the save block
|
||||
// TODO: add a stack to track save*/restore offsets rather than searching backwards
|
||||
while (offset > 0) {
|
||||
offset = writer->read32At(offset);
|
||||
offset = writer->readTAt<uint32_t>(offset);
|
||||
}
|
||||
|
||||
int pattern[] = { SAVE_LAYER, SAVE, CLIP_RECT, kDRAW_BITMAP_FLAVOR, RESTORE, /* RESTORE */ };
|
||||
@ -486,7 +486,7 @@ static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
|
||||
|
||||
// back up to the save block
|
||||
while (offset > 0) {
|
||||
offset = writer->read32At(offset);
|
||||
offset = writer->readTAt<uint32_t>(offset);
|
||||
}
|
||||
|
||||
// now offset points to a save
|
||||
@ -501,7 +501,7 @@ static bool collapse_save_clip_restore(SkWriter32* writer, int32_t offset,
|
||||
SkASSERT(kSaveSize == opSize);
|
||||
|
||||
// get the save flag (last 4-bytes of the space allocated for the opSize)
|
||||
SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->read32At(offset+4);
|
||||
SkCanvas::SaveFlags saveFlags = (SkCanvas::SaveFlags) writer->readTAt<uint32_t>(offset + 4);
|
||||
if (SkCanvas::kMatrixClip_SaveFlag != saveFlags) {
|
||||
// This function's optimization is only correct for kMatrixClip style saves.
|
||||
// TODO: set checkMatrix & checkClip booleans here and then check for the
|
||||
@ -769,8 +769,8 @@ void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t
|
||||
void SkPictureRecord::fillRestoreOffsetPlaceholdersForCurrentStackLevel(uint32_t restoreOffset) {
|
||||
int32_t offset = fRestoreOffsetStack.top();
|
||||
while (offset > 0) {
|
||||
uint32_t peek = fWriter.read32At(offset);
|
||||
fWriter.write32At(offset, restoreOffset);
|
||||
uint32_t peek = fWriter.readTAt<uint32_t>(offset);
|
||||
fWriter.overwriteTAt(offset, restoreOffset);
|
||||
offset = peek;
|
||||
}
|
||||
|
||||
|
@ -321,5 +321,5 @@ void SkWriteBuffer::writeFlattenable(const SkFlattenable* flattenable) {
|
||||
flattenable->flatten(*this);
|
||||
size_t objSize = fWriter.bytesWritten() - offset;
|
||||
// record the obj's size
|
||||
fWriter.write32At(offset - sizeof(uint32_t), SkToU32(objSize));
|
||||
fWriter.overwriteTAt(offset - sizeof(uint32_t), SkToU32(objSize));
|
||||
}
|
||||
|
@ -44,17 +44,13 @@ void SkWriter32::writeString(const char str[], size_t len) {
|
||||
if ((long)len < 0) {
|
||||
len = strlen(str);
|
||||
}
|
||||
this->write32(len);
|
||||
// add 1 since we also write a terminating 0
|
||||
size_t alignedLen = SkAlign4(len + 1);
|
||||
char* ptr = (char*)this->reserve(alignedLen);
|
||||
{
|
||||
// Write the terminating 0 and fill in the rest with zeroes
|
||||
uint32_t* padding = (uint32_t*)(ptr + (alignedLen - 4));
|
||||
*padding = 0;
|
||||
}
|
||||
// Copy the string itself.
|
||||
memcpy(ptr, str, len);
|
||||
|
||||
// [ 4 byte len ] [ str ... ] [1 - 4 \0s]
|
||||
uint32_t* ptr = this->reservePad(sizeof(uint32_t) + len + 1);
|
||||
*ptr = len;
|
||||
char* chars = (char*)(ptr + 1);
|
||||
memcpy(chars, str, len);
|
||||
chars[len] = '\0';
|
||||
}
|
||||
|
||||
size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
|
||||
|
@ -102,7 +102,7 @@ static void test1(skiatest::Reporter* reporter, SkWriter32* writer) {
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(data); ++i) {
|
||||
REPORTER_ASSERT(reporter, i*4 == writer->bytesWritten());
|
||||
writer->write32(data[i]);
|
||||
REPORTER_ASSERT(reporter, data[i] == writer->read32At(i*4));
|
||||
REPORTER_ASSERT(reporter, data[i] == writer->readTAt<uint32_t>(i * 4));
|
||||
}
|
||||
|
||||
char buffer[sizeof(data)];
|
||||
@ -184,6 +184,43 @@ static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) {
|
||||
}
|
||||
}
|
||||
|
||||
static void testOverwriteT(skiatest::Reporter* reporter, SkWriter32* writer) {
|
||||
const size_t padding = 64;
|
||||
|
||||
const uint32_t uint1 = 0x12345678;
|
||||
const uint32_t uint2 = 0x98765432;
|
||||
const SkScalar scalar1 = 1234.5678f;
|
||||
const SkScalar scalar2 = 9876.5432f;
|
||||
const SkRect rect1 = SkRect::MakeXYWH(1, 2, 3, 4);
|
||||
const SkRect rect2 = SkRect::MakeXYWH(5, 6, 7, 8);
|
||||
|
||||
for (size_t i = 0; i < (padding / 4); ++i) {
|
||||
writer->write32(0);
|
||||
}
|
||||
|
||||
writer->write32(uint1);
|
||||
writer->writeRect(rect1);
|
||||
writer->writeScalar(scalar1);
|
||||
|
||||
for (size_t i = 0; i < (padding / 4); ++i) {
|
||||
writer->write32(0);
|
||||
}
|
||||
|
||||
REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint1);
|
||||
REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect1);
|
||||
REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>(
|
||||
padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar1);
|
||||
|
||||
writer->overwriteTAt(padding, uint2);
|
||||
writer->overwriteTAt(padding + sizeof(uint32_t), rect2);
|
||||
writer->overwriteTAt(padding + sizeof(uint32_t) + sizeof(SkRect), scalar2);
|
||||
|
||||
REPORTER_ASSERT(reporter, writer->readTAt<uint32_t>(padding) == uint2);
|
||||
REPORTER_ASSERT(reporter, writer->readTAt<SkRect>(padding + sizeof(uint32_t)) == rect2);
|
||||
REPORTER_ASSERT(reporter, writer->readTAt<SkScalar>(
|
||||
padding + sizeof(uint32_t) + sizeof(SkRect)) == scalar2);
|
||||
}
|
||||
|
||||
DEF_TEST(Writer32_dynamic, reporter) {
|
||||
SkWriter32 writer;
|
||||
test1(reporter, &writer);
|
||||
@ -193,6 +230,9 @@ DEF_TEST(Writer32_dynamic, reporter) {
|
||||
|
||||
writer.reset();
|
||||
testWritePad(reporter, &writer);
|
||||
|
||||
writer.reset();
|
||||
testOverwriteT(reporter, &writer);
|
||||
}
|
||||
|
||||
DEF_TEST(Writer32_contiguous, reporter) {
|
||||
@ -216,6 +256,9 @@ DEF_TEST(Writer32_small, reporter) {
|
||||
|
||||
writer.reset();
|
||||
testWritePad(reporter, &writer);
|
||||
|
||||
writer.reset();
|
||||
testOverwriteT(reporter, &writer);
|
||||
}
|
||||
|
||||
DEF_TEST(Writer32_large, reporter) {
|
||||
@ -226,6 +269,9 @@ DEF_TEST(Writer32_large, reporter) {
|
||||
|
||||
writer.reset();
|
||||
testWritePad(reporter, &writer);
|
||||
|
||||
writer.reset();
|
||||
testOverwriteT(reporter, &writer);
|
||||
}
|
||||
|
||||
DEF_TEST(Writer32_misc, reporter) {
|
||||
|
Loading…
Reference in New Issue
Block a user