Exemple #1
0
void TraceLoader::parseTrace()
{
    QList<ApiTraceFrame*> frames;
    ApiTraceFrame *currentFrame = 0;
    int frameCount = 0;
    QVector<ApiTraceCall*> calls;
    quint64 binaryDataSize = 0;

    int lastPercentReport = 0;

    trace::Call *call = m_parser.parse_call();
    while (call) {
        //std::cout << *call;
        if (!currentFrame) {
            currentFrame = new ApiTraceFrame();
            currentFrame->number = frameCount;
            ++frameCount;
        }
        ApiTraceCall *apiCall =
            apiCallFromTraceCall(call, m_helpHash, currentFrame, this);
        calls.append(apiCall);
        if (apiCall->hasBinaryData()) {
            QByteArray data =
                apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
            binaryDataSize += data.size();
        }
        if (ApiTrace::isCallAFrameMarker(apiCall,
                                         m_frameMarker)) {
            calls.squeeze();
            currentFrame->setCalls(calls, binaryDataSize);
            calls.clear();
            frames.append(currentFrame);
            currentFrame = 0;
            binaryDataSize = 0;
            if (frames.count() >= FRAMES_TO_CACHE) {
                emit framesLoaded(frames);
                frames.clear();
            }
            if (m_parser.percentRead() - lastPercentReport >= 5) {
                emit parsed(m_parser.percentRead());
                lastPercentReport = m_parser.percentRead();
            }
        }
        delete call;
        call = m_parser.parse_call();
    }

    //last frames won't have markers
    //  it's just a bunch of Delete calls for every object
    //  after the last SwapBuffers
    if (currentFrame) {
        calls.squeeze();
        currentFrame->setCalls(calls, binaryDataSize);
        frames.append(currentFrame);
        currentFrame = 0;
    }
    if (frames.count()) {
        emit framesLoaded(frames);
    }
}
Exemple #2
0
void MainWindow::fillState(bool nonDefaults)
{
    if (nonDefaults) {
        ApiTraceState defaultState = m_trace->defaultState();
        if (defaultState.isEmpty()) {
            m_ui.nonDefaultsCB->blockSignals(true);
            m_ui.nonDefaultsCB->setChecked(false);
            m_ui.nonDefaultsCB->blockSignals(false);
            ApiTraceFrame *firstFrame =
                m_trace->frameAt(0);
            if (!firstFrame) {
                return;
            }
            if (!firstFrame->isLoaded()) {
                m_trace->loadFrame(firstFrame);
                return;
            }
            ApiTraceCall *firstCall = firstFrame->calls().first();
            ApiTraceEvent *oldSelected = m_selectedEvent;
            m_nonDefaultsLookupEvent = m_selectedEvent;
            m_selectedEvent = firstCall;
            lookupState();
            m_selectedEvent = oldSelected;
        }
    }
    fillStateForFrame();
}
Exemple #3
0
QModelIndex ApiTraceModel::index(int row, int column,
                                 const QModelIndex &parent) const
{
    if ((parent.isValid() && parent.column() != 0) || column != 0)
        return QModelIndex();

    ApiTraceEvent *event = item(parent);
    if (event) {
        if (event->type() != ApiTraceEvent::Frame) {
            qDebug()<<"got a valid parent but it's not a frame "<<event->type();
            return QModelIndex();
        }
        ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
        ApiTraceCall *call = frame->call(row);
        if (call)
            return createIndex(row, column, call);
        else
            return QModelIndex();
    } else {
        ApiTraceFrame *frame = m_trace->frameAt(row);
        if (frame)
            return createIndex(row, column, frame);
        else
            return QModelIndex();
    }
    return QModelIndex();
}
void TraceLoader::scanTrace()
{
    QList<ApiTraceFrame*> frames;
    ApiTraceFrame *currentFrame = 0;

    trace::Call *call;
    trace::ParseBookmark startBookmark;
    int numOfFrames = 0;
    int numOfCalls = 0;
    int lastPercentReport = 0;

    m_parser.getBookmark(startBookmark);

    while ((call = m_parser.scan_call())) {
        ++numOfCalls;

        if (call->flags & trace::CALL_FLAG_END_FRAME) {
            FrameBookmark frameBookmark(startBookmark);
            frameBookmark.numberOfCalls = numOfCalls;

            currentFrame = new ApiTraceFrame();
            currentFrame->number = numOfFrames;
            currentFrame->setNumChildren(numOfCalls);
            currentFrame->setLastCallIndex(call->no);
            frames.append(currentFrame);

            m_createdFrames.append(currentFrame);
            m_frameBookmarks[numOfFrames] = frameBookmark;
            ++numOfFrames;

            if (m_parser.percentRead() - lastPercentReport >= 5) {
                emit parsed(m_parser.percentRead());
                lastPercentReport = m_parser.percentRead();
            }
            m_parser.getBookmark(startBookmark);
            numOfCalls = 0;
        }
        delete call;
    }

    if (numOfCalls) {
        //trace::File::Bookmark endBookmark = m_parser.currentBookmark();
        FrameBookmark frameBookmark(startBookmark);
        frameBookmark.numberOfCalls = numOfCalls;

        currentFrame = new ApiTraceFrame();
        currentFrame->number = numOfFrames;
        currentFrame->setNumChildren(numOfCalls);
        frames.append(currentFrame);

        m_createdFrames.append(currentFrame);
        m_frameBookmarks[numOfFrames] = frameBookmark;
        ++numOfFrames;
    }

    emit parsed(100);

    emit framesLoaded(frames);
}
void TraceLoader::parseTrace()
{
    QList<ApiTraceFrame*> frames;
    int frameCount = 0;
    int lastPercentReport = 0;

    ApiTraceFrame *currentFrame = new ApiTraceFrame();
    currentFrame->number = frameCount;

    FrameContents frameCalls;
    while (frameCalls.load(this, currentFrame, m_helpHash, m_parser)) {

        if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
            currentFrame->setCalls(frameCalls.allCalls(),
                                   frameCalls.allCalls(),
                                   frameCalls.binaryDataSize());
        } else {
            currentFrame->setCalls(frameCalls.topLevelCalls(),
                                   frameCalls.allCalls(),
                                   frameCalls.binaryDataSize());
        }
        frames.append(currentFrame);
        if (frames.count() >= FRAMES_TO_CACHE) {
            emit framesLoaded(frames);
            frames.clear();
        }
        if (m_parser.percentRead() - lastPercentReport >= 5) {
            emit parsed(m_parser.percentRead());
            lastPercentReport = m_parser.percentRead();
        }
        ++frameCount;
        currentFrame = new ApiTraceFrame();
        currentFrame->number = frameCount;

        frameCalls.reset();
    }

    //last frames won't have markers
    //  it's just a bunch of Delete calls for every object
    //  after the last SwapBuffers
    if (!frameCalls.isEmpty()) {
        if (frameCalls.topLevelCount() == frameCalls.allCallsCount()) {
            currentFrame->setCalls(frameCalls.allCalls(),
                                   frameCalls.allCalls(),
                                   frameCalls.binaryDataSize());
        } else {
            currentFrame->setCalls(frameCalls.topLevelCalls(),
                                   frameCalls.allCalls(),
                                   frameCalls.binaryDataSize());
        }
        frames.append(currentFrame);
    }
    if (frames.count()) {
        emit framesLoaded(frames);
    }
}
Exemple #6
0
QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.column() != 0)
        return QVariant();

    ApiTraceEvent *itm = item(index);
    if (!itm) {
        return QVariant();
    }

    switch (role) {
    case Qt::DisplayRole:
        return itm->staticText().text();
    case Qt::DecorationRole:
        return QImage();
    case Qt::ToolTipRole: {
        const QString stateText = tr("State info available.");
        if (itm->type() == ApiTraceEvent::Call) {
            ApiTraceCall *call = static_cast<ApiTraceCall*>(itm);
            if (call->state().isEmpty())
                return QString::fromLatin1("%1)&nbsp;<b>%2</b>")
                    .arg(call->index())
                    .arg(call->name());
            else
                return QString::fromLatin1("%1)&nbsp;<b>%2</b><br/>%3")
                    .arg(call->index())
                    .arg(call->name())
                    .arg(stateText);
        } else {
            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(itm);
            QString text = QObject::tr("%1)&nbsp;Frame&nbsp;")
                           .arg(frame->number);
            int binaryDataSize = frame->binaryDataSize() / 1024;
            if (frame->state().isEmpty())
                return QObject::tr(
                    "<b>%1&nbsp;</b>(binary&nbsp;data&nbsp;size&nbsp;=&nbsp;%2kB)")
                    .arg(text)
                    .arg(binaryDataSize);
            else
                return QObject::tr(
                    "<b>%1&nbsp;(binary&nbsp;data&nbsp;size&nbsp;=&nbsp;%2kB)</b>"
                    "<br/>%3")
                    .arg(text)
                    .arg(binaryDataSize)
                    .arg(stateText);
        }
    }
    case ApiTraceModel::EventRole:
        return QVariant::fromValue(itm);
    }

    return QVariant();
}
Exemple #7
0
void MainWindow::replayTrace(bool dumpState, bool dumpThumbnails)
{
    if (m_trace->fileName().isEmpty()) {
        return;
    }

    m_retracer->setFileName(m_trace->fileName());
    m_retracer->setAPI(m_api);
    m_retracer->setCaptureState(dumpState);
    m_retracer->setCaptureThumbnails(dumpThumbnails);
    if (m_retracer->captureState() && m_selectedEvent) {
        int index = 0;
        if (m_selectedEvent->type() == ApiTraceEvent::Call) {
            index = static_cast<ApiTraceCall*>(m_selectedEvent)->index();
        } else if (m_selectedEvent->type() == ApiTraceEvent::Frame) {
            ApiTraceFrame *frame =
                static_cast<ApiTraceFrame*>(m_selectedEvent);
            if (frame->isEmpty()) {
                //XXX i guess we could still get the current state
                qDebug()<<"tried to get a state for an empty frame";
                return;
            }
            index = frame->lastCallIndex();
        } else {
            qDebug()<<"Unknown event type";
            return;
        }
        m_retracer->setCaptureAtCallNumber(index);
    }
    m_retracer->start();

    m_ui.actionStop->setEnabled(true);
    m_progressBar->show();
    if (dumpState || dumpThumbnails) {
        if (dumpState && dumpThumbnails) {
            statusBar()->showMessage(
                tr("Looking up the state and capturing thumbnails..."));
        } else if (dumpState) {
            statusBar()->showMessage(
                tr("Looking up the state..."));
        } else if (dumpThumbnails) {
            statusBar()->showMessage(
                tr("Capturing thumbnails..."));
        }
    } else if (m_retracer->isProfiling()) {
        statusBar()->showMessage(
                    tr("Profiling draw calls in trace file..."));
    } else {
        statusBar()->showMessage(
            tr("Replaying the trace file..."));
    }
}
Exemple #8
0
bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
{
    if (parent.isValid()) {
        ApiTraceEvent *event = item(parent);
        if (event && event->type() == ApiTraceEvent::Frame) {
            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
            return !frame->isEmpty();
        } else
            return false;
    } else {
        return (rowCount() > 0);
    }
}
bool ApiTraceModel::canFetchMore(const QModelIndex &parent) const
{
    if (parent.isValid()) {
        ApiTraceEvent *event = item(parent);
        if (event && event->type() == ApiTraceEvent::Frame) {
            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
            return !frame->isLoaded() && !m_loadingFrames.contains(frame);
        } else
            return false;
    } else {
        return false;
    }
}
void ApiTraceModel::fetchMore(const QModelIndex &parent)
{
    if (parent.isValid()) {
        ApiTraceEvent *event = item(parent);
        if (event && event->type() == ApiTraceEvent::Frame) {
            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);

            Q_ASSERT(!frame->isLoaded());
            m_loadingFrames.insert(frame);

            m_trace->loadFrame(frame);
        }
    }
}
Exemple #11
0
int ApiTraceModel::rowCount(const QModelIndex &parent) const
{
    if (!parent.isValid())
        return m_trace->numFrames();

    ApiTraceEvent *event = item(parent);
    if (!event || event->type() == ApiTraceEvent::Call)
        return 0;

    ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
    if (frame)
        return frame->numChildren();

    return 0;
}
Exemple #12
0
QModelIndex ApiTraceModel::indexForCall(ApiTraceCall *call) const
{
    if (!call) {
        return QModelIndex();
    }

    ApiTraceFrame *frame = call->parentFrame();
    Q_ASSERT(frame);

    int row = frame->callIndex(call);
    if (row < 0) {
        qDebug() << "Couldn't find call num "<<call->index()<<" inside parent!";
        return QModelIndex();
    }
    return createIndex(row, 0, call);
}
Exemple #13
0
void MainWindow::trimEvent()
{

    int trimIndex;
    if (m_trimEvent->type() == ApiTraceEvent::Call) {
        ApiTraceCall *call = static_cast<ApiTraceCall*>(m_trimEvent);
        trimIndex = call->index();
    } else if (m_trimEvent->type() == ApiTraceEvent::Frame) {
        ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(m_trimEvent);
        const QList<ApiTraceFrame*> frames = m_trace->frames();
        trimIndex = frame->lastCallIndex();
    }

    m_trimProcess->setTracePath(m_trace->fileName());
    m_trimProcess->setTrimIndex(trimIndex);

    m_trimProcess->start();
}
bool ApiTraceModel::hasChildren(const QModelIndex &parent) const
{
    if (parent.isValid()) {
        ApiTraceEvent *event = item(parent);
        if (!event)
            return false;
        if (event->type() == ApiTraceEvent::Frame) {
            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
            return !frame->isEmpty();
        } else {
            Q_ASSERT(event->type() == ApiTraceEvent::Call);
            ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
            return call->numChildren() != 0;
        }
    } else {
        return (rowCount() > 0);
    }
}
Exemple #15
0
void ApiTraceModel::stateSetOnEvent(ApiTraceEvent *event)
{
    if (!event)
        return;

    if (event->type() == ApiTraceEvent::Call) {
        ApiTraceCall *call = static_cast<ApiTraceCall*>(event);
        ApiTraceFrame *frame = call->parentFrame();
        int row = frame->callIndex(call);
        QModelIndex index = createIndex(row, 0, call);
        emit dataChanged(index, index);
    } else if (event->type() == ApiTraceEvent::Frame) {
        ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(event);
        const QList<ApiTraceFrame*> frames = m_trace->frames();
        int row = frames.indexOf(frame);
        QModelIndex index = createIndex(row, 0, frame);
        emit dataChanged(index, index);
    }
}
Exemple #16
0
void ApiTraceModel::callChanged(ApiTraceCall *call)
{
    ApiTrace *trace = call->parentFrame()->parentTrace();

#if 0
    qDebug()<<"Call changed = "<<call->edited();
    qDebug()<<"\ttrace edited = "<<trace->edited();
    qDebug()<<"\ttrace file = "<<trace->fileName();
    qDebug()<<"\ttrace needs saving = "<<trace->needsSaving();
#endif

    Q_ASSERT(trace);
    if (trace->needsSaving())
        trace->save();

    ApiTraceFrame *frame = call->parentFrame();
    int row = frame->callIndex(call);
    QModelIndex index = createIndex(row, 0, call);
    emit dataChanged(index, index);
}
Exemple #17
0
void TraceLoader::parseTrace()
{
    QList<ApiTraceFrame*> frames;
    ApiTraceFrame *currentFrame = 0;
    int frameCount = 0;
    QStack<ApiTraceCall*> groups;
    QVector<ApiTraceCall*> topLevelItems;
    QVector<ApiTraceCall*> allCalls;
    quint64 binaryDataSize = 0;

    int lastPercentReport = 0;

    trace::Call *call = m_parser.parse_call();
    while (call) {
        //std::cout << *call;
        if (!currentFrame) {
            currentFrame = new ApiTraceFrame();
            currentFrame->number = frameCount;
            ++frameCount;
        }
        ApiTraceCall *apiCall =
            apiCallFromTraceCall(call, m_helpHash, currentFrame, groups.isEmpty() ? 0 : groups.top(), this);
        allCalls.append(apiCall);
        if (groups.count() == 0) {
            topLevelItems.append(apiCall);
        }
        if (call->flags & trace::CALL_FLAG_MARKER_PUSH) {
            groups.push(apiCall);
        } else if (call->flags & trace::CALL_FLAG_MARKER_POP) {
            groups.top()->finishedAddingChildren();
            groups.pop();
        }
        if (!groups.isEmpty()) {
            groups.top()->addChild(apiCall);
        }
        if (apiCall->hasBinaryData()) {
            QByteArray data =
                apiCall->arguments()[apiCall->binaryDataIndex()].toByteArray();
            binaryDataSize += data.size();
        }
        if (call->flags & trace::CALL_FLAG_END_FRAME) {
            allCalls.squeeze();
            topLevelItems.squeeze();
            if (topLevelItems.count() == allCalls.count()) {
                currentFrame->setCalls(allCalls, allCalls, binaryDataSize);
            } else {
                currentFrame->setCalls(topLevelItems, allCalls, binaryDataSize);
            }
            allCalls.clear();
            groups.clear();
            topLevelItems.clear();
            frames.append(currentFrame);
            currentFrame = 0;
            binaryDataSize = 0;
            if (frames.count() >= FRAMES_TO_CACHE) {
                emit framesLoaded(frames);
                frames.clear();
            }
            if (m_parser.percentRead() - lastPercentReport >= 5) {
                emit parsed(m_parser.percentRead());
                lastPercentReport = m_parser.percentRead();
            }
        }
        delete call;
        call = m_parser.parse_call();
    }

    //last frames won't have markers
    //  it's just a bunch of Delete calls for every object
    //  after the last SwapBuffers
    if (currentFrame) {
        allCalls.squeeze();
        if (topLevelItems.count() == allCalls.count()) {
            currentFrame->setCalls(allCalls, allCalls, binaryDataSize);
        } else {
            currentFrame->setCalls(topLevelItems, allCalls, binaryDataSize);
        }
        frames.append(currentFrame);
        currentFrame = 0;
    }
    if (frames.count()) {
        emit framesLoaded(frames);
    }
}
QVariant ApiTraceModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    if (index.column() != 0)
        return QVariant();

    ApiTraceEvent *itm = item(index);
    if (!itm) {
        return QVariant();
    }

    switch (role) {
    case Qt::DisplayRole:
        return itm->staticText().text();
    case Qt::DecorationRole:
        return QImage();
    case Qt::ToolTipRole: {
        const QString stateText = tr("State info available.");
        if (itm->type() == ApiTraceEvent::Call) {
            ApiTraceCall *call = static_cast<ApiTraceCall*>(itm);
            if (!call->hasState())
                return QString::fromLatin1("%1)&nbsp;<b>%2</b>")
                    .arg(call->index())
                    .arg(call->name());
            else
                return QString::fromLatin1("%1)&nbsp;<b>%2</b><br/>%3")
                    .arg(call->index())
                    .arg(call->name())
                    .arg(stateText);
        } else {
            const char *htmlTempl =
                    "<div>\n"
                    "<div>\n"
                    "%1"
                    "<span style=\"font-weight:bold; font-size:large; vertical-align:center; padding-bottom: 30px \">\n"
                    "Frame %2</span>\n"
                    "</div>\n"
                    "<div >%3 calls%4</div>\n"
                    "</div>\n";


            ApiTraceFrame *frame = static_cast<ApiTraceFrame*>(itm);
            QString thumbStr, sizeStr;

            if (frame->hasState()) {
                static const char *imgTempl =
                        "<img style=\"float:left;\" "
                        "src=\"data:image/png;base64,%1\"/>\n";
                static const char *sizeTempl =
                        ", %1kb";

                ApiFramebuffer fbo = frame->state()->colorBuffer();
                QImage thumb = fbo.thumb();
                if (!thumb.isNull()) {
                    QByteArray ba;
                    QBuffer buffer(&ba);
                    buffer.open(QIODevice::WriteOnly);
                    thumb.save(&buffer, "PNG");
                    thumbStr = tr(imgTempl).arg(
                                QString(buffer.data().toBase64()));
                }

                int binaryDataSize = frame->binaryDataSize() / 1024;
                if (binaryDataSize > 0) {
                    sizeStr = tr(sizeTempl).arg(binaryDataSize);
                }
            }

            int numCalls = frame->isLoaded()
                    ? frame->numTotalCalls()
                    : frame->numChildrenToLoad();

            return tr(htmlTempl)
                    .arg(thumbStr)
                    .arg(frame->number)
                    .arg(numCalls)
                    .arg(sizeStr);
        }
    }
    case ApiTraceModel::EventRole:
        return QVariant::fromValue(itm);
    }

    return QVariant();
}