diff --git a/debugger/QT/SkDebuggerGUI.cpp b/debugger/QT/SkDebuggerGUI.cpp index 25e0c57a4d..b301fcef66 100644 --- a/debugger/QT/SkDebuggerGUI.cpp +++ b/debugger/QT/SkDebuggerGUI.cpp @@ -141,11 +141,13 @@ class SkTimedPicturePlayback : public SkPicturePlayback { public: SkTimedPicturePlayback(SkStream* stream, const SkPictInfo& info, bool* isValid, SkSerializationHelpers::DecodeBitmap decoder, - const SkTDArray& offsets) + const SkTDArray& offsets, + const SkTDArray& deletedCommands) : INHERITED(stream, info, isValid, decoder) , fTot(0.0) , fCurCommand(0) - , fOffsets(offsets) { + , fOffsets(offsets) + , fSkipCommands(deletedCommands) { fTimes.setCount(fOffsets.count()); fTypeTimes.setCount(LAST_DRAWTYPE_ENUM+1); this->resetTimes(); @@ -172,6 +174,7 @@ public: protected: BenchSysTimer fTimer; SkTDArray fOffsets; // offset in the SkPicture for each command + SkTDArray fSkipCommands; // has the command been deleted in the GUI? SkTDArray fTimes; // sum of time consumed for each command SkTDArray fTypeTimes; // sum of time consumed for each type of command (e.g., drawPath) double fTot; // total of all times in 'fTimes' @@ -179,7 +182,7 @@ protected: int fCurType; int fCurCommand; // the current command being executed/timed - virtual void preDraw(size_t offset, int type) { + virtual size_t preDraw(size_t offset, int type) SK_OVERRIDE { // This search isn't as bad as it seems. In normal playback mode, the // base class steps through the commands in order and can only skip ahead // a bit on a clip. This class is only used during profiling so we @@ -189,6 +192,17 @@ protected: SkASSERT(i <= fOffsets.count()); // should always find the offset in the list } + if (fSkipCommands[fCurCommand]) { + while (fCurCommand < fSkipCommands.count() && fSkipCommands[fCurCommand]) { + ++fCurCommand; + } + if (fCurCommand == fSkipCommands.count()) { + // Signal SkPicturePlayback to stop playing back + return SK_MaxU32; + } + return fOffsets[fCurCommand]; + } + fCurOffset = offset; fCurType = type; // The SkDebugCanvas doesn't recognize these types. This class needs to @@ -206,9 +220,11 @@ protected: #else fTimer.startCpu(); #endif + + return 0; } - virtual void postDraw(size_t offset) { + virtual void postDraw(size_t offset) SK_OVERRIDE { #if defined(SK_BUILD_FOR_WIN32) // CPU timer doesn't work well on Windows double time = fTimer.endWall(); @@ -234,7 +250,8 @@ public: explicit SkTimedPicture(SkStream* stream, bool* success, SkSerializationHelpers::DecodeBitmap decoder, - const SkTDArray& offsets) { + const SkTDArray& offsets, + const SkTDArray& deletedCommands) { if (success) { *success = false; } @@ -254,7 +271,7 @@ public: if (stream->readBool()) { bool isValid = false; fPlayback = SkNEW_ARGS(SkTimedPicturePlayback, - (stream, info, &isValid, decoder, offsets)); + (stream, info, &isValid, decoder, offsets, deletedCommands)); if (!isValid) { SkDELETE(fPlayback); fPlayback = NULL; @@ -341,7 +358,8 @@ void SkDebuggerGUI::actionProfile() { } bool success = false; - SkTimedPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream, fOffsets); + SkTimedPicture picture(&inputStream, &success, &SkImageDecoder::DecodeStream, + fOffsets, fSkipCommands); if (!success) { return; } @@ -407,6 +425,7 @@ void SkDebuggerGUI::actionClearDeletes() { QListWidgetItem* item = fListWidget.item(row); item->setData(Qt::UserRole + 2, QPixmap(":/blank.png")); fDebugger.setCommandVisible(row, true); + fSkipCommands[row] = false; } if (fPause) { fCanvasWidget.drawTo(fPausedRow); @@ -435,9 +454,11 @@ void SkDebuggerGUI::actionDelete() { if (fDebugger.isCommandVisible(currentRow)) { item->setData(Qt::UserRole + 2, QPixmap(":/delete.png")); fDebugger.setCommandVisible(currentRow, false); + fSkipCommands[currentRow] = true; } else { item->setData(Qt::UserRole + 2, QPixmap(":/blank.png")); fDebugger.setCommandVisible(currentRow, true); + fSkipCommands[currentRow] = false; } if (fPause) { @@ -882,8 +903,9 @@ public: protected: SkTDArray fOffsets; - virtual void preDraw(size_t offset, int type) { + virtual size_t preDraw(size_t offset, int type) SK_OVERRIDE { *fOffsets.append() = offset; + return 0; } private: @@ -956,6 +978,11 @@ void SkDebuggerGUI::loadPicture(const SkString& fileName) { fOffsets = picture->offsets(); + fSkipCommands.setCount(fOffsets.count()); + for (int i = 0; i < fOffsets.count(); ++i) { + fSkipCommands[i] = false; + } + SkSafeUnref(stream); SkSafeUnref(picture); diff --git a/debugger/QT/SkDebuggerGUI.h b/debugger/QT/SkDebuggerGUI.h index aed40721fe..75d3f28561 100644 --- a/debugger/QT/SkDebuggerGUI.h +++ b/debugger/QT/SkDebuggerGUI.h @@ -260,6 +260,7 @@ private: QString fPath; SkString fFileName; SkTDArray fOffsets; // the offset of each command in the SkPicture + SkTDArray fSkipCommands; // has a specific command been deleted? bool fDirectoryWidgetActive; QMenuBar fMenuBar; diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index d0a29d3c9d..a337264d55 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -577,7 +577,8 @@ struct SkipClipRec { #endif #ifdef SK_PICTURE_PROFILING_STUBS -void SkPicturePlayback::preDraw(size_t offset, int type) { +size_t SkPicturePlayback::preDraw(size_t offset, int type) { + return 0; } void SkPicturePlayback::postDraw(size_t offset) { @@ -597,6 +598,10 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { SkAutoMutexAcquire autoMutex(fDrawMutex); #endif + // kDrawComplete will be the signal that we have reached the end of + // the command stream + static const int kDrawComplete = SK_MaxU32; + SkReader32 reader(fOpData->bytes(), fOpData->size()); TextContainer text; SkTDArray results; @@ -621,11 +626,11 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { fStateTree->getIterator(results, &canvas); if (it.isValid()) { - uint32_t off = it.draw(); - if (off == SK_MaxU32) { + uint32_t skipTo = it.draw(); + if (kDrawComplete == skipTo) { return; } - reader.setOffset(off); + reader.setOffset(skipTo); } // Record this, so we can concat w/ it if we encounter a setMatrix() @@ -637,7 +642,14 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { #endif int type = reader.readInt(); #ifdef SK_PICTURE_PROFILING_STUBS - this->preDraw(curOffset, type); + size_t skipTo = this->preDraw(curOffset, type); + if (0 != skipTo) { + if (kDrawComplete == skipTo) { + break; + } + reader.setOffset(skipTo); + continue; + } #endif switch (type) { case CLIP_PATH: { @@ -887,11 +899,11 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { #endif if (it.isValid()) { - uint32_t off = it.draw(); - if (off == SK_MaxU32) { + uint32_t skipTo = it.draw(); + if (kDrawComplete == skipTo) { break; } - reader.setOffset(off); + reader.setOffset(skipTo); } } diff --git a/src/core/SkPicturePlayback.h b/src/core/SkPicturePlayback.h index 9e495fa6cf..8f52b19314 100644 --- a/src/core/SkPicturePlayback.h +++ b/src/core/SkPicturePlayback.h @@ -79,7 +79,7 @@ public: protected: #ifdef SK_PICTURE_PROFILING_STUBS - virtual void preDraw(size_t offset, int type); + virtual size_t preDraw(size_t offset, int type); virtual void postDraw(size_t offset); #endif