OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 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 | 7 |
8 #include "SkDebuggerGUI.h" | 8 #include "SkDebuggerGUI.h" |
9 #include "SkGraphics.h" | 9 #include "SkGraphics.h" |
10 #include "SkImageDecoder.h" | 10 #include "SkImageDecoder.h" |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 && fDeletesActivated); | 137 && fDeletesActivated); |
138 } | 138 } |
139 } | 139 } |
140 | 140 |
141 // The timed picture playback uses the SkPicturePlayback's profiling stubs | 141 // The timed picture playback uses the SkPicturePlayback's profiling stubs |
142 // to time individual commands. The offsets are needed to map SkPicture | 142 // to time individual commands. The offsets are needed to map SkPicture |
143 // offsets to individual commands. | 143 // offsets to individual commands. |
144 class SkTimedPicturePlayback : public SkPicturePlayback { | 144 class SkTimedPicturePlayback : public SkPicturePlayback { |
145 public: | 145 public: |
146 SkTimedPicturePlayback(SkStream* stream, const SkPictInfo& info, | 146 SkTimedPicturePlayback(SkStream* stream, const SkPictInfo& info, |
147 SkPicture::InstallPixelRefProc proc, const SkTDArray< size_t>& offsets, | 147 SkPicture::InstallPixelRefProc proc, |
148 const SkTDArray<bool>& deletedCommands) | 148 const SkTDArray<bool>& deletedCommands) |
149 : INHERITED(stream, info, proc) | 149 : INHERITED(stream, info, proc) |
150 , fOffsets(offsets) | |
151 , fSkipCommands(deletedCommands) | 150 , fSkipCommands(deletedCommands) |
152 , fTot(0.0) | 151 , fTot(0.0) |
153 , fCurCommand(0) { | 152 , fCurCommand(0) { |
154 fTimes.setCount(fOffsets.count()); | 153 fTimes.setCount(deletedCommands.count()); |
155 fTypeTimes.setCount(LAST_DRAWTYPE_ENUM+1); | 154 fTypeTimes.setCount(LAST_DRAWTYPE_ENUM+1); |
156 this->resetTimes(); | 155 this->resetTimes(); |
157 } | 156 } |
158 | 157 |
159 void resetTimes() { | 158 void resetTimes() { |
160 for (int i = 0; i < fOffsets.count(); ++i) { | 159 for (int i = 0; i < fTimes.count(); ++i) { |
161 fTimes[i] = 0.0; | 160 fTimes[i] = 0.0; |
162 } | 161 } |
163 for (int i = 0; i < fTypeTimes.count(); ++i) { | 162 for (int i = 0; i < fTypeTimes.count(); ++i) { |
164 fTypeTimes[i] = 0.0f; | 163 fTypeTimes[i] = 0.0f; |
165 } | 164 } |
166 fTot = 0.0; | 165 fTot = 0.0; |
167 } | 166 } |
168 | 167 |
169 int count() const { return fTimes.count(); } | 168 int count() const { return fTimes.count(); } |
170 | 169 |
171 double time(int index) const { return fTimes[index] / fTot; } | 170 double time(int index) const { return fTimes[index] / fTot; } |
172 | 171 |
173 const SkTDArray<double>* typeTimes() const { return &fTypeTimes; } | 172 const SkTDArray<double>* typeTimes() const { return &fTypeTimes; } |
174 | 173 |
175 double totTime() const { return fTot; } | 174 double totTime() const { return fTot; } |
176 | 175 |
177 protected: | 176 protected: |
178 BenchSysTimer fTimer; | 177 BenchSysTimer fTimer; |
179 SkTDArray<size_t> fOffsets; // offset in the SkPicture for each command | |
180 SkTDArray<bool> fSkipCommands; // has the command been deleted in the GUI? | 178 SkTDArray<bool> fSkipCommands; // has the command been deleted in the GUI? |
181 SkTDArray<double> fTimes; // sum of time consumed for each command | 179 SkTDArray<double> fTimes; // sum of time consumed for each command |
182 SkTDArray<double> fTypeTimes; // sum of time consumed for each type of comma nd (e.g., drawPath) | 180 SkTDArray<double> fTypeTimes; // sum of time consumed for each type of comma nd (e.g., drawPath) |
183 double fTot; // total of all times in 'fTimes' | 181 double fTot; // total of all times in 'fTimes' |
184 size_t fCurOffset; | 182 size_t fCurOffset; |
scroggo
2013/05/22 14:11:07
Is this still being used?
robertphillips
2013/05/22 18:51:28
Nope - deleted.
| |
185 int fCurType; | 183 int fCurType; |
186 int fCurCommand; // the current command being executed/timed | 184 int fCurCommand; // the current command being executed/timed |
187 | 185 |
188 virtual size_t preDraw(size_t offset, int type) { | 186 virtual bool preDraw(int opNum, int type) { |
scroggo
2013/05/22 14:11:07
SK_OVERRIDE.
Also, should these be inside #ifdef
robertphillips
2013/05/22 18:51:28
Done.
| |
189 // This search isn't as bad as it seems. In normal playback mode, the | 187 fCurCommand = opNum; |
190 // base class steps through the commands in order and can only skip ahea d | 188 |
191 // a bit on a clip. This class is only used during profiling so we | 189 if (fSkipCommands[fCurCommand]) { |
192 // don't have to worry about forward/backward scrubbing through commands . | 190 return true; |
193 for (int i = 0; offset != fOffsets[fCurCommand]; ++i) { | |
194 fCurCommand = (fCurCommand+1) % fOffsets.count(); | |
195 SkASSERT(i <= fOffsets.count()); // should always find the offset in the list | |
196 } | 191 } |
197 | 192 |
198 if (fSkipCommands[fCurCommand]) { | |
199 while (fCurCommand < fSkipCommands.count() && fSkipCommands[fCurComm and]) { | |
200 ++fCurCommand; | |
201 } | |
202 if (fCurCommand == fSkipCommands.count()) { | |
203 // Signal SkPicturePlayback to stop playing back | |
204 return SK_MaxU32; | |
205 } | |
206 return fOffsets[fCurCommand]; | |
207 } | |
208 | |
209 fCurOffset = offset; | |
210 fCurType = type; | 193 fCurType = type; |
211 // The SkDebugCanvas doesn't recognize these types. This class needs to | 194 // The SkDebugCanvas doesn't recognize these types. This class needs to |
212 // convert or else we'll wind up with a mismatch between the type counts | 195 // convert or else we'll wind up with a mismatch between the type counts |
213 // the debugger displays and the profile times. | 196 // the debugger displays and the profile times. |
214 if (DRAW_POS_TEXT_TOP_BOTTOM == type) { | 197 if (DRAW_POS_TEXT_TOP_BOTTOM == type) { |
215 fCurType = DRAW_POS_TEXT; | 198 fCurType = DRAW_POS_TEXT; |
216 } else if (DRAW_POS_TEXT_H_TOP_BOTTOM == type) { | 199 } else if (DRAW_POS_TEXT_H_TOP_BOTTOM == type) { |
217 fCurType = DRAW_POS_TEXT_H; | 200 fCurType = DRAW_POS_TEXT_H; |
218 } | 201 } |
219 | 202 |
220 #if defined(SK_BUILD_FOR_WIN32) | 203 #if defined(SK_BUILD_FOR_WIN32) |
221 // CPU timer doesn't work well on Windows | 204 // CPU timer doesn't work well on Windows |
222 fTimer.startWall(); | 205 fTimer.startWall(); |
223 #else | 206 #else |
224 fTimer.startCpu(); | 207 fTimer.startCpu(); |
225 #endif | 208 #endif |
226 | 209 |
227 return 0; | 210 return false; |
228 } | 211 } |
229 | 212 |
230 virtual void postDraw(size_t offset) { | 213 virtual void postDraw(int opNum) { |
scroggo
2013/05/22 14:11:07
SK_OVERRIDE
robertphillips
2013/05/22 18:51:28
Done.
| |
231 #if defined(SK_BUILD_FOR_WIN32) | 214 #if defined(SK_BUILD_FOR_WIN32) |
232 // CPU timer doesn't work well on Windows | 215 // CPU timer doesn't work well on Windows |
233 double time = fTimer.endWall(); | 216 double time = fTimer.endWall(); |
234 #else | 217 #else |
235 double time = fTimer.endCpu(); | 218 double time = fTimer.endCpu(); |
236 #endif | 219 #endif |
237 | 220 |
238 SkASSERT(offset == fCurOffset); | 221 SkASSERT(opNum == fCurCommand); |
239 SkASSERT(fCurType <= LAST_DRAWTYPE_ENUM); | 222 SkASSERT(fCurType <= LAST_DRAWTYPE_ENUM); |
240 | 223 |
241 fTimes[fCurCommand] += time; | 224 fTimes[fCurCommand] += time; |
242 fTypeTimes[fCurType] += time; | 225 fTypeTimes[fCurType] += time; |
243 fTot += time; | 226 fTot += time; |
244 } | 227 } |
245 | 228 |
246 private: | 229 private: |
247 typedef SkPicturePlayback INHERITED; | 230 typedef SkPicturePlayback INHERITED; |
248 }; | 231 }; |
249 | 232 |
250 // Wrap SkPicture to allow installation of an SkTimedPicturePlayback object | 233 // Wrap SkPicture to allow installation of an SkTimedPicturePlayback object |
251 class SkTimedPicture : public SkPicture { | 234 class SkTimedPicture : public SkPicture { |
252 public: | 235 public: |
253 explicit SkTimedPicture(SkStream* stream, bool* success, SkPicture::InstallP ixelRefProc proc, | 236 explicit SkTimedPicture(SkStream* stream, bool* success, SkPicture::InstallP ixelRefProc proc, |
254 const SkTDArray<size_t>& offsets, | |
255 const SkTDArray<bool>& deletedCommands) { | 237 const SkTDArray<bool>& deletedCommands) { |
256 if (success) { | 238 if (success) { |
257 *success = false; | 239 *success = false; |
258 } | 240 } |
259 fRecord = NULL; | 241 fRecord = NULL; |
260 fPlayback = NULL; | 242 fPlayback = NULL; |
261 fWidth = fHeight = 0; | 243 fWidth = fHeight = 0; |
262 | 244 |
263 SkPictInfo info; | 245 SkPictInfo info; |
264 | 246 |
265 if (!stream->read(&info, sizeof(info))) { | 247 if (!stream->read(&info, sizeof(info))) { |
266 return; | 248 return; |
267 } | 249 } |
268 if (SkPicture::PICTURE_VERSION != info.fVersion) { | 250 if (SkPicture::PICTURE_VERSION != info.fVersion) { |
269 return; | 251 return; |
270 } | 252 } |
271 | 253 |
272 if (stream->readBool()) { | 254 if (stream->readBool()) { |
273 fPlayback = SkNEW_ARGS(SkTimedPicturePlayback, | 255 fPlayback = SkNEW_ARGS(SkTimedPicturePlayback, |
274 (stream, info, proc, offsets, deletedCommands )); | 256 (stream, info, proc, deletedCommands)); |
275 } | 257 } |
276 | 258 |
277 // do this at the end, so that they will be zero if we hit an error. | 259 // do this at the end, so that they will be zero if we hit an error. |
278 fWidth = info.fWidth; | 260 fWidth = info.fWidth; |
279 fHeight = info.fHeight; | 261 fHeight = info.fHeight; |
280 if (success) { | 262 if (success) { |
281 *success = true; | 263 *success = true; |
282 } | 264 } |
283 } | 265 } |
284 | 266 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
347 | 329 |
348 SkFILEStream inputStream; | 330 SkFILEStream inputStream; |
349 | 331 |
350 inputStream.setPath(fFileName.c_str()); | 332 inputStream.setPath(fFileName.c_str()); |
351 if (!inputStream.isValid()) { | 333 if (!inputStream.isValid()) { |
352 return; | 334 return; |
353 } | 335 } |
354 | 336 |
355 bool success = false; | 337 bool success = false; |
356 SkTimedPicture picture(&inputStream, &success, &SkImageDecoder::DecodeMemory , | 338 SkTimedPicture picture(&inputStream, &success, &SkImageDecoder::DecodeMemory , |
357 fOffsets, fSkipCommands); | 339 fSkipCommands); |
358 if (!success) { | 340 if (!success) { |
359 return; | 341 return; |
360 } | 342 } |
361 | 343 |
362 // For now this #if allows switching between tiled and simple rendering | 344 // For now this #if allows switching between tiled and simple rendering |
363 // modes. Eventually this will be accomplished via the GUI | 345 // modes. Eventually this will be accomplished via the GUI |
364 #if 0 | 346 #if 0 |
365 // With the current batch of SysTimers, profiling in tiled mode | 347 // With the current batch of SysTimers, profiling in tiled mode |
366 // gets swamped by the timing overhead: | 348 // gets swamped by the timing overhead: |
367 // | 349 // |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
907 QDir dir(path); | 889 QDir dir(path); |
908 QRegExp r(".skp"); | 890 QRegExp r(".skp"); |
909 fDirectoryWidget.clear(); | 891 fDirectoryWidget.clear(); |
910 const QStringList files = dir.entryList(); | 892 const QStringList files = dir.entryList(); |
911 foreach (QString f, files) { | 893 foreach (QString f, files) { |
912 if (f.contains(r)) | 894 if (f.contains(r)) |
913 fDirectoryWidget.addItem(f); | 895 fDirectoryWidget.addItem(f); |
914 } | 896 } |
915 } | 897 } |
916 | 898 |
917 // SkOffsetPicturePlayback records the offset of each command in the picture. | |
918 // These are needed by the profiling system. | |
919 class SkOffsetPicturePlayback : public SkPicturePlayback { | |
920 public: | |
921 SkOffsetPicturePlayback(SkStream* stream, const SkPictInfo& info, | |
922 SkPicture::InstallPixelRefProc proc) | |
923 : INHERITED(stream, info, proc) { | |
924 } | |
925 | |
926 const SkTDArray<size_t>& offsets() const { return fOffsets; } | |
927 | |
928 protected: | |
929 SkTDArray<size_t> fOffsets; | |
930 | |
931 virtual size_t preDraw(size_t offset, int type) { | |
932 *fOffsets.append() = offset; | |
933 return 0; | |
934 } | |
935 | |
936 private: | |
937 typedef SkPicturePlayback INHERITED; | |
938 }; | |
939 | |
940 // Picture to wrap an SkOffsetPicturePlayback. | |
941 class SkOffsetPicture : public SkPicture { | |
942 public: | |
943 SkOffsetPicture(SkStream* stream, bool* success, SkPicture::InstallPixelRefP roc proc) { | |
944 if (success) { | |
945 *success = false; | |
946 } | |
947 fRecord = NULL; | |
948 fPlayback = NULL; | |
949 fWidth = fHeight = 0; | |
950 | |
951 SkPictInfo info; | |
952 | |
953 if (!stream->read(&info, sizeof(info))) { | |
954 return; | |
955 } | |
956 if (PICTURE_VERSION != info.fVersion) { | |
957 return; | |
958 } | |
959 | |
960 if (stream->readBool()) { | |
961 fPlayback = SkNEW_ARGS(SkOffsetPicturePlayback, (stream, info, proc) ); | |
962 } | |
963 | |
964 // do this at the end, so that they will be zero if we hit an error. | |
965 fWidth = info.fWidth; | |
966 fHeight = info.fHeight; | |
967 if (success) { | |
968 *success = true; | |
969 } | |
970 } | |
971 | |
972 const SkTDArray<size_t>& offsets() const { | |
973 return ((SkOffsetPicturePlayback*) fPlayback)->offsets(); | |
974 } | |
975 | |
976 private: | |
977 // disallow default ctor b.c. we don't have a good way to setup the fPlaybac k ptr | |
978 SkOffsetPicture(); | |
979 // disallow the copy ctor - enabling would require copying code from SkPictu re | |
980 SkOffsetPicture(const SkOffsetPicture& src); | |
981 | |
982 typedef SkPicture INHERITED; | |
983 }; | |
984 | |
985 | |
986 | |
987 void SkDebuggerGUI::loadPicture(const SkString& fileName) { | 899 void SkDebuggerGUI::loadPicture(const SkString& fileName) { |
988 fFileName = fileName; | 900 fFileName = fileName; |
989 fLoading = true; | 901 fLoading = true; |
990 SkStream* stream = SkNEW_ARGS(SkFILEStream, (fileName.c_str())); | 902 SkStream* stream = SkNEW_ARGS(SkFILEStream, (fileName.c_str())); |
991 | 903 |
992 bool success = false; | 904 bool success = false; |
993 | 905 |
994 SkOffsetPicture* picture = SkNEW_ARGS(SkOffsetPicture, | 906 SkPicture* picture = SkNEW_ARGS(SkPicture, |
995 (stream, &success, &SkImageDecoder::De codeMemory)); | 907 (stream, &success, &SkImageDecoder::DecodeMe mory)); |
996 | 908 |
997 if (!success) { | 909 if (!success) { |
998 QMessageBox::critical(this, "Error loading file", "Couldn't read file, s orry."); | 910 QMessageBox::critical(this, "Error loading file", "Couldn't read file, s orry."); |
999 SkSafeUnref(stream); | 911 SkSafeUnref(stream); |
1000 return; | 912 return; |
1001 } | 913 } |
1002 | 914 |
1003 fCanvasWidget.resetWidgetTransform(); | 915 fCanvasWidget.resetWidgetTransform(); |
1004 fDebugger.loadPicture(picture); | 916 fDebugger.loadPicture(picture); |
1005 | 917 |
1006 fOffsets = picture->offsets(); | 918 // Will this automatically clear out due to nature of refcnt? |
919 SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings(); | |
djsollen
2013/05/22 14:35:37
if you just want the count use fDebugger.getSize()
robertphillips
2013/05/22 18:51:28
Done-ish. I'm now using getSize and have moved the
scroggo
2013/05/22 19:06:13
Agreed. Can you put commands into an SkAutoTDelete
| |
1007 | 920 |
1008 fSkipCommands.setCount(fOffsets.count()); | 921 fSkipCommands.setCount(commands->count()); |
1009 for (int i = 0; i < fOffsets.count(); ++i) { | 922 for (int i = 0; i < fSkipCommands.count(); ++i) { |
1010 fSkipCommands[i] = false; | 923 fSkipCommands[i] = false; |
1011 } | 924 } |
1012 | 925 |
1013 SkSafeUnref(stream); | 926 SkSafeUnref(stream); |
1014 SkSafeUnref(picture); | 927 SkSafeUnref(picture); |
1015 | 928 |
1016 // Will this automatically clear out due to nature of refcnt? | 929 fActionProfile.setDisabled(false); |
1017 SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings(); | |
1018 | |
1019 // If SkPicturePlayback is compiled w/o SK_PICTURE_PROFILING_STUBS | |
1020 // the offset count will always be zero | |
1021 SkASSERT(0 == fOffsets.count() || commands->count() == fOffsets.count()); | |
1022 if (commands->count() == fOffsets.count()) { | |
1023 fActionProfile.setDisabled(false); | |
1024 } | |
1025 | 930 |
1026 /* fDebugCanvas is reinitialized every load picture. Need it to retain value | 931 /* fDebugCanvas is reinitialized every load picture. Need it to retain value |
1027 * of the visibility filter. | 932 * of the visibility filter. |
1028 * TODO(chudy): This should be deprecated since fDebugger is not | 933 * TODO(chudy): This should be deprecated since fDebugger is not |
1029 * recreated. | 934 * recreated. |
1030 * */ | 935 * */ |
1031 fDebugger.highlightCurrentCommand(fSettingsWidget.getVisibilityButton()->isC hecked()); | 936 fDebugger.highlightCurrentCommand(fSettingsWidget.getVisibilityButton()->isC hecked()); |
1032 | 937 |
1033 setupListWidget(commands); | 938 setupListWidget(commands); |
1034 setupComboBox(commands); | 939 setupComboBox(commands); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1093 } | 998 } |
1094 | 999 |
1095 // NOTE(chudy): Makes first item unselectable. | 1000 // NOTE(chudy): Makes first item unselectable. |
1096 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( | 1001 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( |
1097 fFilter.model()); | 1002 fFilter.model()); |
1098 QModelIndex firstIndex = model->index(0, fFilter.modelColumn(), | 1003 QModelIndex firstIndex = model->index(0, fFilter.modelColumn(), |
1099 fFilter.rootModelIndex()); | 1004 fFilter.rootModelIndex()); |
1100 QStandardItem* firstItem = model->itemFromIndex(firstIndex); | 1005 QStandardItem* firstItem = model->itemFromIndex(firstIndex); |
1101 firstItem->setSelectable(false); | 1006 firstItem->setSelectable(false); |
1102 } | 1007 } |
OLD | NEW |