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(0) |
380 , fScratch(AllocScratch(fScratchSize)) | 380 , fScratch(NULL) |
381 , fWriteBuffer(kWriteBufferGrowthBytes) | 381 , fWriteBuffer(kWriteBufferGrowthBytes) |
382 , fWriteBufferReady(false) { | 382 , fReady(false) { |
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 a
llocating fScratch |
519 void lazyWriteBufferInit() { | 519 // to avoid unnecessary heap allocations, since we're paying the price of th
e conditional |
520 if (fWriteBufferReady) { | 520 // anyway. |
| 521 void lazyInit() { |
| 522 if (fReady) { |
521 return; | 523 return; |
522 } | 524 } |
| 525 |
| 526 fScratchSize = kScratchSizeGuess; |
| 527 fScratch = AllocScratch(fScratchSize); |
| 528 |
523 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev
er what you want. | 529 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev
er what you want. |
524 SkASSERT(fController->getBitmapHeap() != NULL); | 530 SkASSERT(fController->getBitmapHeap() != NULL); |
525 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); | 531 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); |
526 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); | 532 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); |
527 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); | 533 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); |
528 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); | 534 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); |
529 fWriteBufferReady = true; | 535 fReady = true; |
530 } | 536 } |
531 | 537 |
532 // As findAndReturnFlat, but returns a mutable pointer for internal use. | 538 // As findAndReturnFlat, but returns a mutable pointer for internal use. |
533 SkFlatData* findAndReturnMutableFlat(const T& element) { | 539 SkFlatData* findAndReturnMutableFlat(const T& element) { |
534 // Only valid until the next call to resetScratch(). | 540 // Only valid until the next call to resetScratch(). |
535 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); | 541 const SkFlatData& scratch = this->resetScratch(element, fNextIndex); |
536 | 542 |
537 SkFlatData* candidate = fHash.find(scratch); | 543 SkFlatData* candidate = fHash.find(scratch); |
538 if (candidate != NULL) return candidate; | 544 if (candidate != NULL) return candidate; |
539 | 545 |
540 SkFlatData* detached = this->detachScratch(); | 546 SkFlatData* detached = this->detachScratch(); |
541 fHash.add(detached); | 547 fHash.add(detached); |
542 *fIndexedData.insert(fNextIndex) = detached; | 548 *fIndexedData.insert(fNextIndex) = detached; |
543 fNextIndex++; | 549 fNextIndex++; |
544 return detached; | 550 return detached; |
545 } | 551 } |
546 | 552 |
547 // This reference is valid only until the next call to resetScratch() or det
achScratch(). | 553 // This reference is valid only until the next call to resetScratch() or det
achScratch(). |
548 const SkFlatData& resetScratch(const T& element, int index) { | 554 const SkFlatData& resetScratch(const T& element, int index) { |
549 this->lazyWriteBufferInit(); | 555 this->lazyInit(); |
550 | 556 |
551 // Flatten element into fWriteBuffer (using fScratch as storage). | 557 // Flatten element into fWriteBuffer (using fScratch as storage). |
552 fWriteBuffer.reset(fScratch->data(), fScratchSize); | 558 fWriteBuffer.reset(fScratch->data(), fScratchSize); |
553 Traits::flatten(fWriteBuffer, element); | 559 Traits::flatten(fWriteBuffer, element); |
554 const size_t bytesWritten = fWriteBuffer.bytesWritten(); | 560 const size_t bytesWritten = fWriteBuffer.bytesWritten(); |
555 | 561 |
556 // If all the flattened bytes fit into fScratch, we can skip a call to w
riteToMemory. | 562 // If all the flattened bytes fit into fScratch, we can skip a call to w
riteToMemory. |
557 if (!fWriteBuffer.wroteOnlyToStorage()) { | 563 if (!fWriteBuffer.wroteOnlyToStorage()) { |
558 SkASSERT(bytesWritten > fScratchSize); | 564 SkASSERT(bytesWritten > fScratchSize); |
559 // It didn't all fit. Copy into a larger replacement SkFlatData. | 565 // 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. | 576 // The data is in fScratch now but we need to stamp its header. |
571 fScratch->stampHeader(index, bytesWritten); | 577 fScratch->stampHeader(index, bytesWritten); |
572 return *fScratch; | 578 return *fScratch; |
573 } | 579 } |
574 | 580 |
575 // This result is owned by fController and lives as long as it does (unless
unalloc'd). | 581 // This result is owned by fController and lives as long as it does (unless
unalloc'd). |
576 SkFlatData* detachScratch() { | 582 SkFlatData* detachScratch() { |
577 // Allocate a new SkFlatData exactly big enough to hold our current scra
tch. | 583 // 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 | 584 // 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. | 585 // the controller to do whatever memory management it wants. |
| 586 SkASSERT(fScratch != NULL); |
580 const size_t paddedSize = SizeWithPadding(fScratch->flatSize()); | 587 const size_t paddedSize = SizeWithPadding(fScratch->flatSize()); |
581 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); | 588 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize); |
582 | 589 |
583 // Copy scratch into the new SkFlatData. | 590 // Copy scratch into the new SkFlatData. |
584 memcpy(detached, fScratch, paddedSize); | 591 memcpy(detached, fScratch, paddedSize); |
585 | 592 |
586 // We can now reuse fScratch, and detached will live until fController d
ies. | 593 // We can now reuse fScratch, and detached will live until fController d
ies. |
587 return detached; | 594 return detached; |
588 } | 595 } |
589 | 596 |
590 void unflatten(T* dst, const SkFlatData* element) const { | 597 void unflatten(T* dst, const SkFlatData* element) const { |
591 element->unflatten<Traits>(dst, | 598 element->unflatten<Traits>(dst, |
592 fController->getBitmapHeap(), | 599 fController->getBitmapHeap(), |
593 fController->getTypefacePlayback()); | 600 fController->getTypefacePlayback()); |
594 } | 601 } |
595 | 602 |
596 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. | 603 // All SkFlatData* stored in fIndexedData and fHash are owned by the control
ler. |
597 SkAutoTUnref<SkFlatController> fController; | 604 SkAutoTUnref<SkFlatController> fController; |
598 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. | 605 size_t fScratchSize; // How many bytes fScratch has allocated for data itse
lf. |
599 SkFlatData* fScratch; // Owned, must be freed with sk_free. | 606 SkFlatData* fScratch; // Owned, lazily allocated, must be freed with sk_fre
e. |
600 SkOrderedWriteBuffer fWriteBuffer; | 607 SkOrderedWriteBuffer fWriteBuffer; |
601 bool fWriteBufferReady; | 608 bool fReady; |
602 | 609 |
603 // We map between SkFlatData and a 1-based integer index. | 610 // We map between SkFlatData and a 1-based integer index. |
604 int fNextIndex; | 611 int fNextIndex; |
605 | 612 |
606 // For index -> SkFlatData. fIndexedData[0] is always NULL. | 613 // For index -> SkFlatData. fIndexedData[0] is always NULL. |
607 SkTDArray<const SkFlatData*> fIndexedData; | 614 SkTDArray<const SkFlatData*> fIndexedData; |
608 | 615 |
609 // For SkFlatData -> cached SkFlatData, which has index(). | 616 // For SkFlatData -> cached SkFlatData, which has index(). |
610 SkTDynamicHash<SkFlatData, SkFlatData, | 617 SkTDynamicHash<SkFlatData, SkFlatData, |
611 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; | 618 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH
ash; |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
677 } | 684 } |
678 | 685 |
679 private: | 686 private: |
680 SkChunkAlloc fHeap; | 687 SkChunkAlloc fHeap; |
681 SkAutoTUnref<SkRefCntSet> fTypefaceSet; | 688 SkAutoTUnref<SkRefCntSet> fTypefaceSet; |
682 void* fLastAllocated; | 689 void* fLastAllocated; |
683 mutable SkTypefacePlayback fTypefacePlayback; | 690 mutable SkTypefacePlayback fTypefacePlayback; |
684 }; | 691 }; |
685 | 692 |
686 #endif | 693 #endif |
OLD | NEW |