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

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

Issue 261663003: First pass at pre-rendering saveLayers for GPU (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Reduce size of PlaybackReplacements in SkPicturePlayback.h Created 6 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
« no previous file with comments | « src/core/SkPicturePlayback.h ('k') | src/core/SkPictureStateTree.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/core/SkPicturePlayback.h ('k') | src/core/SkPictureStateTree.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698