OLD | NEW |
---|---|
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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S kFlatDictionary; | 369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S kFlatDictionary; |
370 }; | 370 }; |
371 | 371 |
372 template <typename T, typename Traits, int kScratchSizeGuess=0> | 372 template <typename T, typename Traits, int kScratchSizeGuess=0> |
373 class SkFlatDictionary { | 373 class SkFlatDictionary { |
374 static const size_t kWriteBufferGrowthBytes = 1024; | 374 static const size_t kWriteBufferGrowthBytes = 1024; |
375 | 375 |
376 public: | 376 public: |
377 explicit SkFlatDictionary(SkFlatController* controller) | 377 explicit SkFlatDictionary(SkFlatController* controller) |
378 : fController(SkRef(controller)) | 378 : fController(SkRef(controller)) |
379 , fScratchSize(kScratchSizeGuess) | 379 , fScratchSize(kScratchSizeGuess) |
mtklein
2014/01/09 14:38:58
For consistency, let's make this fScratchSize(0) t
tomhudson
2014/01/09 14:49:32
Done.
| |
380 , fScratch(AllocScratch(fScratchSize)) | 380 , fScratch(NULL) |
381 , fWriteBuffer(kWriteBufferGrowthBytes) | 381 , fWriteBuffer(kWriteBufferGrowthBytes) |
382 , fWriteBufferReady(false) { | 382 , fBuffersReady(false) { |
mtklein
2014/01/09 14:38:58
Suggestion: fReady and lazyInit() ?
tomhudson
2014/01/09 14:49:32
Done.
| |
383 this->reset(); | 383 this->reset(); |
384 } | 384 } |
385 | 385 |
386 /** | 386 /** |
387 * 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 |
388 * 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). |
389 */ | 389 */ |
390 void reset() { | 390 void reset() { |
391 fIndexedData.rewind(); | 391 fIndexedData.rewind(); |
392 // TODO(mtklein): There's no reason to have the index start from 1. Cle an this up. | 392 // TODO(mtklein): There's no reason to have the index start from 1. Cle an this up. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 SkASSERT(SkIsAlign4(flatDataSize)); | 508 SkASSERT(SkIsAlign4(flatDataSize)); |
509 return sizeof(SkFlatData) + flatDataSize; | 509 return sizeof(SkFlatData) + flatDataSize; |
510 } | 510 } |
511 | 511 |
512 // Allocate a new scratch SkFlatData. Must be sk_freed. | 512 // Allocate a new scratch SkFlatData. Must be sk_freed. |
513 static SkFlatData* AllocScratch(size_t scratchSize) { | 513 static SkFlatData* AllocScratch(size_t scratchSize) { |
514 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); | 514 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize)); |
515 } | 515 } |
516 | 516 |
517 // We have to delay fWriteBuffer's initialization until its first use; fCont roller might not | 517 // We have to delay fWriteBuffer's initialization until its first use; fCont roller might not |
518 // be fully set up by the time we get it in the constructor. | 518 // be fully set up by the time we get it in the constructor. We also delay f Scratch to |
mtklein
2014/01/09 14:38:58
delay -> delay allocating?
tomhudson
2014/01/09 14:49:32
Done.
| |
519 void lazyWriteBufferInit() { | 519 // avoid unnecessary heap allocations, since we're paying the price of the c onditional |
520 if (fWriteBufferReady) { | 520 // anyway. |
521 void lazyBufferInit() { | |
522 if (fBuffersReady) { | |
521 return; | 523 return; |
522 } | 524 } |
525 | |
526 fScratch = AllocScratch(fScratchSize); | |
527 | |
523 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev er what you want. | 528 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev er what you want. |
524 SkASSERT(fController->getBitmapHeap() != NULL); | 529 SkASSERT(fController->getBitmapHeap() != NULL); |
525 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); | 530 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); |
526 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); | 531 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); |
527 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); | 532 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); |
528 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); | 533 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); |
529 fWriteBufferReady = true; | 534 fBuffersReady = true; |
530 } | 535 } |
531 | 536 |
532 // As findAndReturnFlat, but returns a mutable pointer for internal use. | 537 // As findAndReturnFlat, but returns a mutable pointer for internal use. |
533 SkFlatData* findAndReturnMutableFlat(const T& element) { | 538 SkFlatData* findAndReturnMutableFlat(const T& element) { |
534 // Only valid until the next call to resetScratch(). | 539 // Only valid until the next call to resetScratch(). |
535 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); | 540 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); |
536 | 541 |
537 SkFlatData* candidate = fHash.find(scratch); | 542 SkFlatData* candidate = fHash.find(scratch); |
538 if (candidate != NULL) return candidate; | 543 if (candidate != NULL) return candidate; |
539 | 544 |
540 SkFlatData* detached = this->detachScratch(); | 545 SkFlatData* detached = this->detachScratch(); |
541 fHash.add(detached); | 546 fHash.add(detached); |
542 *fIndexedData.insert(fNextIndex) = detached; | 547 *fIndexedData.insert(fNextIndex) = detached; |
543 fNextIndex++; | 548 fNextIndex++; |
544 return detached; | 549 return detached; |
545 } | 550 } |
546 | 551 |
547 // This reference is valid only until the next call to resetScratch() or det achScratch(). | 552 // This reference is valid only until the next call to resetScratch() or det achScratch(). |
548 const SkFlatData& resetScratch(const T& element, int index) { | 553 const SkFlatData& resetScratch(const T& element, int index) { |
549 this->lazyWriteBufferInit(); | 554 this->lazyBufferInit(); |
550 | 555 |
551 // Flatten element into fWriteBuffer (using fScratch as storage). | 556 // Flatten element into fWriteBuffer (using fScratch as storage). |
552 fWriteBuffer.reset(fScratch->data(), fScratchSize); | 557 fWriteBuffer.reset(fScratch->data(), fScratchSize); |
553 Traits::flatten(fWriteBuffer, element); | 558 Traits::flatten(fWriteBuffer, element); |
554 const size_t bytesWritten = fWriteBuffer.bytesWritten(); | 559 const size_t bytesWritten = fWriteBuffer.bytesWritten(); |
555 | 560 |
556 // If all the flattened bytes fit into fScratch, we can skip a call to w riteToMemory. | 561 // If all the flattened bytes fit into fScratch, we can skip a call to w riteToMemory. |
557 if (!fWriteBuffer.wroteOnlyToStorage()) { | 562 if (!fWriteBuffer.wroteOnlyToStorage()) { |
558 SkASSERT(bytesWritten > fScratchSize); | 563 SkASSERT(bytesWritten > fScratchSize); |
559 // It didn't all fit. Copy into a larger replacement SkFlatData. | 564 // It didn't all fit. Copy into a larger replacement SkFlatData. |
(...skipping 10 matching lines...) Expand all Loading... | |
570 // The data is in fScratch now but we need to stamp its header. | 575 // The data is in fScratch now but we need to stamp its header. |
571 fScratch->stampHeader(index, bytesWritten); | 576 fScratch->stampHeader(index, bytesWritten); |
572 return *fScratch; | 577 return *fScratch; |
573 } | 578 } |
574 | 579 |
575 // This result is owned by fController and lives as long as it does (unless unalloc'd). | 580 // This result is owned by fController and lives as long as it does (unless unalloc'd). |
576 SkFlatData* detachScratch() { | 581 SkFlatData* detachScratch() { |
577 // Allocate a new SkFlatData exactly big enough to hold our current scra tch. | 582 // Allocate a new SkFlatData exactly big enough to hold our current scra tch. |
578 // We use the controller for this allocation to extend the allocation's lifetime and allow | 583 // We use the controller for this allocation to extend the allocation's lifetime and allow |
579 // the controller to do whatever memory management it wants. | 584 // the controller to do whatever memory management it wants. |
585 SkASSERT(fScratch); | |
mtklein
2014/01/09 14:38:58
Suggestion: SkASSERT(fScratch != NULL); as a free
tomhudson
2014/01/09 14:49:32
Done.
| |
580 const size_t paddedSize = SizeWithPadding(fScratch->flatSize()); | 586 const size_t paddedSize = SizeWithPadding(fScratch->flatSize()); |
581 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); | 587 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); |
582 | 588 |
583 // Copy scratch into the new SkFlatData. | 589 // Copy scratch into the new SkFlatData. |
584 memcpy(detached, fScratch, paddedSize); | 590 memcpy(detached, fScratch, paddedSize); |
585 | 591 |
586 // We can now reuse fScratch, and detached will live until fController d ies. | 592 // We can now reuse fScratch, and detached will live until fController d ies. |
587 return detached; | 593 return detached; |
588 } | 594 } |
589 | 595 |
590 void unflatten(T* dst, const SkFlatData* element) const { | 596 void unflatten(T* dst, const SkFlatData* element) const { |
591 element->unflatten<Traits>(dst, | 597 element->unflatten<Traits>(dst, |
592 fController->getBitmapHeap(), | 598 fController->getBitmapHeap(), |
593 fController->getTypefacePlayback()); | 599 fController->getTypefacePlayback()); |
594 } | 600 } |
595 | 601 |
596 // All SkFlatData* stored in fIndexedData and fHash are owned by the control ler. | 602 // All SkFlatData* stored in fIndexedData and fHash are owned by the control ler. |
597 SkAutoTUnref<SkFlatController> fController; | 603 SkAutoTUnref<SkFlatController> fController; |
598 size_t fScratchSize; // How many bytes fScratch has allocated for data itse lf. | 604 size_t fScratchSize; // How many bytes fScratch has allocated for data itse lf. |
599 SkFlatData* fScratch; // Owned, must be freed with sk_free. | 605 SkFlatData* fScratch; // Owned, lazily allocated, must be freed with sk_fre e. |
600 SkOrderedWriteBuffer fWriteBuffer; | 606 SkOrderedWriteBuffer fWriteBuffer; |
601 bool fWriteBufferReady; | 607 bool fBuffersReady; |
602 | 608 |
603 // We map between SkFlatData and a 1-based integer index. | 609 // We map between SkFlatData and a 1-based integer index. |
604 int fNextIndex; | 610 int fNextIndex; |
605 | 611 |
606 // For index -> SkFlatData. fIndexedData[0] is always NULL. | 612 // For index -> SkFlatData. fIndexedData[0] is always NULL. |
607 SkTDArray<const SkFlatData*> fIndexedData; | 613 SkTDArray<const SkFlatData*> fIndexedData; |
608 | 614 |
609 // For SkFlatData -> cached SkFlatData, which has index(). | 615 // For SkFlatData -> cached SkFlatData, which has index(). |
610 SkTDynamicHash<SkFlatData, SkFlatData, | 616 SkTDynamicHash<SkFlatData, SkFlatData, |
611 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH ash; | 617 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH ash; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
677 } | 683 } |
678 | 684 |
679 private: | 685 private: |
680 SkChunkAlloc fHeap; | 686 SkChunkAlloc fHeap; |
681 SkAutoTUnref<SkRefCntSet> fTypefaceSet; | 687 SkAutoTUnref<SkRefCntSet> fTypefaceSet; |
682 void* fLastAllocated; | 688 void* fLastAllocated; |
683 mutable SkTypefacePlayback fTypefacePlayback; | 689 mutable SkTypefacePlayback fTypefacePlayback; |
684 }; | 690 }; |
685 | 691 |
686 #endif | 692 #endif |
OLD | NEW |