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

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

Issue 131483005: Allocate SkPictureFlat::fScratch lazily. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | 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 358 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698