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; | |
185 int fCurType; | 182 int fCurType; |
186 int fCurCommand; // the current command being executed/timed | 183 int fCurCommand; // the current command being executed/timed |
187 | 184 |
188 virtual size_t preDraw(size_t offset, int type) { | 185 #ifdef SK_DEVELOPER |
189 // This search isn't as bad as it seems. In normal playback mode, the | 186 virtual bool preDraw(int opIndex, int type) SK_OVERRIDE { |
190 // base class steps through the commands in order and can only skip ahea
d | 187 fCurCommand = opIndex; |
191 // a bit on a clip. This class is only used during profiling so we | 188 |
192 // don't have to worry about forward/backward scrubbing through commands
. | 189 if (fSkipCommands[fCurCommand]) { |
193 for (int i = 0; offset != fOffsets[fCurCommand]; ++i) { | 190 return true; |
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 opIndex) SK_OVERRIDE { |
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(opIndex == 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 } |
| 228 #endif |
245 | 229 |
246 private: | 230 private: |
247 typedef SkPicturePlayback INHERITED; | 231 typedef SkPicturePlayback INHERITED; |
248 }; | 232 }; |
249 | 233 |
250 // Wrap SkPicture to allow installation of an SkTimedPicturePlayback object | 234 // Wrap SkPicture to allow installation of an SkTimedPicturePlayback object |
251 class SkTimedPicture : public SkPicture { | 235 class SkTimedPicture : public SkPicture { |
252 public: | 236 public: |
253 explicit SkTimedPicture(SkStream* stream, bool* success, SkPicture::InstallP
ixelRefProc proc, | 237 explicit SkTimedPicture(SkStream* stream, bool* success, SkPicture::InstallP
ixelRefProc proc, |
254 const SkTDArray<size_t>& offsets, | |
255 const SkTDArray<bool>& deletedCommands) { | 238 const SkTDArray<bool>& deletedCommands) { |
256 if (success) { | 239 if (success) { |
257 *success = false; | 240 *success = false; |
258 } | 241 } |
259 fRecord = NULL; | 242 fRecord = NULL; |
260 fPlayback = NULL; | 243 fPlayback = NULL; |
261 fWidth = fHeight = 0; | 244 fWidth = fHeight = 0; |
262 | 245 |
263 SkPictInfo info; | 246 SkPictInfo info; |
264 | 247 |
265 if (!stream->read(&info, sizeof(info))) { | 248 if (!stream->read(&info, sizeof(info))) { |
266 return; | 249 return; |
267 } | 250 } |
268 if (SkPicture::PICTURE_VERSION != info.fVersion) { | 251 if (SkPicture::PICTURE_VERSION != info.fVersion) { |
269 return; | 252 return; |
270 } | 253 } |
271 | 254 |
272 if (stream->readBool()) { | 255 if (stream->readBool()) { |
273 fPlayback = SkNEW_ARGS(SkTimedPicturePlayback, | 256 fPlayback = SkNEW_ARGS(SkTimedPicturePlayback, |
274 (stream, info, proc, offsets, deletedCommands
)); | 257 (stream, info, proc, deletedCommands)); |
275 } | 258 } |
276 | 259 |
277 // do this at the end, so that they will be zero if we hit an error. | 260 // do this at the end, so that they will be zero if we hit an error. |
278 fWidth = info.fWidth; | 261 fWidth = info.fWidth; |
279 fHeight = info.fHeight; | 262 fHeight = info.fHeight; |
280 if (success) { | 263 if (success) { |
281 *success = true; | 264 *success = true; |
282 } | 265 } |
283 } | 266 } |
284 | 267 |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
347 | 330 |
348 SkFILEStream inputStream; | 331 SkFILEStream inputStream; |
349 | 332 |
350 inputStream.setPath(fFileName.c_str()); | 333 inputStream.setPath(fFileName.c_str()); |
351 if (!inputStream.isValid()) { | 334 if (!inputStream.isValid()) { |
352 return; | 335 return; |
353 } | 336 } |
354 | 337 |
355 bool success = false; | 338 bool success = false; |
356 SkTimedPicture picture(&inputStream, &success, &SkImageDecoder::DecodeMemory
, | 339 SkTimedPicture picture(&inputStream, &success, &SkImageDecoder::DecodeMemory
, |
357 fOffsets, fSkipCommands); | 340 fSkipCommands); |
358 if (!success) { | 341 if (!success) { |
359 return; | 342 return; |
360 } | 343 } |
361 | 344 |
362 // For now this #if allows switching between tiled and simple rendering | 345 // For now this #if allows switching between tiled and simple rendering |
363 // modes. Eventually this will be accomplished via the GUI | 346 // modes. Eventually this will be accomplished via the GUI |
364 #if 0 | 347 #if 0 |
365 // With the current batch of SysTimers, profiling in tiled mode | 348 // With the current batch of SysTimers, profiling in tiled mode |
366 // gets swamped by the timing overhead: | 349 // gets swamped by the timing overhead: |
367 // | 350 // |
(...skipping 539 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 QDir dir(path); | 890 QDir dir(path); |
908 QRegExp r(".skp"); | 891 QRegExp r(".skp"); |
909 fDirectoryWidget.clear(); | 892 fDirectoryWidget.clear(); |
910 const QStringList files = dir.entryList(); | 893 const QStringList files = dir.entryList(); |
911 foreach (QString f, files) { | 894 foreach (QString f, files) { |
912 if (f.contains(r)) | 895 if (f.contains(r)) |
913 fDirectoryWidget.addItem(f); | 896 fDirectoryWidget.addItem(f); |
914 } | 897 } |
915 } | 898 } |
916 | 899 |
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) { | 900 void SkDebuggerGUI::loadPicture(const SkString& fileName) { |
988 fFileName = fileName; | 901 fFileName = fileName; |
989 fLoading = true; | 902 fLoading = true; |
990 SkStream* stream = SkNEW_ARGS(SkFILEStream, (fileName.c_str())); | 903 SkStream* stream = SkNEW_ARGS(SkFILEStream, (fileName.c_str())); |
991 | 904 |
992 bool success = false; | 905 bool success = false; |
993 | 906 |
994 SkOffsetPicture* picture = SkNEW_ARGS(SkOffsetPicture, | 907 SkPicture* picture = SkNEW_ARGS(SkPicture, |
995 (stream, &success, &SkImageDecoder::De
codeMemory)); | 908 (stream, &success, &SkImageDecoder::DecodeMe
mory)); |
996 | 909 |
997 if (!success) { | 910 if (!success) { |
998 QMessageBox::critical(this, "Error loading file", "Couldn't read file, s
orry."); | 911 QMessageBox::critical(this, "Error loading file", "Couldn't read file, s
orry."); |
999 SkSafeUnref(stream); | 912 SkSafeUnref(stream); |
1000 return; | 913 return; |
1001 } | 914 } |
1002 | 915 |
1003 fCanvasWidget.resetWidgetTransform(); | 916 fCanvasWidget.resetWidgetTransform(); |
1004 fDebugger.loadPicture(picture); | 917 fDebugger.loadPicture(picture); |
1005 | 918 |
1006 fOffsets = picture->offsets(); | 919 fSkipCommands.setCount(fDebugger.getSize()); |
1007 | 920 for (int i = 0; i < fSkipCommands.count(); ++i) { |
1008 fSkipCommands.setCount(fOffsets.count()); | |
1009 for (int i = 0; i < fOffsets.count(); ++i) { | |
1010 fSkipCommands[i] = false; | 921 fSkipCommands[i] = false; |
1011 } | 922 } |
1012 | 923 |
1013 SkSafeUnref(stream); | 924 SkSafeUnref(stream); |
1014 SkSafeUnref(picture); | 925 SkSafeUnref(picture); |
1015 | 926 |
1016 // Will this automatically clear out due to nature of refcnt? | 927 // Will this automatically clear out due to nature of refcnt? |
1017 SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings(); | 928 SkTArray<SkString>* commands = fDebugger.getDrawCommandsAsStrings(); |
1018 | 929 |
1019 // If SkPicturePlayback is compiled w/o SK_PICTURE_PROFILING_STUBS | 930 fActionProfile.setDisabled(false); |
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 | 931 |
1026 /* fDebugCanvas is reinitialized every load picture. Need it to retain value | 932 /* fDebugCanvas is reinitialized every load picture. Need it to retain value |
1027 * of the visibility filter. | 933 * of the visibility filter. |
1028 * TODO(chudy): This should be deprecated since fDebugger is not | 934 * TODO(chudy): This should be deprecated since fDebugger is not |
1029 * recreated. | 935 * recreated. |
1030 * */ | 936 * */ |
1031 fDebugger.highlightCurrentCommand(fSettingsWidget.getVisibilityButton()->isC
hecked()); | 937 fDebugger.highlightCurrentCommand(fSettingsWidget.getVisibilityButton()->isC
hecked()); |
1032 | 938 |
1033 setupListWidget(commands); | 939 setupListWidget(commands); |
1034 setupComboBox(commands); | 940 setupComboBox(commands); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1093 } | 999 } |
1094 | 1000 |
1095 // NOTE(chudy): Makes first item unselectable. | 1001 // NOTE(chudy): Makes first item unselectable. |
1096 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( | 1002 QStandardItemModel* model = qobject_cast<QStandardItemModel*>( |
1097 fFilter.model()); | 1003 fFilter.model()); |
1098 QModelIndex firstIndex = model->index(0, fFilter.modelColumn(), | 1004 QModelIndex firstIndex = model->index(0, fFilter.modelColumn(), |
1099 fFilter.rootModelIndex()); | 1005 fFilter.rootModelIndex()); |
1100 QStandardItem* firstItem = model->itemFromIndex(firstIndex); | 1006 QStandardItem* firstItem = model->itemFromIndex(firstIndex); |
1101 firstItem->setSelectable(false); | 1007 firstItem->setSelectable(false); |
1102 } | 1008 } |
OLD | NEW |