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

Side by Side Diff: src/core/SkPicturePlayback.cpp

Issue 12545009: Adding option in SkPicture to record device-space bounds of draw commands. (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 7 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
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 #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
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(&regionBytes); 139 regions = fPlayback->regions(&regionBytes);
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698