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:
commit-bot@chromium.org 2014-02-11 22:38:51 +00:00
parent 14747e58f8
commit 536ac5e20c
6 changed files with 89 additions and 41 deletions

View File

@ -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;
}

View File

@ -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;)
}
}

View File

@ -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;
}

View File

@ -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));
}

View File

@ -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) {

View File

@ -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) {