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

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

Issue 137433003: Convert SkWriter32 to use an SkTDArray for its internal storage. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: of course 0's fine too... 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 | « src/core/SkPaint.cpp ('k') | src/core/SkPicturePlayback.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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 template <typename Traits, typename T> 270 template <typename Traits, typename T>
271 static SkFlatData* Create(SkFlatController* controller, const T& obj, int in dex) { 271 static SkFlatData* Create(SkFlatController* controller, const T& obj, int in dex) {
272 // A buffer of 256 bytes should fit most paints, regions, and matrices. 272 // A buffer of 256 bytes should fit most paints, regions, and matrices.
273 uint32_t storage[64]; 273 uint32_t storage[64];
274 SkOrderedWriteBuffer buffer(256, storage, sizeof(storage)); 274 SkOrderedWriteBuffer buffer(storage, sizeof(storage));
275 275
276 buffer.setBitmapHeap(controller->getBitmapHeap()); 276 buffer.setBitmapHeap(controller->getBitmapHeap());
277 buffer.setTypefaceRecorder(controller->getTypefaceSet()); 277 buffer.setTypefaceRecorder(controller->getTypefaceSet());
278 buffer.setNamedFactoryRecorder(controller->getNamedFactorySet()); 278 buffer.setNamedFactoryRecorder(controller->getNamedFactorySet());
279 buffer.setFlags(controller->getWriteBufferFlags()); 279 buffer.setFlags(controller->getWriteBufferFlags());
280 280
281 Traits::flatten(buffer, obj); 281 Traits::flatten(buffer, obj);
282 uint32_t size = buffer.size(); 282 uint32_t size = buffer.size();
283 SkASSERT(SkIsAlign4(size)); 283 SkASSERT(SkIsAlign4(size));
284 284
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
359 fTopBot[0] = SK_ScalarNaN; // Mark as unwritten. 359 fTopBot[0] = SK_ScalarNaN; // Mark as unwritten.
360 fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size); 360 fChecksum = SkChecksum::Compute((uint32_t*)this->data(), size);
361 } 361 }
362 362
363 int fIndex; 363 int fIndex;
364 int32_t fFlatSize; 364 int32_t fFlatSize;
365 uint32_t fChecksum; 365 uint32_t fChecksum;
366 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,?].
367 // uint32_t flattenedData[] implicitly hangs off the end. 367 // uint32_t flattenedData[] implicitly hangs off the end.
368 368
369 template <typename T, typename Traits, int kScratchSizeGuess> friend class S kFlatDictionary; 369 template <typename T, typename Traits> friend class SkFlatDictionary;
370 }; 370 };
371 371
372 template <typename T, typename Traits, int kScratchSizeGuess=0> 372 template <typename T, typename Traits>
373 class SkFlatDictionary { 373 class SkFlatDictionary {
374 static const size_t kWriteBufferGrowthBytes = 1024;
375
376 public: 374 public:
377 explicit SkFlatDictionary(SkFlatController* controller) 375 explicit SkFlatDictionary(SkFlatController* controller)
378 : fController(SkRef(controller)) 376 : fController(SkRef(controller))
379 , fScratchSize(0)
380 , fScratch(NULL)
381 , fWriteBuffer(kWriteBufferGrowthBytes)
382 , fReady(false) { 377 , fReady(false) {
383 this->reset(); 378 this->reset();
384 } 379 }
385 380
386 /** 381 /**
387 * Clears the dictionary of all entries. However, it does NOT free the 382 * 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). 383 * memory that was allocated for each entry (that's owned by controller).
389 */ 384 */
390 void reset() { 385 void reset() {
391 fIndexedData.rewind(); 386 fIndexedData.rewind();
392 } 387 }
393 388
394 ~SkFlatDictionary() {
395 sk_free(fScratch);
396 }
397
398 int count() const { 389 int count() const {
399 SkASSERT(fHash.count() == fIndexedData.count()); 390 SkASSERT(fHash.count() == fIndexedData.count());
400 return fHash.count(); 391 return fHash.count();
401 } 392 }
402 393
403 // For testing only. Index is zero-based. 394 // For testing only. Index is zero-based.
404 const SkFlatData* operator[](int index) { 395 const SkFlatData* operator[](int index) {
405 return fIndexedData[index]; 396 return fIndexedData[index];
406 } 397 }
407 398
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 484
494 /** 485 /**
495 * Find or insert a flattened version of element into the dictionary. 486 * Find or insert a flattened version of element into the dictionary.
496 * Caller does not take ownership of the result. This will not return NULL. 487 * Caller does not take ownership of the result. This will not return NULL.
497 */ 488 */
498 const SkFlatData* findAndReturnFlat(const T& element) { 489 const SkFlatData* findAndReturnFlat(const T& element) {
499 return this->findAndReturnMutableFlat(element); 490 return this->findAndReturnMutableFlat(element);
500 } 491 }
501 492
502 private: 493 private:
503 // Layout: [ SkFlatData header, 20 bytes ] [ data ..., 4-byte aligned ] 494 // We have to delay fScratch's initialization until its first use; fControll er might not
504 static size_t SizeWithPadding(size_t flatDataSize) { 495 // be fully set up by the time we get it in the constructor.
505 SkASSERT(SkIsAlign4(flatDataSize));
506 return sizeof(SkFlatData) + flatDataSize;
507 }
508
509 // Allocate a new scratch SkFlatData. Must be sk_freed.
510 static SkFlatData* AllocScratch(size_t scratchSize) {
511 return (SkFlatData*) sk_malloc_throw(SizeWithPadding(scratchSize));
512 }
513
514 // We have to delay fWriteBuffer's initialization until its first use; fCont roller might not
515 // be fully set up by the time we get it in the constructor. We also delay a llocating fScratch
516 // to avoid unnecessary heap allocations, since we're paying the price of th e conditional
517 // anyway.
518 void lazyInit() { 496 void lazyInit() {
519 if (fReady) { 497 if (fReady) {
520 return; 498 return;
521 } 499 }
522 500
523 fScratchSize = kScratchSizeGuess;
524 fScratch = AllocScratch(fScratchSize);
525
526 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev er what you want. 501 // Without a bitmap heap, we'll flatten bitmaps into paints. That's nev er what you want.
527 SkASSERT(fController->getBitmapHeap() != NULL); 502 SkASSERT(fController->getBitmapHeap() != NULL);
528 fWriteBuffer.setBitmapHeap(fController->getBitmapHeap()); 503 fScratch.setBitmapHeap(fController->getBitmapHeap());
529 fWriteBuffer.setTypefaceRecorder(fController->getTypefaceSet()); 504 fScratch.setTypefaceRecorder(fController->getTypefaceSet());
530 fWriteBuffer.setNamedFactoryRecorder(fController->getNamedFactorySet()); 505 fScratch.setNamedFactoryRecorder(fController->getNamedFactorySet());
531 fWriteBuffer.setFlags(fController->getWriteBufferFlags()); 506 fScratch.setFlags(fController->getWriteBufferFlags());
532 fReady = true; 507 fReady = true;
533 } 508 }
534 509
535 // As findAndReturnFlat, but returns a mutable pointer for internal use. 510 // As findAndReturnFlat, but returns a mutable pointer for internal use.
536 SkFlatData* findAndReturnMutableFlat(const T& element) { 511 SkFlatData* findAndReturnMutableFlat(const T& element) {
537 // Only valid until the next call to resetScratch(). 512 // Only valid until the next call to resetScratch().
538 const SkFlatData& scratch = this->resetScratch(element, this->count()+1) ; 513 const SkFlatData& scratch = this->resetScratch(element, this->count()+1) ;
539 514
540 SkFlatData* candidate = fHash.find(scratch); 515 SkFlatData* candidate = fHash.find(scratch);
541 if (candidate != NULL) return candidate; 516 if (candidate != NULL) return candidate;
542 517
543 SkFlatData* detached = this->detachScratch(); 518 SkFlatData* detached = this->detachScratch();
544 fHash.add(detached); 519 fHash.add(detached);
545 *fIndexedData.append() = detached; 520 *fIndexedData.append() = detached;
546 SkASSERT(fIndexedData.top()->index() == this->count()); 521 SkASSERT(fIndexedData.top()->index() == this->count());
547 return detached; 522 return detached;
548 } 523 }
549 524
550 // This reference is valid only until the next call to resetScratch() or det achScratch(). 525 // This reference is valid only until the next call to resetScratch() or det achScratch().
551 const SkFlatData& resetScratch(const T& element, int index) { 526 const SkFlatData& resetScratch(const T& element, int index) {
552 this->lazyInit(); 527 this->lazyInit();
553 528
554 // Flatten element into fWriteBuffer (using fScratch as storage). 529 // Layout of fScratch: [ SkFlatData header, 20 bytes ] [ data ..., 4-byt e aligned ]
555 fWriteBuffer.reset(fScratch->data(), fScratchSize); 530 fScratch.reset();
556 Traits::flatten(fWriteBuffer, element); 531 fScratch.reserve(sizeof(SkFlatData));
557 const size_t bytesWritten = fWriteBuffer.bytesWritten(); 532 Traits::flatten(fScratch, element);
533 const size_t dataSize = fScratch.bytesWritten() - sizeof(SkFlatData);
558 534
559 // If all the flattened bytes fit into fScratch, we can skip a call to w riteToMemory. 535 // Reinterpret data in fScratch as an SkFlatData.
560 if (!fWriteBuffer.wroteOnlyToStorage()) { 536 SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArr ay();
561 SkASSERT(bytesWritten > fScratchSize); 537 SkASSERT(scratch != NULL);
562 // It didn't all fit. Copy into a larger replacement SkFlatData. 538 scratch->stampHeader(index, dataSize);
563 // We can't just realloc because it might move the pointer and confu se writeToMemory. 539 return *scratch;
564 SkFlatData* larger = AllocScratch(bytesWritten);
565 fWriteBuffer.writeToMemory(larger->data());
566
567 // Carry on with this larger scratch to minimize the likelihood of f uture resizing.
568 sk_free(fScratch);
569 fScratchSize = bytesWritten;
570 fScratch = larger;
571 }
572
573 // The data is in fScratch now but we need to stamp its header.
574 fScratch->stampHeader(index, bytesWritten);
575 return *fScratch;
576 } 540 }
577 541
578 // This result is owned by fController and lives as long as it does (unless unalloc'd). 542 // This result is owned by fController and lives as long as it does (unless unalloc'd).
579 SkFlatData* detachScratch() { 543 SkFlatData* detachScratch() {
580 // Allocate a new SkFlatData exactly big enough to hold our current scra tch. 544 // Allocate a new SkFlatData exactly big enough to hold our current scra tch.
581 // We use the controller for this allocation to extend the allocation's lifetime and allow 545 // We use the controller for this allocation to extend the allocation's lifetime and allow
582 // the controller to do whatever memory management it wants. 546 // the controller to do whatever memory management it wants.
583 SkASSERT(fScratch != NULL); 547 SkFlatData* detached = (SkFlatData*)fController->allocThrow(fScratch.byt esWritten());
584 const size_t paddedSize = SizeWithPadding(fScratch->flatSize());
585 SkFlatData* detached = (SkFlatData*)fController->allocThrow(paddedSize);
586 548
587 // Copy scratch into the new SkFlatData. 549 // Copy scratch into the new SkFlatData.
588 memcpy(detached, fScratch, paddedSize); 550 SkFlatData* scratch = (SkFlatData*)fScratch.getWriter32()->contiguousArr ay();
551 SkASSERT(scratch != NULL);
552 memcpy(detached, scratch, fScratch.bytesWritten());
589 553
590 // We can now reuse fScratch, and detached will live until fController d ies. 554 // We can now reuse fScratch, and detached will live until fController d ies.
591 return detached; 555 return detached;
592 } 556 }
593 557
594 void unflatten(T* dst, const SkFlatData* element) const { 558 void unflatten(T* dst, const SkFlatData* element) const {
595 element->unflatten<Traits>(dst, 559 element->unflatten<Traits>(dst,
596 fController->getBitmapHeap(), 560 fController->getBitmapHeap(),
597 fController->getTypefacePlayback()); 561 fController->getTypefacePlayback());
598 } 562 }
599 563
600 // All SkFlatData* stored in fIndexedData and fHash are owned by the control ler. 564 // All SkFlatData* stored in fIndexedData and fHash are owned by the control ler.
601 SkAutoTUnref<SkFlatController> fController; 565 SkAutoTUnref<SkFlatController> fController;
602 size_t fScratchSize; // How many bytes fScratch has allocated for data itse lf. 566 SkOrderedWriteBuffer fScratch;
603 SkFlatData* fScratch; // Owned, lazily allocated, must be freed with sk_fre e.
604 SkOrderedWriteBuffer fWriteBuffer;
605 bool fReady; 567 bool fReady;
606 568
607 // For index -> SkFlatData. 0-based, while all indices in the API are 1-bas ed. Careful! 569 // For index -> SkFlatData. 0-based, while all indices in the API are 1-bas ed. Careful!
608 SkTDArray<const SkFlatData*> fIndexedData; 570 SkTDArray<const SkFlatData*> fIndexedData;
609 571
610 // For SkFlatData -> cached SkFlatData, which has index(). 572 // For SkFlatData -> cached SkFlatData, which has index().
611 SkTDynamicHash<SkFlatData, SkFlatData, 573 SkTDynamicHash<SkFlatData, SkFlatData,
612 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH ash; 574 SkFlatData::Identity, SkFlatData::Hash, SkFlatData::Equal> fH ash;
613 }; 575 };
614 576
615 /////////////////////////////////////////////////////////////////////////////// 577 ///////////////////////////////////////////////////////////////////////////////
616 // Some common dictionaries are defined here for both reference and convenience 578 // Some common dictionaries are defined here for both reference and convenience
617 /////////////////////////////////////////////////////////////////////////////// 579 ///////////////////////////////////////////////////////////////////////////////
618 580
619 struct SkMatrixTraits { 581 struct SkMatrixTraits {
620 static void flatten(SkOrderedWriteBuffer& buffer, const SkMatrix& matrix) { 582 static void flatten(SkOrderedWriteBuffer& buffer, const SkMatrix& matrix) {
621 buffer.getWriter32()->writeMatrix(matrix); 583 buffer.getWriter32()->writeMatrix(matrix);
622 } 584 }
623 static void unflatten(SkOrderedReadBuffer& buffer, SkMatrix* matrix) { 585 static void unflatten(SkOrderedReadBuffer& buffer, SkMatrix* matrix) {
624 buffer.getReader32()->readMatrix(matrix); 586 buffer.getReader32()->readMatrix(matrix);
625 } 587 }
626 }; 588 };
627 typedef SkFlatDictionary<SkMatrix, SkMatrixTraits, 36> SkMatrixDictionary; 589 typedef SkFlatDictionary<SkMatrix, SkMatrixTraits> SkMatrixDictionary;
628 590
629 591
630 struct SkRegionTraits { 592 struct SkRegionTraits {
631 static void flatten(SkOrderedWriteBuffer& buffer, const SkRegion& region) { 593 static void flatten(SkOrderedWriteBuffer& buffer, const SkRegion& region) {
632 buffer.getWriter32()->writeRegion(region); 594 buffer.getWriter32()->writeRegion(region);
633 } 595 }
634 static void unflatten(SkOrderedReadBuffer& buffer, SkRegion* region) { 596 static void unflatten(SkOrderedReadBuffer& buffer, SkRegion* region) {
635 buffer.getReader32()->readRegion(region); 597 buffer.getReader32()->readRegion(region);
636 } 598 }
637 }; 599 };
638 typedef SkFlatDictionary<SkRegion, SkRegionTraits> SkRegionDictionary; 600 typedef SkFlatDictionary<SkRegion, SkRegionTraits> SkRegionDictionary;
639 601
640 602
641 struct SkPaintTraits { 603 struct SkPaintTraits {
642 static void flatten(SkOrderedWriteBuffer& buffer, const SkPaint& paint) { 604 static void flatten(SkOrderedWriteBuffer& buffer, const SkPaint& paint) {
643 paint.flatten(buffer); 605 paint.flatten(buffer);
644 } 606 }
645 static void unflatten(SkOrderedReadBuffer& buffer, SkPaint* paint) { 607 static void unflatten(SkOrderedReadBuffer& buffer, SkPaint* paint) {
646 paint->unflatten(buffer); 608 paint->unflatten(buffer);
647 } 609 }
648 }; 610 };
649 typedef SkFlatDictionary<SkPaint, SkPaintTraits, 512> SkPaintDictionary; 611 typedef SkFlatDictionary<SkPaint, SkPaintTraits> SkPaintDictionary;
650 612
651 class SkChunkFlatController : public SkFlatController { 613 class SkChunkFlatController : public SkFlatController {
652 public: 614 public:
653 SkChunkFlatController(size_t minSize) 615 SkChunkFlatController(size_t minSize)
654 : fHeap(minSize) 616 : fHeap(minSize)
655 , fTypefaceSet(SkNEW(SkRefCntSet)) 617 , fTypefaceSet(SkNEW(SkRefCntSet))
656 , fLastAllocated(NULL) { 618 , fLastAllocated(NULL) {
657 this->setTypefaceSet(fTypefaceSet); 619 this->setTypefaceSet(fTypefaceSet);
658 this->setTypefacePlayback(&fTypefacePlayback); 620 this->setTypefacePlayback(&fTypefacePlayback);
659 } 621 }
(...skipping 18 matching lines...) Expand all
678 } 640 }
679 641
680 private: 642 private:
681 SkChunkAlloc fHeap; 643 SkChunkAlloc fHeap;
682 SkAutoTUnref<SkRefCntSet> fTypefaceSet; 644 SkAutoTUnref<SkRefCntSet> fTypefaceSet;
683 void* fLastAllocated; 645 void* fLastAllocated;
684 mutable SkTypefacePlayback fTypefacePlayback; 646 mutable SkTypefacePlayback fTypefacePlayback;
685 }; 647 };
686 648
687 #endif 649 #endif
OLDNEW
« no previous file with comments | « src/core/SkPaint.cpp ('k') | src/core/SkPicturePlayback.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698