OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 #include <new> | 7 #include <new> |
8 #include "SkBBoxHierarchy.h" | 8 #include "SkBBoxHierarchy.h" |
9 #include "SkPicturePlayback.h" | 9 #include "SkPicturePlayback.h" |
10 #include "SkPictureRecord.h" | 10 #include "SkPictureRecord.h" |
11 #include "SkPictureStateTree.h" | 11 #include "SkPictureStateTree.h" |
12 #include "SkReadBuffer.h" | 12 #include "SkReadBuffer.h" |
13 #include "SkTypeface.h" | 13 #include "SkTypeface.h" |
14 #include "SkTSort.h" | 14 #include "SkTSort.h" |
15 #include "SkWriteBuffer.h" | 15 #include "SkWriteBuffer.h" |
16 | 16 |
17 template <typename T> int SafeCount(const T* obj) { | 17 template <typename T> int SafeCount(const T* obj) { |
18 return obj ? obj->count() : 0; | 18 return obj ? obj->count() : 0; |
19 } | 19 } |
20 | 20 |
21 /* Define this to spew out a debug statement whenever we skip the remainder of | 21 /* Define this to spew out a debug statement whenever we skip the remainder of |
22 a save/restore block because a clip... command returned false (empty). | 22 a save/restore block because a clip... command returned false (empty). |
23 */ | 23 */ |
24 #define SPEW_CLIP_SKIPPINGx | 24 #define SPEW_CLIP_SKIPPINGx |
25 | 25 |
| 26 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* |
| 27 SkPicturePlayback::PlaybackReplacements::push() { |
| 28 SkDEBUGCODE(this->validate()); |
| 29 return fReplacements.push(); |
| 30 } |
| 31 |
| 32 void SkPicturePlayback::PlaybackReplacements::freeAll() { |
| 33 for (int i = 0; i < fReplacements.count(); ++i) { |
| 34 SkDELETE(fReplacements[i].fBM); |
| 35 } |
| 36 fReplacements.reset(); |
| 37 } |
| 38 |
| 39 #ifdef SK_DEBUG |
| 40 void SkPicturePlayback::PlaybackReplacements::validate() const { |
| 41 // Check that the ranges are monotonically increasing and non-overlapping |
| 42 if (fReplacements.count() > 0) { |
| 43 SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop); |
| 44 |
| 45 for (int i = 1; i < fReplacements.count(); ++i) { |
| 46 SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop); |
| 47 SkASSERT(fReplacements[i-1].fStop < fReplacements[i].fStart); |
| 48 } |
| 49 } |
| 50 } |
| 51 #endif |
| 52 |
26 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPictInfo&
info) | 53 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPictInfo&
info) |
27 : fPicture(picture) | 54 : fPicture(picture) |
28 , fInfo(info) { | 55 , fInfo(info) { |
29 this->init(); | 56 this->init(); |
30 } | 57 } |
31 | 58 |
32 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, | 59 SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, |
33 const SkPictureRecord& record, | 60 const SkPictureRecord& record, |
34 const SkPictInfo& info, | 61 const SkPictInfo& info, |
35 bool deepCopy) | 62 bool deepCopy) |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 fBitmaps = NULL; | 225 fBitmaps = NULL; |
199 fPaints = NULL; | 226 fPaints = NULL; |
200 fPictureRefs = NULL; | 227 fPictureRefs = NULL; |
201 fPictureCount = 0; | 228 fPictureCount = 0; |
202 fOpData = NULL; | 229 fOpData = NULL; |
203 fFactoryPlayback = NULL; | 230 fFactoryPlayback = NULL; |
204 fBoundingHierarchy = NULL; | 231 fBoundingHierarchy = NULL; |
205 fStateTree = NULL; | 232 fStateTree = NULL; |
206 fCachedActiveOps = NULL; | 233 fCachedActiveOps = NULL; |
207 fCurOffset = 0; | 234 fCurOffset = 0; |
| 235 fUseBBH = true; |
| 236 fStart = 0; |
| 237 fStop = 0; |
| 238 fReplacements = NULL; |
208 } | 239 } |
209 | 240 |
210 SkPicturePlayback::~SkPicturePlayback() { | 241 SkPicturePlayback::~SkPicturePlayback() { |
211 SkSafeUnref(fOpData); | 242 SkSafeUnref(fOpData); |
212 | 243 |
213 SkSafeUnref(fBitmaps); | 244 SkSafeUnref(fBitmaps); |
214 SkSafeUnref(fPaints); | 245 SkSafeUnref(fPaints); |
215 SkSafeUnref(fBoundingHierarchy); | 246 SkSafeUnref(fBoundingHierarchy); |
216 SkSafeUnref(fStateTree); | 247 SkSafeUnref(fStateTree); |
217 | 248 |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 ~SkAutoResetOpID() { | 768 ~SkAutoResetOpID() { |
738 if (NULL != fPlayback) { | 769 if (NULL != fPlayback) { |
739 fPlayback->resetOpID(); | 770 fPlayback->resetOpID(); |
740 } | 771 } |
741 } | 772 } |
742 | 773 |
743 private: | 774 private: |
744 SkPicturePlayback* fPlayback; | 775 SkPicturePlayback* fPlayback; |
745 }; | 776 }; |
746 | 777 |
| 778 // TODO: Replace with hash or pass in "lastLookedUp" hint |
| 779 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* |
| 780 SkPicturePlayback::PlaybackReplacements::lookupByStart(size_t start) { |
| 781 SkDEBUGCODE(this->validate()); |
| 782 for (int i = 0; i < fReplacements.count(); ++i) { |
| 783 if (start == fReplacements[i].fStart) { |
| 784 return &fReplacements[i]; |
| 785 } else if (start < fReplacements[i].fStart) { |
| 786 return NULL; // the ranges are monotonically increasing and non-ove
rlapping |
| 787 } |
| 788 } |
| 789 |
| 790 return NULL; |
| 791 } |
| 792 |
747 void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
{ | 793 void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
{ |
748 SkAutoResetOpID aroi(this); | 794 SkAutoResetOpID aroi(this); |
749 SkASSERT(0 == fCurOffset); | 795 SkASSERT(0 == fCurOffset); |
750 | 796 |
751 #ifdef ENABLE_TIME_DRAW | 797 #ifdef ENABLE_TIME_DRAW |
752 SkAutoTime at("SkPicture::draw", 50); | 798 SkAutoTime at("SkPicture::draw", 50); |
753 #endif | 799 #endif |
754 | 800 |
755 #ifdef SPEW_CLIP_SKIPPING | 801 #ifdef SPEW_CLIP_SKIPPING |
756 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull; | 802 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull; |
757 int opCount = 0; | 803 int opCount = 0; |
758 #endif | 804 #endif |
759 | 805 |
760 #ifdef SK_BUILD_FOR_ANDROID | 806 #ifdef SK_BUILD_FOR_ANDROID |
761 SkAutoMutexAcquire autoMutex(fDrawMutex); | 807 SkAutoMutexAcquire autoMutex(fDrawMutex); |
762 #endif | 808 #endif |
763 | 809 |
764 // kDrawComplete will be the signal that we have reached the end of | 810 // kDrawComplete will be the signal that we have reached the end of |
765 // the command stream | 811 // the command stream |
766 static const uint32_t kDrawComplete = SK_MaxU32; | 812 static const uint32_t kDrawComplete = SK_MaxU32; |
767 | 813 |
768 SkReader32 reader(fOpData->bytes(), fOpData->size()); | 814 SkReader32 reader(fOpData->bytes(), fOpData->size()); |
769 TextContainer text; | 815 TextContainer text; |
770 const SkTDArray<void*>* activeOps = NULL; | 816 const SkTDArray<void*>* activeOps = NULL; |
771 | 817 |
772 if (NULL != fStateTree && NULL != fBoundingHierarchy) { | 818 // When draw limits are enabled (i.e., 0 != fStart || 0 != fStop) the state |
773 SkRect clipBounds; | 819 // tree isn't used to pick and choose the draw operations |
774 if (canvas.getClipBounds(&clipBounds)) { | 820 if (0 == fStart && 0 == fStop) { |
775 SkIRect query; | 821 if (fUseBBH && NULL != fStateTree && NULL != fBoundingHierarchy) { |
776 clipBounds.roundOut(&query); | 822 SkRect clipBounds; |
| 823 if (canvas.getClipBounds(&clipBounds)) { |
| 824 SkIRect query; |
| 825 clipBounds.roundOut(&query); |
777 | 826 |
778 const SkPicture::OperationList& activeOpsList = this->getActiveOps(q
uery); | 827 const SkPicture::OperationList& activeOpsList = this->getActiveO
ps(query); |
779 if (activeOpsList.valid()) { | 828 if (activeOpsList.valid()) { |
780 if (0 == activeOpsList.numOps()) { | 829 if (0 == activeOpsList.numOps()) { |
781 return; // nothing to draw | 830 return; // nothing to draw |
| 831 } |
| 832 |
| 833 // Since the opList is valid we know it is our derived class |
| 834 activeOps = &((const CachedOperationList&)activeOpsList).fOp
s; |
782 } | 835 } |
783 | |
784 // Since the opList is valid we know it is our derived class | |
785 activeOps = &((const CachedOperationList&)activeOpsList).fOps; | |
786 } | 836 } |
787 } | 837 } |
788 } | 838 } |
789 | 839 |
790 SkPictureStateTree::Iterator it = (NULL == activeOps) ? | 840 SkPictureStateTree::Iterator it = (NULL == activeOps) ? |
791 SkPictureStateTree::Iterator() : | 841 SkPictureStateTree::Iterator() : |
792 fStateTree->getIterator(*activeOps, &canvas); | 842 fStateTree->getIterator(*activeOps, &canvas); |
793 | 843 |
| 844 if (0 != fStart || 0 != fStop) { |
| 845 reader.setOffset(fStart); |
| 846 uint32_t size; |
| 847 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); |
| 848 SkASSERT(SAVE_LAYER == op); |
| 849 reader.setOffset(fStart+size); |
| 850 } |
| 851 |
794 if (it.isValid()) { | 852 if (it.isValid()) { |
795 uint32_t skipTo = it.nextDraw(); | 853 uint32_t skipTo = it.nextDraw(); |
796 if (kDrawComplete == skipTo) { | 854 if (kDrawComplete == skipTo) { |
797 return; | 855 return; |
798 } | 856 } |
799 reader.setOffset(skipTo); | 857 reader.setOffset(skipTo); |
800 } | 858 } |
801 | 859 |
802 // Record this, so we can concat w/ it if we encounter a setMatrix() | 860 // Record this, so we can concat w/ it if we encounter a setMatrix() |
803 SkMatrix initialMatrix = canvas.getTotalMatrix(); | 861 SkMatrix initialMatrix = canvas.getTotalMatrix(); |
(...skipping 10 matching lines...) Expand all Loading... |
814 while (!reader.eof()) { | 872 while (!reader.eof()) { |
815 if (callback && callback->abortDrawing()) { | 873 if (callback && callback->abortDrawing()) { |
816 canvas.restoreToCount(originalSaveCount); | 874 canvas.restoreToCount(originalSaveCount); |
817 return; | 875 return; |
818 } | 876 } |
819 #ifdef SK_BUILD_FOR_ANDROID | 877 #ifdef SK_BUILD_FOR_ANDROID |
820 if (fAbortCurrentPlayback) { | 878 if (fAbortCurrentPlayback) { |
821 return; | 879 return; |
822 } | 880 } |
823 #endif | 881 #endif |
| 882 if (0 != fStart || 0 != fStop) { |
| 883 size_t offset = reader.offset() ; |
| 884 if (offset >= fStop) { |
| 885 uint32_t size; |
| 886 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); |
| 887 SkASSERT(RESTORE == op); |
| 888 return; |
| 889 } |
| 890 } |
| 891 |
| 892 if (NULL != fReplacements) { |
| 893 // Potentially replace a block of operations with a single drawBitma
p call |
| 894 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp = |
| 895 fReplacements->lookupByStart(reader.
offset()); |
| 896 if (NULL != temp) { |
| 897 SkASSERT(NULL != temp->fBM); |
| 898 SkASSERT(NULL != temp->fPaint); |
| 899 canvas.drawBitmap(*temp->fBM, temp->fPos.fX, temp->fPos.fY, temp
->fPaint); |
| 900 |
| 901 if (it.isValid()) { |
| 902 // This save is needed since the BBH will automatically issu
e |
| 903 // a restore to balanced the saveLayer we're skipping |
| 904 canvas.save(); |
| 905 // Note: This skipping only works if the client only issues |
| 906 // well behaved saveLayer calls (i.e., doesn't use |
| 907 // kMatrix_SaveFlag or kClip_SaveFlag in isolation) |
| 908 |
| 909 // At this point we know that the PictureStateTree was aimin
g |
| 910 // for some draw op within temp's saveLayer (although potent
ially |
| 911 // in a separate saveLayer nested inside it). |
| 912 // We need to skip all the operations inside temp's range |
| 913 // along with all the associated state changes but update |
| 914 // the state tree to the first operation outside temp's rang
e. |
| 915 SkASSERT(it.peekDraw() >= temp->fStart && it.peekDraw() <= t
emp->fStop); |
| 916 |
| 917 while (kDrawComplete != it.peekDraw() && it.peekDraw() <= te
mp->fStop) { |
| 918 it.skipDraw(); |
| 919 } |
| 920 |
| 921 if (kDrawComplete == it.peekDraw()) { |
| 922 break; |
| 923 } |
| 924 |
| 925 uint32_t skipTo = it.nextDraw(); |
| 926 reader.setOffset(skipTo); |
| 927 } else { |
| 928 reader.setOffset(temp->fStop); |
| 929 uint32_t size; |
| 930 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); |
| 931 SkASSERT(RESTORE == op); |
| 932 } |
| 933 continue; |
| 934 } |
| 935 } |
824 | 936 |
825 #ifdef SPEW_CLIP_SKIPPING | 937 #ifdef SPEW_CLIP_SKIPPING |
826 opCount++; | 938 opCount++; |
827 #endif | 939 #endif |
828 | 940 |
829 fCurOffset = reader.offset(); | 941 fCurOffset = reader.offset(); |
830 uint32_t size; | 942 uint32_t size; |
831 DrawType op = read_op_and_size(&reader, &size); | 943 DrawType op = read_op_and_size(&reader, &size); |
832 size_t skipTo = 0; | 944 size_t skipTo = 0; |
833 if (NOOP == op) { | 945 if (NOOP == op) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 reader.setOffset(offsetToRestore); | 1020 reader.setOffset(offsetToRestore); |
909 } | 1021 } |
910 } break; | 1022 } break; |
911 case CLIP_RRECT: { | 1023 case CLIP_RRECT: { |
912 SkRRect rrect; | 1024 SkRRect rrect; |
913 reader.readRRect(&rrect); | 1025 reader.readRRect(&rrect); |
914 uint32_t packed = reader.readInt(); | 1026 uint32_t packed = reader.readInt(); |
915 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); | 1027 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); |
916 bool doAA = ClipParams_unpackDoAA(packed); | 1028 bool doAA = ClipParams_unpackDoAA(packed); |
917 size_t offsetToRestore = reader.readInt(); | 1029 size_t offsetToRestore = reader.readInt(); |
918 SkASSERT(!offsetToRestore || \ | 1030 SkASSERT(!offsetToRestore || offsetToRestore >= reader.offset())
; |
919 offsetToRestore >= reader.offset()); | |
920 canvas.clipRRect(rrect, regionOp, doAA); | 1031 canvas.clipRRect(rrect, regionOp, doAA); |
921 if (canvas.isClipEmpty() && offsetToRestore) { | 1032 if (canvas.isClipEmpty() && offsetToRestore) { |
922 #ifdef SPEW_CLIP_SKIPPING | 1033 #ifdef SPEW_CLIP_SKIPPING |
923 skipRRect.recordSkip(offsetToRestore - reader.offset()); | 1034 skipRRect.recordSkip(offsetToRestore - reader.offset()); |
924 #endif | 1035 #endif |
925 reader.setOffset(offsetToRestore); | 1036 reader.setOffset(offsetToRestore); |
926 } | 1037 } |
927 } break; | 1038 } break; |
928 case PUSH_CULL: { | 1039 case PUSH_CULL: { |
929 const SkRect& cullRect = reader.skipT<SkRect>(); | 1040 const SkRect& cullRect = reader.skipT<SkRect>(); |
(...skipping 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1712 for (index = 0; index < fPictureCount; index++) | 1823 for (index = 0; index < fPictureCount; index++) |
1713 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer
), | 1824 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer
), |
1714 "picture%p, ", fPictureRefs[index]); | 1825 "picture%p, ", fPictureRefs[index]); |
1715 if (fPictureCount > 0) | 1826 if (fPictureCount > 0) |
1716 SkDebugf("%s0};\n", pBuffer); | 1827 SkDebugf("%s0};\n", pBuffer); |
1717 | 1828 |
1718 const_cast<SkPicturePlayback*>(this)->dumpStream(); | 1829 const_cast<SkPicturePlayback*>(this)->dumpStream(); |
1719 } | 1830 } |
1720 | 1831 |
1721 #endif | 1832 #endif |
OLD | NEW |