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" |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 fBitmaps = NULL; | 198 fBitmaps = NULL; |
199 fPaints = NULL; | 199 fPaints = NULL; |
200 fPictureRefs = NULL; | 200 fPictureRefs = NULL; |
201 fPictureCount = 0; | 201 fPictureCount = 0; |
202 fOpData = NULL; | 202 fOpData = NULL; |
203 fFactoryPlayback = NULL; | 203 fFactoryPlayback = NULL; |
204 fBoundingHierarchy = NULL; | 204 fBoundingHierarchy = NULL; |
205 fStateTree = NULL; | 205 fStateTree = NULL; |
206 fCachedActiveOps = NULL; | 206 fCachedActiveOps = NULL; |
207 fCurOffset = 0; | 207 fCurOffset = 0; |
| 208 fUseBBH = true; |
| 209 fStart = 0; |
| 210 fStop = 0; |
| 211 fReplacements = NULL; |
208 } | 212 } |
209 | 213 |
210 SkPicturePlayback::~SkPicturePlayback() { | 214 SkPicturePlayback::~SkPicturePlayback() { |
211 SkSafeUnref(fOpData); | 215 SkSafeUnref(fOpData); |
212 | 216 |
213 SkSafeUnref(fBitmaps); | 217 SkSafeUnref(fBitmaps); |
214 SkSafeUnref(fPaints); | 218 SkSafeUnref(fPaints); |
215 SkSafeUnref(fBoundingHierarchy); | 219 SkSafeUnref(fBoundingHierarchy); |
216 SkSafeUnref(fStateTree); | 220 SkSafeUnref(fStateTree); |
217 | 221 |
(...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 ~SkAutoResetOpID() { | 741 ~SkAutoResetOpID() { |
738 if (NULL != fPlayback) { | 742 if (NULL != fPlayback) { |
739 fPlayback->resetOpID(); | 743 fPlayback->resetOpID(); |
740 } | 744 } |
741 } | 745 } |
742 | 746 |
743 private: | 747 private: |
744 SkPicturePlayback* fPlayback; | 748 SkPicturePlayback* fPlayback; |
745 }; | 749 }; |
746 | 750 |
| 751 // TODO: Replace with hash or pass in "lastLookedUp" hint |
| 752 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* |
| 753 SkPicturePlayback::PlaybackReplacements::lookupByStart(size_t start) { |
| 754 SkDEBUGCODE(this->validate()); |
| 755 for (int i = 0; i < fReplacements.count(); ++i) { |
| 756 if (start == fReplacements[i].fStart) { |
| 757 return &fReplacements[i]; |
| 758 } else if (start < fReplacements[i].fStart) { |
| 759 return NULL; // the ranges are monotonically increasing and non-ove
rlapping |
| 760 } |
| 761 } |
| 762 |
| 763 return NULL; |
| 764 } |
| 765 |
747 void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
{ | 766 void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback)
{ |
748 SkAutoResetOpID aroi(this); | 767 SkAutoResetOpID aroi(this); |
749 SkASSERT(0 == fCurOffset); | 768 SkASSERT(0 == fCurOffset); |
750 | 769 |
751 #ifdef ENABLE_TIME_DRAW | 770 #ifdef ENABLE_TIME_DRAW |
752 SkAutoTime at("SkPicture::draw", 50); | 771 SkAutoTime at("SkPicture::draw", 50); |
753 #endif | 772 #endif |
754 | 773 |
755 #ifdef SPEW_CLIP_SKIPPING | 774 #ifdef SPEW_CLIP_SKIPPING |
756 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull; | 775 SkipClipRec skipRect, skipRRect, skipRegion, skipPath, skipCull; |
757 int opCount = 0; | 776 int opCount = 0; |
758 #endif | 777 #endif |
759 | 778 |
760 #ifdef SK_BUILD_FOR_ANDROID | 779 #ifdef SK_BUILD_FOR_ANDROID |
761 SkAutoMutexAcquire autoMutex(fDrawMutex); | 780 SkAutoMutexAcquire autoMutex(fDrawMutex); |
762 #endif | 781 #endif |
763 | 782 |
764 // kDrawComplete will be the signal that we have reached the end of | 783 // kDrawComplete will be the signal that we have reached the end of |
765 // the command stream | 784 // the command stream |
766 static const uint32_t kDrawComplete = SK_MaxU32; | 785 static const uint32_t kDrawComplete = SK_MaxU32; |
767 | 786 |
768 SkReader32 reader(fOpData->bytes(), fOpData->size()); | 787 SkReader32 reader(fOpData->bytes(), fOpData->size()); |
769 TextContainer text; | 788 TextContainer text; |
770 const SkTDArray<void*>* activeOps = NULL; | 789 const SkTDArray<void*>* activeOps = NULL; |
771 | 790 |
772 if (NULL != fStateTree && NULL != fBoundingHierarchy) { | 791 // When draw limits are enabled (i.e., 0 != fStart || 0 != fStop) the state |
773 SkRect clipBounds; | 792 // tree isn't used to pick and choose the draw operations |
774 if (canvas.getClipBounds(&clipBounds)) { | 793 if (0 == fStart && 0 == fStop) { |
775 SkIRect query; | 794 if (fUseBBH && NULL != fStateTree && NULL != fBoundingHierarchy) { |
776 clipBounds.roundOut(&query); | 795 SkRect clipBounds; |
| 796 if (canvas.getClipBounds(&clipBounds)) { |
| 797 SkIRect query; |
| 798 clipBounds.roundOut(&query); |
777 | 799 |
778 const SkPicture::OperationList& activeOpsList = this->getActiveOps(q
uery); | 800 const SkPicture::OperationList& activeOpsList = this->getActiveO
ps(query); |
779 if (activeOpsList.valid()) { | 801 if (activeOpsList.valid()) { |
780 if (0 == activeOpsList.numOps()) { | 802 if (0 == activeOpsList.numOps()) { |
781 return; // nothing to draw | 803 return; // nothing to draw |
| 804 } |
| 805 |
| 806 // Since the opList is valid we know it is our derived class |
| 807 activeOps = &((const CachedOperationList&)activeOpsList).fOp
s; |
782 } | 808 } |
783 | |
784 // Since the opList is valid we know it is our derived class | |
785 activeOps = &((const CachedOperationList&)activeOpsList).fOps; | |
786 } | 809 } |
787 } | 810 } |
788 } | 811 } |
789 | 812 |
790 SkPictureStateTree::Iterator it = (NULL == activeOps) ? | 813 SkPictureStateTree::Iterator it = (NULL == activeOps) ? |
791 SkPictureStateTree::Iterator() : | 814 SkPictureStateTree::Iterator() : |
792 fStateTree->getIterator(*activeOps, &canvas); | 815 fStateTree->getIterator(*activeOps, &canvas); |
793 | 816 |
| 817 if (0 != fStart || 0 != fStop) { |
| 818 reader.setOffset(fStart); |
| 819 uint32_t size; |
| 820 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); |
| 821 SkASSERT(SAVE_LAYER == op); |
| 822 reader.setOffset(fStart+size); |
| 823 } |
| 824 |
794 if (it.isValid()) { | 825 if (it.isValid()) { |
795 uint32_t skipTo = it.nextDraw(); | 826 uint32_t skipTo = it.nextDraw(); |
796 if (kDrawComplete == skipTo) { | 827 if (kDrawComplete == skipTo) { |
797 return; | 828 return; |
798 } | 829 } |
799 reader.setOffset(skipTo); | 830 reader.setOffset(skipTo); |
800 } | 831 } |
801 | 832 |
802 // Record this, so we can concat w/ it if we encounter a setMatrix() | 833 // Record this, so we can concat w/ it if we encounter a setMatrix() |
803 SkMatrix initialMatrix = canvas.getTotalMatrix(); | 834 SkMatrix initialMatrix = canvas.getTotalMatrix(); |
(...skipping 10 matching lines...) Expand all Loading... |
814 while (!reader.eof()) { | 845 while (!reader.eof()) { |
815 if (callback && callback->abortDrawing()) { | 846 if (callback && callback->abortDrawing()) { |
816 canvas.restoreToCount(originalSaveCount); | 847 canvas.restoreToCount(originalSaveCount); |
817 return; | 848 return; |
818 } | 849 } |
819 #ifdef SK_BUILD_FOR_ANDROID | 850 #ifdef SK_BUILD_FOR_ANDROID |
820 if (fAbortCurrentPlayback) { | 851 if (fAbortCurrentPlayback) { |
821 return; | 852 return; |
822 } | 853 } |
823 #endif | 854 #endif |
| 855 if (0 != fStart || 0 != fStop) { |
| 856 size_t offset = reader.offset() ; |
| 857 if (offset >= fStop) { |
| 858 uint32_t size; |
| 859 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); |
| 860 SkASSERT(RESTORE == op); |
| 861 return; |
| 862 } |
| 863 } |
| 864 |
| 865 if (NULL != fReplacements) { |
| 866 // Potentially replace a block of operations with a single drawBitma
p call |
| 867 SkPicturePlayback::PlaybackReplacements::ReplacementInfo* temp = |
| 868 fReplacements->lookupByStart(reader.
offset()); |
| 869 if (NULL != temp) { |
| 870 SkASSERT(NULL != temp->fBM); |
| 871 SkASSERT(NULL != temp->fPaint); |
| 872 canvas.drawBitmap(*temp->fBM, temp->fPos.fX, temp->fPos.fY, temp
->fPaint); |
| 873 |
| 874 if (it.isValid()) { |
| 875 // This save is needed since the BBH will automatically issu
e |
| 876 // a restore to balanced the saveLayer we're skipping |
| 877 canvas.save(); |
| 878 // Note: This skipping only works if the client only issues |
| 879 // well behaved saveLayer calls (i.e., doesn't use |
| 880 // kMatrix_SaveFlag or kClip_SaveFlag in isolation) |
| 881 |
| 882 // At this point we know that the PictureStateTree was aimin
g |
| 883 // for some draw op within temp's saveLayer (although potent
ially |
| 884 // in a separate saveLayer nested inside it). |
| 885 // We need to skip all the operations inside temp's range |
| 886 // along with all the associated state changes but update |
| 887 // the state tree to the first operation outside temp's rang
e. |
| 888 SkASSERT(it.peekDraw() >= temp->fStart && it.peekDraw() <= t
emp->fStop); |
| 889 |
| 890 while (kDrawComplete != it.peekDraw() && it.peekDraw() <= te
mp->fStop) { |
| 891 it.skipDraw(); |
| 892 } |
| 893 |
| 894 if (kDrawComplete == it.peekDraw()) { |
| 895 break; |
| 896 } |
| 897 |
| 898 uint32_t skipTo = it.nextDraw(); |
| 899 reader.setOffset(skipTo); |
| 900 } else { |
| 901 reader.setOffset(temp->fStop); |
| 902 uint32_t size; |
| 903 SkDEBUGCODE(DrawType op =) read_op_and_size(&reader, &size); |
| 904 SkASSERT(RESTORE == op); |
| 905 } |
| 906 continue; |
| 907 } |
| 908 } |
824 | 909 |
825 #ifdef SPEW_CLIP_SKIPPING | 910 #ifdef SPEW_CLIP_SKIPPING |
826 opCount++; | 911 opCount++; |
827 #endif | 912 #endif |
828 | 913 |
829 fCurOffset = reader.offset(); | 914 fCurOffset = reader.offset(); |
830 uint32_t size; | 915 uint32_t size; |
831 DrawType op = read_op_and_size(&reader, &size); | 916 DrawType op = read_op_and_size(&reader, &size); |
832 size_t skipTo = 0; | 917 size_t skipTo = 0; |
833 if (NOOP == op) { | 918 if (NOOP == op) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 reader.setOffset(offsetToRestore); | 993 reader.setOffset(offsetToRestore); |
909 } | 994 } |
910 } break; | 995 } break; |
911 case CLIP_RRECT: { | 996 case CLIP_RRECT: { |
912 SkRRect rrect; | 997 SkRRect rrect; |
913 reader.readRRect(&rrect); | 998 reader.readRRect(&rrect); |
914 uint32_t packed = reader.readInt(); | 999 uint32_t packed = reader.readInt(); |
915 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); | 1000 SkRegion::Op regionOp = ClipParams_unpackRegionOp(packed); |
916 bool doAA = ClipParams_unpackDoAA(packed); | 1001 bool doAA = ClipParams_unpackDoAA(packed); |
917 size_t offsetToRestore = reader.readInt(); | 1002 size_t offsetToRestore = reader.readInt(); |
918 SkASSERT(!offsetToRestore || \ | 1003 SkASSERT(!offsetToRestore || offsetToRestore >= reader.offset())
; |
919 offsetToRestore >= reader.offset()); | |
920 canvas.clipRRect(rrect, regionOp, doAA); | 1004 canvas.clipRRect(rrect, regionOp, doAA); |
921 if (canvas.isClipEmpty() && offsetToRestore) { | 1005 if (canvas.isClipEmpty() && offsetToRestore) { |
922 #ifdef SPEW_CLIP_SKIPPING | 1006 #ifdef SPEW_CLIP_SKIPPING |
923 skipRRect.recordSkip(offsetToRestore - reader.offset()); | 1007 skipRRect.recordSkip(offsetToRestore - reader.offset()); |
924 #endif | 1008 #endif |
925 reader.setOffset(offsetToRestore); | 1009 reader.setOffset(offsetToRestore); |
926 } | 1010 } |
927 } break; | 1011 } break; |
928 case PUSH_CULL: { | 1012 case PUSH_CULL: { |
929 const SkRect& cullRect = reader.skipT<SkRect>(); | 1013 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++) | 1796 for (index = 0; index < fPictureCount; index++) |
1713 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer
), | 1797 bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer
), |
1714 "picture%p, ", fPictureRefs[index]); | 1798 "picture%p, ", fPictureRefs[index]); |
1715 if (fPictureCount > 0) | 1799 if (fPictureCount > 0) |
1716 SkDebugf("%s0};\n", pBuffer); | 1800 SkDebugf("%s0};\n", pBuffer); |
1717 | 1801 |
1718 const_cast<SkPicturePlayback*>(this)->dumpStream(); | 1802 const_cast<SkPicturePlayback*>(this)->dumpStream(); |
1719 } | 1803 } |
1720 | 1804 |
1721 #endif | 1805 #endif |
OLD | NEW |