diff options
-rw-r--r-- | bench/WriterBench.cpp | 40 | ||||
-rw-r--r-- | gyp/bench.gypi | 1 | ||||
-rw-r--r-- | src/core/SkWriter32.cpp | 28 | ||||
-rw-r--r-- | tests/Writer32Test.cpp | 55 |
4 files changed, 111 insertions, 13 deletions
diff --git a/bench/WriterBench.cpp b/bench/WriterBench.cpp new file mode 100644 index 0000000000..2de653c374 --- /dev/null +++ b/bench/WriterBench.cpp @@ -0,0 +1,40 @@ + +/* + * Copyright 2012 The Android Open Source Project + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkBenchmark.h" +#include "SkCanvas.h" +#include "SkWriter32.h" + +class WriterBench : public SkBenchmark { +public: + WriterBench(void* param) : INHERITED(param) {} + +protected: + virtual const char* onGetName() SK_OVERRIDE { + return "writer"; + } + + virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE { + static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz"; + static const size_t gLen = strlen(gStr); + SkWriter32 writer(256 * 4); + for (int i = 0; i < SkBENCHLOOP(800); i++) { + for (size_t j = 0; j <= gLen; j++) { + writer.writeString(gStr, j); + } + } + } + +private: + typedef SkBenchmark INHERITED; +}; + +//////////////////////////////////////////////////////////////////////////////// + +static SkBenchmark* fact(void* p) { return new WriterBench(p); } +static BenchRegistry gReg(fact); diff --git a/gyp/bench.gypi b/gyp/bench.gypi index f809b6431e..e32db41117 100644 --- a/gyp/bench.gypi +++ b/gyp/bench.gypi @@ -34,6 +34,7 @@ '../bench/ShaderMaskBench.cpp', '../bench/TextBench.cpp', '../bench/VertBench.cpp', + '../bench/WriterBench.cpp', ], } diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp index 23f51b93fe..926a4303ec 100644 --- a/src/core/SkWriter32.cpp +++ b/src/core/SkWriter32.cpp @@ -180,13 +180,15 @@ void SkWriter32::flatten(void* dst) const { } void SkWriter32::writePad(const void* src, size_t size) { - size_t alignedSize = SkAlign4(size); - char* dst = (char*)this->reserve(alignedSize); - memcpy(dst, src, size); - dst += size; - int n = alignedSize - size; - while (--n >= 0) { - *dst++ = 0; + if (size > 0) { + size_t alignedSize = SkAlign4(size); + char* dst = (char*)this->reserve(alignedSize); + // Pad the last four bytes with zeroes in one step. Some (or all) will + // be overwritten by the memcpy. + uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4)); + *padding = 0; + // Copy the actual data. + memcpy(dst, src, size); } } @@ -279,13 +281,13 @@ void SkWriter32::writeString(const char str[], size_t len) { // add 1 since we also write a terminating 0 size_t alignedLen = SkAlign4(len + 1); char* ptr = (char*)this->reserve(alignedLen); - memcpy(ptr, str, len); - // Add the terminating 0, and pad the rest with 0s - ptr += len; - int n = alignedLen - len; - while (--n >= 0) { - *ptr++ = 0; + { + // 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); } size_t SkWriter32::WriteStringSize(const char* str, size_t len) { diff --git a/tests/Writer32Test.cpp b/tests/Writer32Test.cpp index 5c9d7ea58c..8b048a7b73 100644 --- a/tests/Writer32Test.cpp +++ b/tests/Writer32Test.cpp @@ -8,6 +8,7 @@ +#include "SkRandom.h" #include "SkReader32.h" #include "SkWriter32.h" #include "Test.h" @@ -86,6 +87,48 @@ static void test2(skiatest::Reporter* reporter, SkWriter32* writer) { REPORTER_ASSERT(reporter, reader.eof()); } +static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) { + // Create some random data to write. + const size_t dataSize = 10<<2; + SkASSERT(SkIsAlign4(dataSize)); + + SkAutoMalloc originalData(dataSize); + { + SkRandom rand(0); + uint32_t* ptr = static_cast<uint32_t*>(originalData.get()); + uint32_t* stop = ptr + (dataSize>>2); + while (ptr < stop) { + *ptr++ = rand.nextU(); + } + + // Write the random data to the writer at different lengths for + // different alignments. + for (size_t len = 0; len < dataSize; len++) { + writer->writePad(originalData.get(), len); + } + } + + uint32_t totalBytes = writer->size(); + + SkAutoMalloc readStorage(totalBytes); + writer->flatten(readStorage.get()); + + SkReader32 reader; + reader.setMemory(readStorage.get(), totalBytes); + + for (size_t len = 0; len < dataSize; len++) { + const char* readPtr = static_cast<const char*>(reader.skip(len)); + // Ensure that the data read is the same as what was written. + REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0); + // Ensure that the rest is padded with zeroes. + const char* stop = readPtr + SkAlign4(len); + readPtr += len; + while (readPtr < stop) { + REPORTER_ASSERT(reporter, *readPtr++ == 0); + } + } +} + static void Tests(skiatest::Reporter* reporter) { // dynamic allocator { @@ -95,6 +138,9 @@ static void Tests(skiatest::Reporter* reporter) { writer.reset(); test2(reporter, &writer); + + writer.reset(); + testWritePad(reporter, &writer); } // single-block @@ -108,6 +154,9 @@ static void Tests(skiatest::Reporter* reporter) { writer.reset(storage, sizeof(storage)); test2(reporter, &writer); + + writer.reset(storage, sizeof(storage)); + testWritePad(reporter, &writer); } // small storage @@ -116,6 +165,9 @@ static void Tests(skiatest::Reporter* reporter) { test1(reporter, &writer); writer.reset(); // should just rewind our storage test2(reporter, &writer); + + writer.reset(); + testWritePad(reporter, &writer); } // large storage @@ -124,6 +176,9 @@ static void Tests(skiatest::Reporter* reporter) { test1(reporter, &writer); writer.reset(); // should just rewind our storage test2(reporter, &writer); + + writer.reset(); + testWritePad(reporter, &writer); } test_ptr(reporter); |