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 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |