From 07adb6359fd137ccb633b2c64ee2287c8edfd701 Mon Sep 17 00:00:00 2001 From: "commit-bot@chromium.org" Date: Thu, 2 Jan 2014 22:20:49 +0000 Subject: [PATCH] Function pointers -> templates in SkPictureFlat. These flatten/unflatten function pointers were driving me nuts when reading the generated assembly for this code. We don't need the flexibility of function pointers here, so let's use templates to make it more manageable. You'll notice we get much better typing now on flatten/unflatten. BUG= R=reed@google.com Author: mtklein@google.com Review URL: https://codereview.chromium.org/123213004 git-svn-id: http://skia.googlecode.com/svn/trunk@12873 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkPictureFlat.cpp | 48 ---------- src/core/SkPictureFlat.h | 157 +++++++++++++++++---------------- src/core/SkPicturePlayback.cpp | 12 +-- src/pipe/SkGPipeWrite.cpp | 17 ++-- tests/BitmapHeapTest.cpp | 14 +-- tests/FlatDataTest.cpp | 46 +++++----- 6 files changed, 119 insertions(+), 175 deletions(-) diff --git a/src/core/SkPictureFlat.cpp b/src/core/SkPictureFlat.cpp index 149cf7cc02..e75023e0f6 100644 --- a/src/core/SkPictureFlat.cpp +++ b/src/core/SkPictureFlat.cpp @@ -90,51 +90,3 @@ SkNamedFactorySet* SkFlatController::setNamedFactorySet(SkNamedFactorySet* set) return set; } -/////////////////////////////////////////////////////////////////////////////// - -SkFlatData* SkFlatData::Create(SkFlatController* controller, - const void* obj, - int index, - void (*flattenProc)(SkOrderedWriteBuffer&, const void*)) { - // a buffer of 256 bytes should be sufficient for most paints, regions, - // and matrices. - intptr_t storage[256]; - SkOrderedWriteBuffer buffer(256, storage, sizeof(storage)); - - buffer.setBitmapHeap(controller->getBitmapHeap()); - buffer.setTypefaceRecorder(controller->getTypefaceSet()); - buffer.setNamedFactoryRecorder(controller->getNamedFactorySet()); - buffer.setFlags(controller->getWriteBufferFlags()); - - flattenProc(buffer, obj); - uint32_t size = buffer.size(); - SkASSERT(SkIsAlign4(size)); - - // Allocate enough memory to hold SkFlatData struct and the flat data itself. - size_t allocSize = sizeof(SkFlatData) + size; - SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize); - - // Put the serialized contents into the data section of the new allocation. - buffer.writeToMemory(result->data()); - // Stamp the index, size and checksum in the header. - result->stampHeader(index, size); - return result; -} - -void SkFlatData::unflatten(void* result, - void (*unflattenProc)(SkOrderedReadBuffer&, void*), - SkBitmapHeap* bitmapHeap, - SkTypefacePlayback* facePlayback) const { - - SkOrderedReadBuffer buffer(this->data(), fFlatSize); - - if (bitmapHeap) { - buffer.setBitmapStorage(bitmapHeap); - } - if (facePlayback) { - facePlayback->setupBuffer(buffer); - } - - unflattenProc(buffer, result); - SkASSERT(fFlatSize == (int32_t)buffer.offset()); -} diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h index 5452501c43..220ae11c0e 100644 --- a/src/core/SkPictureFlat.h +++ b/src/core/SkPictureFlat.h @@ -267,16 +267,49 @@ private: class SkFlatData { public: // Flatten obj into an SkFlatData with this index. controller owns the SkFlatData*. - static SkFlatData* Create(SkFlatController* controller, - const void* obj, - int index, - void (*flattenProc)(SkOrderedWriteBuffer&, const void*)); + template + static SkFlatData* Create(SkFlatController* controller, const T& obj, int index) { + // A buffer of 256 bytes should fit most paints, regions, and matrices. + uint32_t storage[64]; + SkOrderedWriteBuffer buffer(256, storage, sizeof(storage)); - // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given. - void unflatten(void* result, - void (*unflattenProc)(SkOrderedReadBuffer&, void*), + buffer.setBitmapHeap(controller->getBitmapHeap()); + buffer.setTypefaceRecorder(controller->getTypefaceSet()); + buffer.setNamedFactoryRecorder(controller->getNamedFactorySet()); + buffer.setFlags(controller->getWriteBufferFlags()); + + Traits::flatten(buffer, obj); + uint32_t size = buffer.size(); + SkASSERT(SkIsAlign4(size)); + + // Allocate enough memory to hold SkFlatData struct and the flat data itself. + size_t allocSize = sizeof(SkFlatData) + size; + SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize); + + // Put the serialized contents into the data section of the new allocation. + buffer.writeToMemory(result->data()); + // Stamp the index, size and checksum in the header. + result->stampHeader(index, size); + return result; + } + + // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given + template + void unflatten(T* result, SkBitmapHeap* bitmapHeap = NULL, - SkTypefacePlayback* facePlayback = NULL) const; + SkTypefacePlayback* facePlayback = NULL) const { + SkOrderedReadBuffer buffer(this->data(), fFlatSize); + + if (bitmapHeap) { + buffer.setBitmapStorage(bitmapHeap); + } + if (facePlayback) { + facePlayback->setupBuffer(buffer); + } + + Traits::unflatten(buffer, result); + SkASSERT(fFlatSize == (int32_t)buffer.offset()); + } // Do these contain the same data? Ignores index() and topBot(). bool operator==(const SkFlatData& that) const { @@ -333,19 +366,17 @@ private: mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts as [NaN,?]. // uint32_t flattenedData[] implicitly hangs off the end. - template friend class SkFlatDictionary; + template friend class SkFlatDictionary; }; -template +template class SkFlatDictionary { static const size_t kWriteBufferGrowthBytes = 1024; public: - SkFlatDictionary(SkFlatController* controller, size_t scratchSizeGuess = 0) - : fFlattenProc(NULL) - , fUnflattenProc(NULL) - , fController(SkRef(controller)) - , fScratchSize(scratchSizeGuess) + explicit SkFlatDictionary(SkFlatController* controller) + : fController(SkRef(controller)) + , fScratchSize(kScratchSizeGuess) , fScratch(AllocScratch(fScratchSize)) , fWriteBuffer(kWriteBufferGrowthBytes) , fWriteBufferReady(false) { @@ -471,10 +502,6 @@ public: return this->findAndReturnMutableFlat(element); } -protected: - void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*); - void (*fUnflattenProc)(SkOrderedReadBuffer&, void*); - private: // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ] static size_t SizeWithPadding(size_t flatDataSize) { @@ -523,7 +550,7 @@ private: // Flatten element into fWriteBuffer (using fScratch as storage). fWriteBuffer.reset(fScratch->data(), fScratchSize); - fFlattenProc(fWriteBuffer, &element); + Traits::flatten(fWriteBuffer, element); const size_t bytesWritten = fWriteBuffer.bytesWritten(); // If all the flattened bytes fit into fScratch, we can skip a call to writeToMemory. @@ -561,10 +588,9 @@ private: } void unflatten(T* dst, const SkFlatData* element) const { - element->unflatten(dst, - fUnflattenProc, - fController->getBitmapHeap(), - fController->getTypefacePlayback()); + element->unflatten(dst, + fController->getBitmapHeap(), + fController->getTypefacePlayback()); } // All SkFlatData* stored in fIndexedData and fHash are owned by the controller. @@ -589,15 +615,37 @@ private: // Some common dictionaries are defined here for both reference and convenience /////////////////////////////////////////////////////////////////////////////// -template -static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) { - ((T*)obj)->flatten(buffer); -} +struct SkMatrixTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkMatrix& matrix) { + buffer.getWriter32()->writeMatrix(matrix); + } + static void unflatten(SkOrderedReadBuffer& buffer, SkMatrix* matrix) { + buffer.getReader32()->readMatrix(matrix); + } +}; +typedef SkFlatDictionary SkMatrixDictionary; -template -static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) { - ((T*)obj)->unflatten(buffer); -} + +struct SkRegionTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkRegion& region) { + buffer.getWriter32()->writeRegion(region); + } + static void unflatten(SkOrderedReadBuffer& buffer, SkRegion* region) { + buffer.getReader32()->readRegion(region); + } +}; +typedef SkFlatDictionary SkRegionDictionary; + + +struct SkPaintTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkPaint& paint) { + paint.flatten(buffer); + } + static void unflatten(SkOrderedReadBuffer& buffer, SkPaint* paint) { + paint->unflatten(buffer); + } +}; +typedef SkFlatDictionary SkPaintDictionary; class SkChunkFlatController : public SkFlatController { public: @@ -635,49 +683,4 @@ private: mutable SkTypefacePlayback fTypefacePlayback; }; -class SkMatrixDictionary : public SkFlatDictionary { - public: - // All matrices fit in 36 bytes. - SkMatrixDictionary(SkFlatController* controller) - : SkFlatDictionary(controller, 36) { - fFlattenProc = &flattenMatrix; - fUnflattenProc = &unflattenMatrix; - } - - static void flattenMatrix(SkOrderedWriteBuffer& buffer, const void* obj) { - buffer.getWriter32()->writeMatrix(*(SkMatrix*)obj); - } - - static void unflattenMatrix(SkOrderedReadBuffer& buffer, void* obj) { - buffer.getReader32()->readMatrix((SkMatrix*)obj); - } -}; - -class SkPaintDictionary : public SkFlatDictionary { - public: - // The largest paint across ~60 .skps was 500 bytes. - SkPaintDictionary(SkFlatController* controller) - : SkFlatDictionary(controller, 512) { - fFlattenProc = &SkFlattenObjectProc; - fUnflattenProc = &SkUnflattenObjectProc; - } -}; - -class SkRegionDictionary : public SkFlatDictionary { - public: - SkRegionDictionary(SkFlatController* controller) - : SkFlatDictionary(controller) { - fFlattenProc = &flattenRegion; - fUnflattenProc = &unflattenRegion; - } - - static void flattenRegion(SkOrderedWriteBuffer& buffer, const void* obj) { - buffer.getWriter32()->writeRegion(*(SkRegion*)obj); - } - - static void unflattenRegion(SkOrderedReadBuffer& buffer, void* obj) { - buffer.getReader32()->readRegion((SkRegion*)obj); - } -}; - #endif diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index 195afc6526..97e566764b 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -212,9 +212,10 @@ SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInf SkDEBUGCODE(int heapSize = SafeCount(fBitmapHeap.get());) for (int i = 0; i < paintCount; i++) { if (needs_deep_copy(src.fPaints->at(i))) { - deepCopyInfo->paintData[i] = SkFlatData::Create(&deepCopyInfo->controller, - &src.fPaints->at(i), 0, - &SkFlattenObjectProc); + deepCopyInfo->paintData[i] = + SkFlatData::Create(&deepCopyInfo->controller, + src.fPaints->at(i), 0); + } else { // this is our sentinel, which we use in the unflatten loop deepCopyInfo->paintData[i] = NULL; @@ -233,9 +234,8 @@ SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInf SkTypefacePlayback* tfPlayback = deepCopyInfo->controller.getTypefacePlayback(); for (int i = 0; i < paintCount; i++) { if (deepCopyInfo->paintData[i]) { - deepCopyInfo->paintData[i]->unflatten(&fPaints->writableAt(i), - &SkUnflattenObjectProc, - bmHeap, tfPlayback); + deepCopyInfo->paintData[i]->unflatten(&fPaints->writableAt(i), + bmHeap, tfPlayback); } else { // needs_deep_copy was false, so just need to assign fPaints->writableAt(i) = src.fPaints->at(i); diff --git a/src/pipe/SkGPipeWrite.cpp b/src/pipe/SkGPipeWrite.cpp index 0131ebb876..68acc179e7 100644 --- a/src/pipe/SkGPipeWrite.cpp +++ b/src/pipe/SkGPipeWrite.cpp @@ -150,20 +150,13 @@ const SkFlatData* FlattenableHeap::flatToReplace() const { /////////////////////////////////////////////////////////////////////////////// -class FlatDictionary : public SkFlatDictionary { -public: - FlatDictionary(FlattenableHeap* heap) - : SkFlatDictionary(heap) { - fFlattenProc = &flattenFlattenableProc; - // No need to define fUnflattenProc since the writer will never - // unflatten the data. +struct SkFlattenableTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkFlattenable& flattenable) { + buffer.writeFlattenable(&flattenable); } - static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer, - const void* obj) { - buffer.writeFlattenable((SkFlattenable*)obj); - } - + // No need to define unflatten if we never call it. }; +typedef SkFlatDictionary FlatDictionary; /////////////////////////////////////////////////////////////////////////////// diff --git a/tests/BitmapHeapTest.cpp b/tests/BitmapHeapTest.cpp index 2b5cf830c5..bcfec22fd1 100644 --- a/tests/BitmapHeapTest.cpp +++ b/tests/BitmapHeapTest.cpp @@ -16,18 +16,12 @@ #include "Test.h" #include "TestClassDef.h" -class FlatDictionary : public SkFlatDictionary { - -public: - FlatDictionary(SkFlatController* controller) - : SkFlatDictionary(controller) { - fFlattenProc = &flattenFlattenableProc; - // No need for an unflattenProc - } - static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer, const void* obj) { - buffer.writeFlattenable((SkFlattenable*)obj); +struct SkShaderTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkShader& shader) { + buffer.writeFlattenable(&shader); } }; +typedef SkFlatDictionary FlatDictionary; class SkBitmapHeapTester { diff --git a/tests/FlatDataTest.cpp b/tests/FlatDataTest.cpp index b6133acf87..95a2bd020f 100644 --- a/tests/FlatDataTest.cpp +++ b/tests/FlatDataTest.cpp @@ -17,10 +17,16 @@ #include "SkShader.h" #include "SkXfermode.h" -static void flattenFlattenableProc(SkOrderedWriteBuffer& buffer, - const void* obj) { - buffer.writeFlattenable((SkFlattenable*)obj); -} +struct SkFlattenableTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkFlattenable& flattenable) { + buffer.writeFlattenable(&flattenable); + } +}; +struct SkBitmapTraits { + static void flatten(SkOrderedWriteBuffer& buffer, const SkBitmap& bitmap) { + bitmap.flatten(buffer); + } +}; class Controller : public SkChunkFlatController { public: @@ -38,13 +44,12 @@ private: * @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*)) { +template +static void testCreate(skiatest::Reporter* reporter, const T& obj) { Controller controller; - // No need to delete data because that will be taken care of by the - // controller. - SkFlatData* data1 = SkFlatData::Create(&controller, obj, 0, flattenProc); - SkFlatData* data2 = SkFlatData::Create(&controller, obj, 1, flattenProc); + // No need to delete data because that will be taken care of by the controller. + SkFlatData* data1 = SkFlatData::Create(&controller, obj, 0); + SkFlatData* data2 = SkFlatData::Create(&controller, obj, 1); REPORTER_ASSERT(reporter, *data1 == *data2); } @@ -56,10 +61,10 @@ DEF_TEST(FlatData, reporter) { 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); + + SkAutoTUnref shader(SkGradientShader::CreateLinear(points, colors, NULL, 2, + SkShader::kRepeat_TileMode)); + testCreate(reporter, *shader); // Test SkBitmap { @@ -70,17 +75,14 @@ DEF_TEST(FlatData, reporter) { SkPaint paint; paint.setShader(shader); canvas.drawPaint(paint); - testCreate(reporter, &bm, &SkFlattenObjectProc); + testCreate(reporter, bm); } // Test SkColorFilter - SkColorFilter* cf = SkColorFilter::CreateLightingFilter(SK_ColorBLUE, - SK_ColorRED); - SkAutoUnref aurcf(cf); - testCreate(reporter, cf, &flattenFlattenableProc); + SkAutoTUnref cf(SkColorFilter::CreateLightingFilter(SK_ColorBLUE, SK_ColorRED)); + testCreate(reporter, *cf); // Test SkXfermode - SkXfermode* xfer = SkXfermode::Create(SkXfermode::kDstOver_Mode); - SkAutoUnref aurxf(xfer); - testCreate(reporter, xfer, &flattenFlattenableProc); + SkAutoTUnref xfer(SkXfermode::Create(SkXfermode::kDstOver_Mode)); + testCreate(reporter, *xfer); }