Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: src/core/SkPictureFlat.h

Issue 123213004: Function pointers -> templates in SkPictureFlat. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: align storage Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/core/SkPictureFlat.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 1
2 /* 2 /*
3 * Copyright 2011 Google Inc. 3 * Copyright 2011 Google Inc.
4 * 4 *
5 * Use of this source code is governed by a BSD-style license that can be 5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file. 6 * found in the LICENSE file.
7 */ 7 */
8 #ifndef SkPictureFlat_DEFINED 8 #ifndef SkPictureFlat_DEFINED
9 #define SkPictureFlat_DEFINED 9 #define SkPictureFlat_DEFINED
10 10
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after
260 SkTypefacePlayback* fTypefacePlayback; 260 SkTypefacePlayback* fTypefacePlayback;
261 SkNamedFactorySet* fFactorySet; 261 SkNamedFactorySet* fFactorySet;
262 uint32_t fWriteBufferFlags; 262 uint32_t fWriteBufferFlags;
263 263
264 typedef SkRefCnt INHERITED; 264 typedef SkRefCnt INHERITED;
265 }; 265 };
266 266
267 class SkFlatData { 267 class SkFlatData {
268 public: 268 public:
269 // Flatten obj into an SkFlatData with this index. controller owns the SkFl atData*. 269 // Flatten obj into an SkFlatData with this index. controller owns the SkFl atData*.
270 static SkFlatData* Create(SkFlatController* controller, 270 template <typename Traits, typename T>
271 const void* obj, 271 static SkFlatData* Create(SkFlatController* controller, const T& obj, int in dex) {
272 int index, 272 // A buffer of 256 bytes should fit most paints, regions, and matrices.
273 void (*flattenProc)(SkOrderedWriteBuffer&, const v oid*)); 273 uint32_t storage[64];
274 SkOrderedWriteBuffer buffer(256, storage, sizeof(storage));
274 275
275 // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given. 276 buffer.setBitmapHeap(controller->getBitmapHeap());
276 void unflatten(void* result, 277 buffer.setTypefaceRecorder(controller->getTypefaceSet());
277 void (*unflattenProc)(SkOrderedReadBuffer&, void*), 278 buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());
279 buffer.setFlags(controller->getWriteBufferFlags());
280
281 Traits::flatten(buffer, obj);
282 uint32_t size = buffer.size();
283 SkASSERT(SkIsAlign4(size));
284
285 // Allocate enough memory to hold SkFlatData struct and the flat data it self.
286 size_t allocSize = sizeof(SkFlatData) + size;
287 SkFlatData* result = (SkFlatData*) controller->allocThrow(allocSize);
288
289 // Put the serialized contents into the data section of the new allocati on.
290 buffer.writeToMemory(result->data());
291 // Stamp the index, size and checksum in the header.
292 result->stampHeader(index, size);
293 return result;
294 }
295
296 // Unflatten this into result, using bitmapHeap and facePlayback for bitmaps and fonts if given
297 template <typename Traits, typename T>
298 void unflatten(T* result,
278 SkBitmapHeap* bitmapHeap = NULL, 299 SkBitmapHeap* bitmapHeap = NULL,
279 SkTypefacePlayback* facePlayback = NULL) const; 300 SkTypefacePlayback* facePlayback = NULL) const {
301 SkOrderedReadBuffer buffer(this->data(), fFlatSize);
302
303 if (bitmapHeap) {
304 buffer.setBitmapStorage(bitmapHeap);
305 }
306 if (facePlayback) {
307 facePlayback->setupBuffer(buffer);
308 }
309
310 Traits::unflatten(buffer, result);
311 SkASSERT(fFlatSize == (int32_t)buffer.offset());
312 }
280 313
281 // Do these contain the same data? Ignores index() and topBot(). 314 // Do these contain the same data? Ignores index() and topBot().
282 bool operator==(const SkFlatData& that) const { 315 bool operator==(const SkFlatData& that) const {
283 if (this->checksum() != that.checksum() || this->flatSize() != that.flat Size()) { 316 if (this->checksum() != that.checksum() || this->flatSize() != that.flat Size()) {
284 return false; 317 return false;
285 } 318 }
286 return memcmp(this->data(), that.data(), this->flatSize()) == 0; 319 return memcmp(this->data(), that.data(), this->flatSize()) == 0;
287 } 320 }
288 321
289 int index() const { return fIndex; } 322 int index() const { return fIndex; }
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 fTopBot[0] = SK_ScalarNaN; // Mark as unwritten. 359 fTopBot[0] = SK_ScalarNaN; // Mark as unwritten.
327 fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size); 360 fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size);
328 } 361 }
329 362
330 int fIndex; 363 int fIndex;
331 int32_t fFlatSize; 364 int32_t fFlatSize;
332 uint32_t fChecksum; 365 uint32_t fChecksum;
333 mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts as [NaN,?]. 366 mutable SkScalar fTopBot[2]; // Cache of FontMetrics fTop, fBottom. Starts as [NaN,?].
334 // uint32_t flattenedData[] implicitly hangs off the end. 367 // uint32_t flattenedData[] implicitly hangs off the end.
335 368
336 template <class T> friend class SkFlatDictionary; 369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S kFlatDictionary;
337 }; 370 };
338 371
339 template <class T> 372 template <typename T, typename Traits, int kScratchSizeGuess=0>
340 class SkFlatDictionary { 373 class SkFlatDictionary {
341 static const size_t kWriteBufferGrowthBytes = 1024; 374 static const size_t kWriteBufferGrowthBytes = 1024;
342 375
343 public: 376 public:
344 SkFlatDictionary(SkFlatController* controller, size_t scratchSizeGuess = 0) 377 explicit SkFlatDictionary(SkFlatController* controller)
345 : fFlattenProc(NULL) 378 : fController(SkRef(controller))
346 , fUnflattenProc(NULL) 379 , fScratchSize(kScratchSizeGuess)
347 , fController(SkRef(controller))
348 , fScratchSize(scratchSizeGuess)
349 , fScratch(AllocScratch(fScratchSize)) 380 , fScratch(AllocScratch(fScratchSize))
350 , fWriteBuffer(kWriteBufferGrowthBytes) 381 , fWriteBuffer(kWriteBufferGrowthBytes)
351 , fWriteBufferReady(false) { 382 , fWriteBufferReady(false) {
352 this->reset(); 383 this->reset();
353 } 384 }
354 385
355 /** 386 /**
356 * Clears the dictionary of all entries. However, it does NOT free the 387 * Clears the dictionary of all entries. However, it does NOT free the
357 * memory that was allocated for each entry (that's owned by controller). 388 * memory that was allocated for each entry (that's owned by controller).
358 */ 389 */
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
464 } 495 }
465 496
466 /** 497 /**
467 * Find or insert a flattened version of element into the dictionary. 498 * Find or insert a flattened version of element into the dictionary.
468 * Caller does not take ownership of the result. This will not return NULL. 499 * Caller does not take ownership of the result. This will not return NULL.
469 */ 500 */
470 const SkFlatData* findAndReturnFlat(const T& element) { 501 const SkFlatData* findAndReturnFlat(const T& element) {
471 return this->findAndReturnMutableFlat(element); 502 return this->findAndReturnMutableFlat(element);
472 } 503 }
473 504
474 protected:
475 void (*fFlattenProc)(SkOrderedWriteBuffer&, const void*);
476 void (*fUnflattenProc)(SkOrderedReadBuffer&, void*);
477
478 private: 505 private:
479 // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ] 506 // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ]
480 static size_t SizeWithPadding(size_t flatDataSize) { 507 static size_t SizeWithPadding(size_t flatDataSize) {
481 SkASSERT(SkIsAlign4(flatDataSize)); 508 SkASSERT(SkIsAlign4(flatDataSize));
482 return sizeof(SkFlatData) + flatDataSize; 509 return sizeof(SkFlatData) + flatDataSize;
483 } 510 }
484 511
485 // Allocate a new scratch SkFlatData. Must be sk_freed. 512 // Allocate a new scratch SkFlatData. Must be sk_freed.
486 static SkFlatData* AllocScratch(size_t scratchSize) { 513 static SkFlatData* AllocScratch(size_t scratchSize) {
487 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); 514 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize));
(...skipping 28 matching lines...) Expand all
516 fNextIndex++; 543 fNextIndex++;
517 return detached; 544 return detached;
518 } 545 }
519 546
520 // This reference is valid only until the next call to resetScratch() or det achScratch(). 547 // This reference is valid only until the next call to resetScratch() or det achScratch().
521 const SkFlatData& resetScratch(const T& element, int index) { 548 const SkFlatData& resetScratch(const T& element, int index) {
522 this->lazyWriteBufferInit(); 549 this->lazyWriteBufferInit();
523 550
524 // Flatten element into fWriteBuffer (using fScratch as storage). 551 // Flatten element into fWriteBuffer (using fScratch as storage).
525 fWriteBuffer.reset(fScratch->data(), fScratchSize); 552 fWriteBuffer.reset(fScratch->data(), fScratchSize);
526 fFlattenProc(fWriteBuffer, &element); 553 Traits::flatten(fWriteBuffer, element);
527 const size_t bytesWritten = fWriteBuffer.bytesWritten(); 554 const size_t bytesWritten = fWriteBuffer.bytesWritten();
528 555
529 // If all the flattened bytes fit into fScratch, we can skip a call to w riteToMemory. 556 // If all the flattened bytes fit into fScratch, we can skip a call to w riteToMemory.
530 if (!fWriteBuffer.wroteOnlyToStorage()) { 557 if (!fWriteBuffer.wroteOnlyToStorage()) {
531 SkASSERT(bytesWritten > fScratchSize); 558 SkASSERT(bytesWritten > fScratchSize);
532 // It didn't all fit. Copy into a larger replacement SkFlatData. 559 // It didn't all fit. Copy into a larger replacement SkFlatData.
533 // We can't just realloc because it might move the pointer and confu se writeToMemory. 560 // We can't just realloc because it might move the pointer and confu se writeToMemory.
534 SkFlatData* larger = AllocScratch(bytesWritten); 561 SkFlatData* larger = AllocScratch(bytesWritten);
535 fWriteBuffer.writeToMemory(larger->data()); 562 fWriteBuffer.writeToMemory(larger->data());
536 563
(...skipping 17 matching lines...) Expand all
554 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); 581 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize);
555 582
556 // Copy scratch into the new SkFlatData. 583 // Copy scratch into the new SkFlatData.
557 memcpy(detached, fScratch, paddedSize); 584 memcpy(detached, fScratch, paddedSize);
558 585
559 // We can now reuse fScratch, and detached will live until fController d ies. 586 // We can now reuse fScratch, and detached will live until fController d ies.
560 return detached; 587 return detached;
561 } 588 }
562 589
563 void unflatten(T* dst, const SkFlatData* element) const { 590 void unflatten(T* dst, const SkFlatData* element) const {
564 element->unflatten(dst, 591 element->unflatten<Traits>(dst,
565 fUnflattenProc, 592 fController->getBitmapHeap(),
566 fController->getBitmapHeap(), 593 fController->getTypefacePlayback());
567 fController->getTypefacePlayback());
568 } 594 }
569 595
570 // All SkFlatData* stored in fIndexedData and fHash are owned by the control ler. 596 // All SkFlatData* stored in fIndexedData and fHash are owned by the control ler.
571 SkAutoTUnref<SkFlatController> fController; 597 SkAutoTUnref<SkFlatController> fController;
572 size_t fScratchSize; // How many bytes fScratch has allocated for data itse lf. 598 size_t fScratchSize; // How many bytes fScratch has allocated for data itse lf.
573 SkFlatData* fScratch; // Owned, must be freed with sk_free. 599 SkFlatData* fScratch; // Owned, must be freed with sk_free.
574 SkOrderedWriteBuffer fWriteBuffer; 600 SkOrderedWriteBuffer fWriteBuffer;
575 bool fWriteBufferReady; 601 bool fWriteBufferReady;
576 602
577 // We map between SkFlatData and a 1-based integer index. 603 // We map between SkFlatData and a 1-based integer index.
578 int fNextIndex; 604 int fNextIndex;
579 605
580 // For index -> SkFlatData. fIndexedData[0] is always NULL. 606 // For index -> SkFlatData. fIndexedData[0] is always NULL.
581 SkTDArray<const SkFlatData*> fIndexedData; 607 SkTDArray<const SkFlatData*> fIndexedData;
582 608
583 // For SkFlatData -> cached SkFlatData, which has index(). 609 // For SkFlatData -> cached SkFlatData, which has index().
584 SkTDynamicHash<SkFlatData, SkFlatData, 610 SkTDynamicHash<SkFlatData, SkFlatData,
585 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH ash; 611 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH ash;
586 }; 612 };
587 613
588 /////////////////////////////////////////////////////////////////////////////// 614 ///////////////////////////////////////////////////////////////////////////////
589 // Some common dictionaries are defined here for both reference and convenience 615 // Some common dictionaries are defined here for both reference and convenience
590 /////////////////////////////////////////////////////////////////////////////// 616 ///////////////////////////////////////////////////////////////////////////////
591 617
592 template <class T> 618 struct SkMatrixTraits {
593 static void SkFlattenObjectProc(SkOrderedWriteBuffer& buffer, const void* obj) { 619 static void flatten(SkOrderedWriteBuffer& buffer, const SkMatrix& matrix) {
594 ((T*)obj)->flatten(buffer); 620 buffer.getWriter32()->writeMatrix(matrix);
595 } 621 }
622 static void unflatten(SkOrderedReadBuffer& buffer, SkMatrix* matrix) {
623 buffer.getReader32()->readMatrix(matrix);
624 }
625 };
626 typedef SkFlatDictionary<SkMatrix, SkMatrixTraits, 36> SkMatrixDictionary;
596 627
597 template <class T> 628
598 static void SkUnflattenObjectProc(SkOrderedReadBuffer& buffer, void* obj) { 629 struct SkRegionTraits {
599 ((T*)obj)->unflatten(buffer); 630 static void flatten(SkOrderedWriteBuffer& buffer, const SkRegion& region) {
600 } 631 buffer.getWriter32()->writeRegion(region);
632 }
633 static void unflatten(SkOrderedReadBuffer& buffer, SkRegion* region) {
634 buffer.getReader32()->readRegion(region);
635 }
636 };
637 typedef SkFlatDictionary<SkRegion, SkRegionTraits> SkRegionDictionary;
638
639
640 struct SkPaintTraits {
641 static void flatten(SkOrderedWriteBuffer& buffer, const SkPaint& paint) {
642 paint.flatten(buffer);
643 }
644 static void unflatten(SkOrderedReadBuffer& buffer, SkPaint* paint) {
645 paint->unflatten(buffer);
646 }
647 };
648 typedef SkFlatDictionary<SkPaint, SkPaintTraits, 512> SkPaintDictionary;
601 649
602 class SkChunkFlatController : public SkFlatController { 650 class SkChunkFlatController : public SkFlatController {
603 public: 651 public:
604 SkChunkFlatController(size_t minSize) 652 SkChunkFlatController(size_t minSize)
605 : fHeap(minSize) 653 : fHeap(minSize)
606 , fTypefaceSet(SkNEW(SkRefCntSet)) 654 , fTypefaceSet(SkNEW(SkRefCntSet))
607 , fLastAllocated(NULL) { 655 , fLastAllocated(NULL) {
608 this->setTypefaceSet(fTypefaceSet); 656 this->setTypefaceSet(fTypefaceSet);
609 this->setTypefacePlayback(&fTypefacePlayback); 657 this->setTypefacePlayback(&fTypefacePlayback);
610 } 658 }
(...skipping 17 matching lines...) Expand all
628 this->setBitmapHeap(heap); 676 this->setBitmapHeap(heap);
629 } 677 }
630 678
631 private: 679 private:
632 SkChunkAlloc fHeap; 680 SkChunkAlloc fHeap;
633 SkAutoTUnref<SkRefCntSet> fTypefaceSet; 681 SkAutoTUnref<SkRefCntSet> fTypefaceSet;
634 void* fLastAllocated; 682 void* fLastAllocated;
635 mutable SkTypefacePlayback fTypefacePlayback; 683 mutable SkTypefacePlayback fTypefacePlayback;
636 }; 684 };
637 685
638 class SkMatrixDictionary : public SkFlatDictionary<SkMatrix> {
639 public:
640 // All matrices fit in 36 bytes.
641 SkMatrixDictionary(SkFlatController* controller)
642 : SkFlatDictionary<SkMatrix>(controller, 36) {
643 fFlattenProc = &flattenMatrix;
644 fUnflattenProc = &unflattenMatrix;
645 }
646
647 static void flattenMatrix(SkOrderedWriteBuffer& buffer, const void* obj) {
648 buffer.getWriter32()->writeMatrix(*(SkMatrix*)obj);
649 }
650
651 static void unflattenMatrix(SkOrderedReadBuffer& buffer, void* obj) {
652 buffer.getReader32()->readMatrix((SkMatrix*)obj);
653 }
654 };
655
656 class SkPaintDictionary : public SkFlatDictionary<SkPaint> {
657 public:
658 // The largest paint across ~60 .skps was 500 bytes.
659 SkPaintDictionary(SkFlatController* controller)
660 : SkFlatDictionary<SkPaint>(controller, 512) {
661 fFlattenProc = &SkFlattenObjectProc<SkPaint>;
662 fUnflattenProc = &SkUnflattenObjectProc<SkPaint>;
663 }
664 };
665
666 class SkRegionDictionary : public SkFlatDictionary<SkRegion> {
667 public:
668 SkRegionDictionary(SkFlatController* controller)
669 : SkFlatDictionary<SkRegion>(controller) {
670 fFlattenProc = &flattenRegion;
671 fUnflattenProc = &unflattenRegion;
672 }
673
674 static void flattenRegion(SkOrderedWriteBuffer& buffer, const void* obj) {
675 buffer.getWriter32()->writeRegion(*(SkRegion*)obj);
676 }
677
678 static void unflattenRegion(SkOrderedReadBuffer& buffer, void* obj) {
679 buffer.getReader32()->readRegion((SkRegion*)obj);
680 }
681 };
682
683 #endif 686 #endif
OLDNEW
« no previous file with comments | « no previous file | src/core/SkPictureFlat.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698