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 #include "SkPicturePlayback.h" | 8 #include "SkPicturePlayback.h" |
9 #include "SkPictureRecord.h" | 9 #include "SkPictureRecord.h" |
10 #include "SkTypeface.h" | 10 #include "SkTypeface.h" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 for (int i = 0; i < fPictureCount; i++) { | 117 for (int i = 0; i < fPictureCount; i++) { |
118 if (deepCopy) { | 118 if (deepCopy) { |
119 fPictureRefs[i] = pictures[i]->clone(); | 119 fPictureRefs[i] = pictures[i]->clone(); |
120 } else { | 120 } else { |
121 fPictureRefs[i] = pictures[i]; | 121 fPictureRefs[i] = pictures[i]; |
122 fPictureRefs[i]->ref(); | 122 fPictureRefs[i]->ref(); |
123 } | 123 } |
124 } | 124 } |
125 } | 125 } |
126 | 126 |
127 #if SK_RECORD_BOUNDS_IN_PICTURE | |
128 fHasRecordedBounds = true; | |
129 #else | |
130 fHasRecordedBounds = false; | |
131 #endif | |
132 | |
127 #ifdef SK_DEBUG_SIZE | 133 #ifdef SK_DEBUG_SIZE |
128 int overall = fPlayback->size(&overallBytes); | 134 int overall = fPlayback->size(&overallBytes); |
129 bitmaps = fPlayback->bitmaps(&bitmapBytes); | 135 bitmaps = fPlayback->bitmaps(&bitmapBytes); |
130 paints = fPlayback->paints(&paintBytes); | 136 paints = fPlayback->paints(&paintBytes); |
131 paths = fPlayback->paths(&pathBytes); | 137 paths = fPlayback->paths(&pathBytes); |
132 pictures = fPlayback->pictures(&pictureBytes); | 138 pictures = fPlayback->pictures(&pictureBytes); |
133 regions = fPlayback->regions(®ionBytes); | 139 regions = fPlayback->regions(®ionBytes); |
134 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall); | 140 SkDebugf("playback size %zd (objects:%d) ", overallBytes, overall); |
135 if (bitmaps != 0) | 141 if (bitmaps != 0) |
136 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps); | 142 SkDebugf("bitmaps size %zd (bitmaps:%d) ", bitmapBytes, bitmaps); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
169 | 175 |
170 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get())); | 176 fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get())); |
171 fPathHeap.reset(SkSafeRef(src.fPathHeap.get())); | 177 fPathHeap.reset(SkSafeRef(src.fPathHeap.get())); |
172 | 178 |
173 fMatrices = SkSafeRef(src.fMatrices); | 179 fMatrices = SkSafeRef(src.fMatrices); |
174 fRegions = SkSafeRef(src.fRegions); | 180 fRegions = SkSafeRef(src.fRegions); |
175 fOpData = SkSafeRef(src.fOpData); | 181 fOpData = SkSafeRef(src.fOpData); |
176 | 182 |
177 fBoundingHierarchy = src.fBoundingHierarchy; | 183 fBoundingHierarchy = src.fBoundingHierarchy; |
178 fStateTree = src.fStateTree; | 184 fStateTree = src.fStateTree; |
179 | 185 fHasRecordedBounds = src.fHasRecordedBounds; |
180 SkSafeRef(fBoundingHierarchy); | 186 SkSafeRef(fBoundingHierarchy); |
181 SkSafeRef(fStateTree); | 187 SkSafeRef(fStateTree); |
182 | 188 |
183 if (deepCopyInfo) { | 189 if (deepCopyInfo) { |
184 int paintCount = SafeCount(src.fPaints); | 190 int paintCount = SafeCount(src.fPaints); |
185 | 191 |
186 if (src.fBitmaps) { | 192 if (src.fBitmaps) { |
187 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src. fBitmaps->count()); | 193 fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src. fBitmaps->count()); |
188 } | 194 } |
189 | 195 |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
263 fBitmaps = NULL; | 269 fBitmaps = NULL; |
264 fMatrices = NULL; | 270 fMatrices = NULL; |
265 fPaints = NULL; | 271 fPaints = NULL; |
266 fPictureRefs = NULL; | 272 fPictureRefs = NULL; |
267 fRegions = NULL; | 273 fRegions = NULL; |
268 fPictureCount = 0; | 274 fPictureCount = 0; |
269 fOpData = NULL; | 275 fOpData = NULL; |
270 fFactoryPlayback = NULL; | 276 fFactoryPlayback = NULL; |
271 fBoundingHierarchy = NULL; | 277 fBoundingHierarchy = NULL; |
272 fStateTree = NULL; | 278 fStateTree = NULL; |
279 fHasRecordedBounds = false; | |
273 } | 280 } |
274 | 281 |
275 SkPicturePlayback::~SkPicturePlayback() { | 282 SkPicturePlayback::~SkPicturePlayback() { |
276 fOpData->unref(); | 283 fOpData->unref(); |
277 | 284 |
278 SkSafeUnref(fBitmaps); | 285 SkSafeUnref(fBitmaps); |
279 SkSafeUnref(fMatrices); | 286 SkSafeUnref(fMatrices); |
280 SkSafeUnref(fPaints); | 287 SkSafeUnref(fPaints); |
281 SkSafeUnref(fRegions); | 288 SkSafeUnref(fRegions); |
282 SkSafeUnref(fBoundingHierarchy); | 289 SkSafeUnref(fBoundingHierarchy); |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
585 for (size_t i = 0; i < size; ++i) { | 592 for (size_t i = 0; i < size; ++i) { |
586 buffer.readRegion(&fRegions->writableAt(i)); | 593 buffer.readRegion(&fRegions->writableAt(i)); |
587 } | 594 } |
588 } break; | 595 } break; |
589 } | 596 } |
590 } | 597 } |
591 | 598 |
592 SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info, | 599 SkPicturePlayback::SkPicturePlayback(SkStream* stream, const SkPictInfo& info, |
593 SkPicture::InstallPixelRefProc proc) { | 600 SkPicture::InstallPixelRefProc proc) { |
594 this->init(); | 601 this->init(); |
595 | 602 #if SK_RECORD_BOUNDS_IN_PICTURE |
603 fHasRecordedBounds = SkToBool(info.fFlags & SkPictInfo::kHasRecordedBounds_F lag); | |
604 #else | |
605 // Can't handle skps with recorded bounds in a build that does support them. | |
Tom Hudson
2013/05/14 17:00:49
Typo: does *not* support them?
| |
606 SkASSERT(false == SkToBool(info.fFlags & SkPictInfo::kHasRecordedBounds_Flag )); | |
607 fHasRecordedBounds = false; | |
608 #endif | |
596 for (;;) { | 609 for (;;) { |
597 uint32_t tag = stream->readU32(); | 610 uint32_t tag = stream->readU32(); |
598 if (PICT_EOF_TAG == tag) { | 611 if (PICT_EOF_TAG == tag) { |
599 break; | 612 break; |
600 } | 613 } |
601 | 614 |
602 uint32_t size = stream->readU32(); | 615 uint32_t size = stream->readU32(); |
603 this->parseStreamTag(stream, info, tag, size, proc); | 616 this->parseStreamTag(stream, info, tag, size, proc); |
604 } | 617 } |
605 } | 618 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
649 *size = 0; | 662 *size = 0; |
650 } else { | 663 } else { |
651 UNPACK_8_24(temp, op, *size); | 664 UNPACK_8_24(temp, op, *size); |
652 if (MASK_24 == *size) { | 665 if (MASK_24 == *size) { |
653 *size = reader->readInt(); | 666 *size = reader->readInt(); |
654 } | 667 } |
655 } | 668 } |
656 return (DrawType) op; | 669 return (DrawType) op; |
657 } | 670 } |
658 | 671 |
672 // Sets 'bounds' to represent the clip bounds of the playback canvas, | |
673 // expressed in the recording device's coordinate space. | |
674 // returns true if the bounds are not empty. | |
675 static inline bool get_intial_clip_bounds(const SkCanvas& canvas, SkIRect* bound s) { | |
676 SkASSERT(NULL != bounds); | |
677 SkRect clipBounds; | |
678 if (canvas.getClipBounds(&clipBounds)) { | |
679 clipBounds.roundOut(bounds); | |
680 } else { | |
681 bounds->setEmpty(); | |
682 return false; | |
683 } | |
684 return !bounds->isEmpty(); | |
685 } | |
686 | |
687 class SkDisableQuickRejectInScope { | |
688 public: | |
689 SkDisableQuickRejectInScope() { | |
690 fCanvas = NULL; | |
Tom Hudson
2013/05/14 17:00:49
Why not pass a canvas to the constructor, and avoi
| |
691 } | |
692 void set(SkCanvas* canvas) { | |
693 if (canvas->fQuickRejectEnabled == true) { | |
Tom Hudson
2013/05/14 17:00:49
// protect against nested Disables
| |
694 fCanvas = canvas; | |
695 fCanvas->fQuickRejectEnabled = false; | |
696 } | |
697 } | |
698 | |
699 ~SkDisableQuickRejectInScope() { | |
700 if (fCanvas) { | |
701 fCanvas->fQuickRejectEnabled = true; | |
702 } | |
703 } | |
704 private: | |
705 SkCanvas* fCanvas; | |
706 }; | |
707 | |
659 void SkPicturePlayback::draw(SkCanvas& canvas) { | 708 void SkPicturePlayback::draw(SkCanvas& canvas) { |
660 #ifdef ENABLE_TIME_DRAW | 709 #ifdef ENABLE_TIME_DRAW |
661 SkAutoTime at("SkPicture::draw", 50); | 710 SkAutoTime at("SkPicture::draw", 50); |
662 #endif | 711 #endif |
663 | 712 |
664 #ifdef SPEW_CLIP_SKIPPING | 713 #ifdef SPEW_CLIP_SKIPPING |
665 SkipClipRec skipRect, skipRRect, skipRegion, skipPath; | 714 SkipClipRec skipRect, skipRRect, skipRegion, skipPath; |
666 #endif | 715 #endif |
667 | 716 |
668 #ifdef SK_BUILD_FOR_ANDROID | 717 #ifdef SK_BUILD_FOR_ANDROID |
669 SkAutoMutexAcquire autoMutex(fDrawMutex); | 718 SkAutoMutexAcquire autoMutex(fDrawMutex); |
670 #endif | 719 #endif |
671 | 720 |
672 // kDrawComplete will be the signal that we have reached the end of | 721 // kDrawComplete will be the signal that we have reached the end of |
673 // the command stream | 722 // the command stream |
674 static const uint32_t kDrawComplete = SK_MaxU32; | 723 static const uint32_t kDrawComplete = SK_MaxU32; |
675 | 724 |
676 SkReader32 reader(fOpData->bytes(), fOpData->size()); | 725 SkReader32 reader(fOpData->bytes(), fOpData->size()); |
677 TextContainer text; | 726 TextContainer text; |
678 SkTDArray<void*> results; | 727 SkTDArray<void*> results; |
679 | 728 |
729 #if SK_RECORD_BOUNDS_IN_PICTURE | |
730 bool initialClipBoundsSet = false; | |
731 #endif | |
732 SkIRect initialClipBounds; // only computed if needed | |
680 if (NULL != fStateTree && NULL != fBoundingHierarchy) { | 733 if (NULL != fStateTree && NULL != fBoundingHierarchy) { |
681 SkRect clipBounds; | 734 if (!get_intial_clip_bounds(canvas, &initialClipBounds)) { |
682 if (canvas.getClipBounds(&clipBounds)) { | 735 return; |
Tom Hudson
2013/05/14 17:00:49
You now have an early return where it looks like y
| |
683 SkIRect query; | |
684 clipBounds.roundOut(&query); | |
685 fBoundingHierarchy->search(query, &results); | |
686 if (results.count() == 0) { | |
687 return; | |
688 } | |
689 SkTQSort<SkPictureStateTree::Draw>( | |
690 reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()), | |
691 reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1)); | |
692 } | 736 } |
737 fBoundingHierarchy->search(initialClipBounds, &results); | |
738 if (results.count() == 0) { | |
739 return; | |
740 } | |
741 #if SK_RECORD_BOUNDS_IN_PICTURE | |
742 initialClipBoundsSet = true; | |
743 #endif | |
744 SkTQSort<SkPictureStateTree::Draw>( | |
745 reinterpret_cast<SkPictureStateTree::Draw**>(results.begin()), | |
746 reinterpret_cast<SkPictureStateTree::Draw**>(results.end()-1)); | |
693 } | 747 } |
694 | 748 |
749 #if SK_RECORD_BOUNDS_IN_PICTURE | |
750 SkDisableQuickRejectInScope dqr; | |
751 if (fHasRecordedBounds) { | |
752 // Temporarily disable quickReject testing on 'canvas' | |
753 // because it is redundant with early bounds check. | |
Tom Hudson
2013/05/14 17:00:49
Nit: Second line of this comment is more useful th
| |
754 dqr.set(&canvas); | |
Tom Hudson
2013/05/14 17:00:49
Ugh, given that you need this to be conditionally
| |
755 if (!initialClipBoundsSet && !get_intial_clip_bounds(canvas, &initialCli pBounds)) { | |
756 return; | |
757 } | |
758 initialClipBoundsSet = true; | |
759 } | |
760 #endif | |
761 | |
695 SkPictureStateTree::Iterator it = (NULL == fStateTree) ? | 762 SkPictureStateTree::Iterator it = (NULL == fStateTree) ? |
696 SkPictureStateTree::Iterator() : | 763 SkPictureStateTree::Iterator() : |
697 fStateTree->getIterator(results, &canvas); | 764 fStateTree->getIterator(results, &canvas); |
698 | 765 |
699 if (it.isValid()) { | 766 if (it.isValid()) { |
700 uint32_t skipTo = it.draw(); | 767 uint32_t skipTo = it.draw(); |
701 if (kDrawComplete == skipTo) { | 768 if (kDrawComplete == skipTo) { |
702 return; | 769 return; |
703 } | 770 } |
704 reader.setOffset(skipTo); | 771 reader.setOffset(skipTo); |
(...skipping 15 matching lines...) Expand all Loading... | |
720 | 787 |
721 size_t curOffset = reader.offset(); | 788 size_t curOffset = reader.offset(); |
722 uint32_t size; | 789 uint32_t size; |
723 DrawType op = read_op_and_size(&reader, &size); | 790 DrawType op = read_op_and_size(&reader, &size); |
724 size_t skipTo = 0; | 791 size_t skipTo = 0; |
725 #ifdef SK_DEVELOPER | 792 #ifdef SK_DEVELOPER |
726 // TODO: once chunk sizes are in all .skps just use | 793 // TODO: once chunk sizes are in all .skps just use |
727 // "curOffset + size" | 794 // "curOffset + size" |
728 skipTo = this->preDraw(curOffset, op); | 795 skipTo = this->preDraw(curOffset, op); |
729 #endif | 796 #endif |
730 if (0 == skipTo && NOOP == op) { | 797 if (0 == skipTo) { |
731 // NOOPs are to be ignored - do not propagate them any further | 798 if (NOOP == op) { |
732 skipTo = curOffset + size; | 799 // NOOPs are to be ignored - do not propagate them any further |
800 skipTo = curOffset + size; | |
801 } | |
802 #if SK_RECORD_BOUNDS_IN_PICTURE | |
803 else if (fHasRecordedBounds && SkPictureRecord::canRecordBounds(op)) { | |
804 const SkIRect& clippedBounds = reader.skipT<SkIRect>(); | |
805 // recording canvas device bounds are in the same coordinate spa ce | |
806 // as local clip bounds at start of playback. | |
807 SkASSERT(initialClipBoundsSet); | |
808 if (!SkIRect::Intersects(clippedBounds, initialClipBounds)) { | |
809 skipTo = curOffset + size; | |
810 } | |
811 } | |
812 #endif | |
733 } | 813 } |
734 | 814 |
735 if (0 != skipTo) { | 815 if (0 != skipTo) { |
736 if (it.isValid()) { | 816 if (it.isValid()) { |
737 // If using a bounding box hierarchy, advance the state tree | 817 // If using a bounding box hierarchy, advance the state tree |
738 // iterator until at or after skipTo | 818 // iterator until at or after skipTo |
739 uint32_t adjustedSkipTo; | 819 uint32_t adjustedSkipTo; |
740 do { | 820 do { |
741 adjustedSkipTo = it.draw(); | 821 adjustedSkipTo = it.draw(); |
742 } while (adjustedSkipTo < skipTo); | 822 } while (adjustedSkipTo < skipTo); |
(...skipping 844 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1587 for (index = 0; index < fRegionCount; index++) | 1667 for (index = 0; index < fRegionCount; index++) |
1588 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer ), | 1668 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer ), |
1589 "region%p, ", &fRegions[index]); | 1669 "region%p, ", &fRegions[index]); |
1590 if (fRegionCount > 0) | 1670 if (fRegionCount > 0) |
1591 SkDebugf("%s0};\n", pBuffer); | 1671 SkDebugf("%s0};\n", pBuffer); |
1592 | 1672 |
1593 const_cast<SkPicturePlayback*>(this)->dumpStream(); | 1673 const_cast<SkPicturePlayback*>(this)->dumpStream(); |
1594 } | 1674 } |
1595 | 1675 |
1596 #endif | 1676 #endif |
OLD | NEW |