Don't use AbstractTimelineModel's private class

We can easily implement all needed functionality with only the public
interface.

Change-Id: Ibf22f2e4bc27a8b506f0164e0e1fdf529b1a9e45
Reviewed-by: Kai Koehne <kai.koehne@theqtcompany.com>
This commit is contained in:
Ulf Hermann
2014-10-27 19:54:23 +01:00
committed by Ulf Hermann
parent 587caba5e7
commit bfbad9b941
8 changed files with 254 additions and 344 deletions

View File

@@ -19,21 +19,14 @@
#include "inputeventsmodel.h" #include "inputeventsmodel.h"
#include "qmldebug/qmlprofilereventtypes.h" #include "qmldebug/qmlprofilereventtypes.h"
#include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilermodelmanager.h"
#include "qmlprofiler/abstracttimelinemodel_p.h"
namespace QmlProfilerExtension { namespace QmlProfilerExtension {
namespace Internal { namespace Internal {
using namespace QmlProfiler; using namespace QmlProfiler;
class InputEventsModel::InputEventsModelPrivate : public AbstractTimelineModelPrivate
{
Q_DECLARE_PUBLIC(InputEventsModel)
};
InputEventsModel::InputEventsModel(QObject *parent) InputEventsModel::InputEventsModel(QObject *parent)
: AbstractTimelineModel(new InputEventsModelPrivate(), : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)),
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileInputEvents)),
QmlDebug::Event, QmlDebug::MaximumRangeType, parent) QmlDebug::Event, QmlDebug::MaximumRangeType, parent)
{ {
} }
@@ -45,8 +38,7 @@ quint64 InputEventsModel::features() const
int InputEventsModel::selectionId(int index) const int InputEventsModel::selectionId(int index) const
{ {
Q_D(const InputEventsModel); return modelManager()->qmlModel()->getEventTypes()[typeId(index)].detailType;
return d->modelManager->qmlModel()->getEventTypes()[typeId(index)].detailType;
} }
QColor InputEventsModel::color(int index) const QColor InputEventsModel::color(int index) const
@@ -56,10 +48,9 @@ QColor InputEventsModel::color(int index) const
QVariantList InputEventsModel::labels() const QVariantList InputEventsModel::labels() const
{ {
Q_D(const InputEventsModel);
QVariantList result; QVariantList result;
if (d->expanded && !d->hidden && !isEmpty()) { if (expanded() && !hidden() && !isEmpty()) {
{ {
QVariantMap element; QVariantMap element;
element.insert(QLatin1String("description"), QVariant(tr("Mouse Events"))); element.insert(QLatin1String("description"), QVariant(tr("Mouse Events")));
@@ -96,9 +87,8 @@ int InputEventsModel::row(int index) const
void InputEventsModel::loadData() void InputEventsModel::loadData()
{ {
Q_D(InputEventsModel);
clear(); clear();
QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel();
if (simpleModel->isEmpty()) if (simpleModel->isEmpty())
return; return;
@@ -108,12 +98,11 @@ void InputEventsModel::loadData()
if (!accepted(type)) if (!accepted(type))
continue; continue;
insert(event.startTime, 0, event.typeIndex); insert(event.startTime, 0, event.typeIndex);
d->modelManager->modelProxyCountUpdated(d->modelId, count(), updateProgress(count(), simpleModel->getEvents().count());
simpleModel->getEvents().count());
} }
d->collapsedRowCount = 2; setCollapsedRowCount(2);
d->expandedRowCount = 3; setExpandedRowCount(3);
d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); updateProgress(1, 1);
} }
bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const bool InputEventsModel::accepted(const QmlProfilerDataModel::QmlEventTypeData &event) const

View File

@@ -27,8 +27,6 @@ namespace Internal {
class InputEventsModel : public QmlProfiler::AbstractTimelineModel class InputEventsModel : public QmlProfiler::AbstractTimelineModel
{ {
Q_OBJECT Q_OBJECT
class InputEventsModelPrivate;
Q_DECLARE_PRIVATE(InputEventsModel)
protected: protected:
bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const; bool accepted(const QmlProfiler::QmlProfilerDataModel::QmlEventTypeData &event) const;

View File

@@ -19,7 +19,6 @@
#include "memoryusagemodel.h" #include "memoryusagemodel.h"
#include "qmldebug/qmlprofilereventtypes.h" #include "qmldebug/qmlprofilereventtypes.h"
#include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilermodelmanager.h"
#include "qmlprofiler/abstracttimelinemodel_p.h"
#include <QStack> #include <QStack>
@@ -28,20 +27,8 @@ namespace Internal {
using namespace QmlProfiler; using namespace QmlProfiler;
class MemoryUsageModel::MemoryUsageModelPrivate : public AbstractTimelineModelPrivate
{
public:
static QString memoryTypeName(int type);
QVector<MemoryAllocation> data;
qint64 maxSize;
private:
Q_DECLARE_PUBLIC(MemoryUsageModel)
};
MemoryUsageModel::MemoryUsageModel(QObject *parent) MemoryUsageModel::MemoryUsageModel(QObject *parent)
: AbstractTimelineModel(new MemoryUsageModelPrivate(), : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)),
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileMemory)),
QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent) QmlDebug::MemoryAllocation, QmlDebug::MaximumRangeType, parent)
{ {
} }
@@ -54,15 +41,13 @@ quint64 MemoryUsageModel::features() const
int MemoryUsageModel::rowMaxValue(int rowNumber) const int MemoryUsageModel::rowMaxValue(int rowNumber) const
{ {
Q_D(const MemoryUsageModel);
Q_UNUSED(rowNumber); Q_UNUSED(rowNumber);
return d->maxSize; return m_maxSize;
} }
int MemoryUsageModel::row(int index) const int MemoryUsageModel::row(int index) const
{ {
Q_D(const MemoryUsageModel); QmlDebug::MemoryType type = m_data[index].type;
QmlDebug::MemoryType type = d->data[index].type;
if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem) if (type == QmlDebug::HeapPage || type == QmlDebug::LargeItem)
return 1; return 1;
else else
@@ -71,8 +56,7 @@ int MemoryUsageModel::row(int index) const
int MemoryUsageModel::selectionId(int index) const int MemoryUsageModel::selectionId(int index) const
{ {
Q_D(const MemoryUsageModel); return m_data[index].type;
return d->data[index].type;
} }
QColor MemoryUsageModel::color(int index) const QColor MemoryUsageModel::color(int index) const
@@ -82,8 +66,7 @@ QColor MemoryUsageModel::color(int index) const
float MemoryUsageModel::relativeHeight(int index) const float MemoryUsageModel::relativeHeight(int index) const
{ {
Q_D(const MemoryUsageModel); return qMin(1.0f, (float)m_data[index].size / (float)m_maxSize);
return qMin(1.0f, (float)d->data[index].size / (float)d->maxSize);
} }
QVariantMap MemoryUsageModel::location(int index) const QVariantMap MemoryUsageModel::location(int index) const
@@ -92,13 +75,12 @@ QVariantMap MemoryUsageModel::location(int index) const
static const QLatin1String line("line"); static const QLatin1String line("line");
static const QLatin1String column("column"); static const QLatin1String column("column");
Q_D(const MemoryUsageModel);
QVariantMap result; QVariantMap result;
int originType = d->data[index].originTypeIndex; int originType = m_data[index].originTypeIndex;
if (originType > -1) { if (originType > -1) {
const QmlDebug::QmlEventLocation &location = const QmlDebug::QmlEventLocation &location =
d->modelManager->qmlModel()->getEventTypes().at(originType).location; modelManager()->qmlModel()->getEventTypes().at(originType).location;
result.insert(file, location.filename); result.insert(file, location.filename);
result.insert(line, location.line); result.insert(line, location.line);
@@ -110,10 +92,9 @@ QVariantMap MemoryUsageModel::location(int index) const
QVariantList MemoryUsageModel::labels() const QVariantList MemoryUsageModel::labels() const
{ {
Q_D(const MemoryUsageModel);
QVariantList result; QVariantList result;
if (d->expanded && !d->hidden && !isEmpty()) { if (expanded() && !hidden() && !isEmpty()) {
{ {
QVariantMap element; QVariantMap element;
element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation"))); element.insert(QLatin1String("description"), QVariant(tr("Memory Allocation")));
@@ -136,10 +117,8 @@ QVariantList MemoryUsageModel::labels() const
QVariantMap MemoryUsageModel::details(int index) const QVariantMap MemoryUsageModel::details(int index) const
{ {
Q_D(const MemoryUsageModel);
QVariantMap result; QVariantMap result;
const MemoryAllocation *ev = &d->data[index]; const MemoryAllocation *ev = &m_data[index];
if (ev->allocated >= -ev->deallocated) if (ev->allocated >= -ev->deallocated)
result.insert(QLatin1String("displayName"), tr("Memory Allocated")); result.insert(QLatin1String("displayName"), tr("Memory Allocated"));
@@ -155,11 +134,11 @@ QVariantMap MemoryUsageModel::details(int index) const
result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated)); result.insert(tr("Deallocated"), QString::fromLatin1("%1 bytes").arg(-ev->deallocated));
result.insert(tr("Deallocations"), QString::number(ev->deallocations)); result.insert(tr("Deallocations"), QString::number(ev->deallocations));
} }
result.insert(tr("Type"), QVariant(MemoryUsageModelPrivate::memoryTypeName(ev->type))); result.insert(tr("Type"), QVariant(memoryTypeName(ev->type)));
if (ev->originTypeIndex != -1) { if (ev->originTypeIndex != -1) {
result.insert(tr("Location"), result.insert(tr("Location"),
d->modelManager->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName); modelManager()->qmlModel()->getEventTypes().at(ev->originTypeIndex).displayName);
} }
return result; return result;
} }
@@ -175,9 +154,8 @@ struct RangeStackFrame {
void MemoryUsageModel::loadData() void MemoryUsageModel::loadData()
{ {
Q_D(MemoryUsageModel);
clear(); clear();
QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel();
if (simpleModel->isEmpty()) if (simpleModel->isEmpty())
return; return;
@@ -203,7 +181,7 @@ void MemoryUsageModel::loadData()
} }
if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) { if (type.detailType == QmlDebug::SmallItem || type.detailType == QmlDebug::LargeItem) {
MemoryAllocation &last = currentUsageIndex > -1 ? d->data[currentUsageIndex] : dummy; MemoryAllocation &last = currentUsageIndex > -1 ? m_data[currentUsageIndex] : dummy;
if (!rangeStack.empty() && type.detailType == last.type && if (!rangeStack.empty() && type.detailType == last.type &&
last.originTypeIndex == rangeStack.top().originTypeIndex && last.originTypeIndex == rangeStack.top().originTypeIndex &&
rangeStack.top().startTime < startTime(currentUsageIndex)) { rangeStack.top().startTime < startTime(currentUsageIndex)) {
@@ -220,12 +198,12 @@ void MemoryUsageModel::loadData()
event.startTime - startTime(currentUsageIndex) - 1); event.startTime - startTime(currentUsageIndex) - 1);
} }
currentUsageIndex = insertStart(event.startTime, event.typeIndex); currentUsageIndex = insertStart(event.startTime, event.typeIndex);
d->data.insert(currentUsageIndex, allocation); m_data.insert(currentUsageIndex, allocation);
} }
} }
if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) { if (type.detailType == QmlDebug::HeapPage || type.detailType == QmlDebug::LargeItem) {
MemoryAllocation &last = currentJSHeapIndex > -1 ? d->data[currentJSHeapIndex] : dummy; MemoryAllocation &last = currentJSHeapIndex > -1 ? m_data[currentJSHeapIndex] : dummy;
if (!rangeStack.empty() && type.detailType == last.type && if (!rangeStack.empty() && type.detailType == last.type &&
last.originTypeIndex == rangeStack.top().originTypeIndex && last.originTypeIndex == rangeStack.top().originTypeIndex &&
rangeStack.top().startTime < startTime(currentJSHeapIndex)) { rangeStack.top().startTime < startTime(currentJSHeapIndex)) {
@@ -237,42 +215,41 @@ void MemoryUsageModel::loadData()
allocation.update(event.numericData1); allocation.update(event.numericData1);
currentSize = allocation.size; currentSize = allocation.size;
if (currentSize > d->maxSize) if (currentSize > m_maxSize)
d->maxSize = currentSize; m_maxSize = currentSize;
if (currentJSHeapIndex != -1) if (currentJSHeapIndex != -1)
insertEnd(currentJSHeapIndex, insertEnd(currentJSHeapIndex,
event.startTime - startTime(currentJSHeapIndex) - 1); event.startTime - startTime(currentJSHeapIndex) - 1);
currentJSHeapIndex = insertStart(event.startTime, event.typeIndex); currentJSHeapIndex = insertStart(event.startTime, event.typeIndex);
d->data.insert(currentJSHeapIndex, allocation); m_data.insert(currentJSHeapIndex, allocation);
} }
} }
d->modelManager->modelProxyCountUpdated(d->modelId, count(), updateProgress(count(), simpleModel->getEvents().count());
simpleModel->getEvents().count());
} }
if (currentJSHeapIndex != -1) if (currentJSHeapIndex != -1)
insertEnd(currentJSHeapIndex, d->modelManager->traceTime()->endTime() - insertEnd(currentJSHeapIndex, modelManager()->traceTime()->endTime() -
startTime(currentJSHeapIndex) - 1); startTime(currentJSHeapIndex) - 1);
if (currentUsageIndex != -1) if (currentUsageIndex != -1)
insertEnd(currentUsageIndex, d->modelManager->traceTime()->endTime() - insertEnd(currentUsageIndex, modelManager()->traceTime()->endTime() -
startTime(currentUsageIndex) - 1); startTime(currentUsageIndex) - 1);
computeNesting(); computeNesting();
d->expandedRowCount = d->collapsedRowCount = 3; setExpandedRowCount(3);
d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); setCollapsedRowCount(3);
updateProgress(1, 1);
} }
void MemoryUsageModel::clear() void MemoryUsageModel::clear()
{ {
Q_D(MemoryUsageModel); m_data.clear();
d->data.clear(); m_maxSize = 1;
d->maxSize = 1;
AbstractTimelineModel::clear(); AbstractTimelineModel::clear();
} }
QString MemoryUsageModel::MemoryUsageModelPrivate::memoryTypeName(int type) QString MemoryUsageModel::memoryTypeName(int type)
{ {
switch (type) { switch (type) {
case QmlDebug::HeapPage: return tr("Heap Allocation"); case QmlDebug::HeapPage: return tr("Heap Allocation");

View File

@@ -67,8 +67,10 @@ protected:
void clear(); void clear();
private: private:
class MemoryUsageModelPrivate; static QString memoryTypeName(int type);
Q_DECLARE_PRIVATE(MemoryUsageModel)
QVector<MemoryAllocation> m_data;
qint64 m_maxSize;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -19,72 +19,17 @@
#include "pixmapcachemodel.h" #include "pixmapcachemodel.h"
#include "qmldebug/qmlprofilereventtypes.h" #include "qmldebug/qmlprofilereventtypes.h"
#include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilermodelmanager.h"
#include "qmlprofiler/abstracttimelinemodel_p.h"
#include <QDebug>
#include <QSize>
namespace QmlProfilerExtension { namespace QmlProfilerExtension {
namespace Internal { namespace Internal {
using namespace QmlProfiler; using namespace QmlProfiler;
enum CacheState {
Uncached, // After loading started (or some other proof of existence) or after uncaching
ToBeCached, // After determining the pixmap is to be cached but before knowing its size
Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap
Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached
Corrupt // If after ToBeCached we learn that loading failed
};
enum LoadState {
Initial,
Loading,
Finished,
Error
};
struct PixmapState {
PixmapState(int width, int height, CacheState cache = Uncached) :
size(width, height), started(-1), loadState(Initial), cacheState(cache) {}
PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {}
QSize size;
int started;
LoadState loadState;
CacheState cacheState;
};
struct Pixmap {
Pixmap() {}
Pixmap(const QString &url) : url(url), sizes(1) {}
QString url;
QVector<PixmapState> sizes;
};
class PixmapCacheModel::PixmapCacheModelPrivate : public AbstractTimelineModelPrivate
{
public:
void computeMaxCacheSize();
void resizeUnfinishedLoads();
void flattenLoads();
int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize,
PixmapCacheEvent &newEvent, int typeId);
QVector<PixmapCacheEvent> data;
QVector<Pixmap> pixmaps;
qint64 maxCacheSize;
private:
Q_DECLARE_PUBLIC(PixmapCacheModel)
};
PixmapCacheModel::PixmapCacheModel(QObject *parent) PixmapCacheModel::PixmapCacheModel(QObject *parent)
: AbstractTimelineModel(new PixmapCacheModelPrivate(), : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)),
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfilePixmapCache)),
QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent) QmlDebug::PixmapCacheEvent, QmlDebug::MaximumRangeType, parent)
{ {
Q_D(PixmapCacheModel); m_maxCacheSize = 1;
d->maxCacheSize = 1;
} }
quint64 PixmapCacheModel::features() const quint64 PixmapCacheModel::features() const
@@ -94,9 +39,8 @@ quint64 PixmapCacheModel::features() const
int PixmapCacheModel::rowMaxValue(int rowNumber) const int PixmapCacheModel::rowMaxValue(int rowNumber) const
{ {
Q_D(const PixmapCacheModel);
if (rowNumber == 1) { if (rowNumber == 1) {
return d->maxCacheSize; return m_maxCacheSize;
} else { } else {
return AbstractTimelineModel::rowMaxValue(rowNumber); return AbstractTimelineModel::rowMaxValue(rowNumber);
} }
@@ -104,33 +48,29 @@ int PixmapCacheModel::rowMaxValue(int rowNumber) const
int PixmapCacheModel::row(int index) const int PixmapCacheModel::row(int index) const
{ {
Q_D(const PixmapCacheModel); if (expanded())
if (d->expanded)
return selectionId(index) + 1; return selectionId(index) + 1;
return d->data[index].rowNumberCollapsed; return m_data[index].rowNumberCollapsed;
} }
int PixmapCacheModel::selectionId(int index) const int PixmapCacheModel::selectionId(int index) const
{ {
Q_D(const PixmapCacheModel); return m_data[index].pixmapEventType == PixmapCacheCountChanged ?
return d->data[index].pixmapEventType == PixmapCacheCountChanged ? 0 : m_data[index].urlIndex + 1;
0 : d->data[index].urlIndex + 1;
} }
QColor PixmapCacheModel::color(int index) const QColor PixmapCacheModel::color(int index) const
{ {
Q_D(const PixmapCacheModel); if (m_data[index].pixmapEventType == PixmapCacheCountChanged)
if (d->data[index].pixmapEventType == PixmapCacheCountChanged) return colorByHue(s_pixmapCacheCountHue);
return colorByHue(PixmapCacheCountHue);
return colorBySelectionId(index); return colorBySelectionId(index);
} }
float PixmapCacheModel::relativeHeight(int index) const float PixmapCacheModel::relativeHeight(int index) const
{ {
Q_D(const PixmapCacheModel); if (m_data[index].pixmapEventType == PixmapCacheCountChanged)
if (d->data[index].pixmapEventType == PixmapCacheCountChanged) return (float)m_data[index].cacheSize / (float)m_maxCacheSize;
return (float)d->data[index].cacheSize / (float)d->maxCacheSize;
else else
return 1.0f; return 1.0f;
} }
@@ -145,10 +85,9 @@ QString getFilenameOnly(QString absUrl)
QVariantList PixmapCacheModel::labels() const QVariantList PixmapCacheModel::labels() const
{ {
Q_D(const PixmapCacheModel);
QVariantList result; QVariantList result;
if (d->expanded && !d->hidden && !isEmpty()) { if (expanded() && !hidden() && !isEmpty()) {
{ {
// Cache Size // Cache Size
QVariantMap element; QVariantMap element;
@@ -158,12 +97,12 @@ QVariantList PixmapCacheModel::labels() const
result << element; result << element;
} }
for (int i=0; i < d->pixmaps.count(); i++) { for (int i=0; i < m_pixmaps.count(); i++) {
// Loading // Loading
QVariantMap element; QVariantMap element;
element.insert(QLatin1String("displayName"), d->pixmaps[i].url); element.insert(QLatin1String("displayName"), m_pixmaps[i].url);
element.insert(QLatin1String("description"), element.insert(QLatin1String("description"),
QVariant(getFilenameOnly(d->pixmaps[i].url))); QVariant(getFilenameOnly(m_pixmaps[i].url)));
element.insert(QLatin1String("id"), QVariant(i+1)); element.insert(QLatin1String("id"), QVariant(i+1));
result << element; result << element;
@@ -175,27 +114,26 @@ QVariantList PixmapCacheModel::labels() const
QVariantMap PixmapCacheModel::details(int index) const QVariantMap PixmapCacheModel::details(int index) const
{ {
Q_D(const PixmapCacheModel);
QVariantMap result; QVariantMap result;
const PixmapCacheEvent *ev = &d->data[index]; const PixmapCacheEvent *ev = &m_data[index];
if (ev->pixmapEventType == PixmapCacheCountChanged) { if (ev->pixmapEventType == PixmapCacheCountChanged) {
result.insert(QLatin1String("displayName"), tr("Image Cached")); result.insert(QLatin1String("displayName"), tr("Image Cached"));
} else { } else {
if (ev->pixmapEventType == PixmapLoadingStarted) { if (ev->pixmapEventType == PixmapLoadingStarted) {
result.insert(QLatin1String("displayName"), tr("Image Loaded")); result.insert(QLatin1String("displayName"), tr("Image Loaded"));
if (d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished) if (m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].loadState != Finished)
result.insert(tr("Result"), tr("Load Error")); result.insert(tr("Result"), tr("Load Error"));
} }
result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index)));
} }
result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize)); result.insert(tr("Cache Size"), QString::fromLatin1("%1 px").arg(ev->cacheSize));
result.insert(tr("File"), getFilenameOnly(d->pixmaps[ev->urlIndex].url)); result.insert(tr("File"), getFilenameOnly(m_pixmaps[ev->urlIndex].url));
result.insert(tr("Width"), QString::fromLatin1("%1 px") result.insert(tr("Width"), QString::fromLatin1("%1 px")
.arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width())); .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.width()));
result.insert(tr("Height"), QString::fromLatin1("%1 px") result.insert(tr("Height"), QString::fromLatin1("%1 px")
.arg(d->pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height())); .arg(m_pixmaps[ev->urlIndex].sizes[ev->sizeIndex].size.height()));
return result; return result;
} }
@@ -231,9 +169,8 @@ QVariantMap PixmapCacheModel::details(int index) const
void PixmapCacheModel::loadData() void PixmapCacheModel::loadData()
{ {
Q_D(PixmapCacheModel);
clear(); clear();
QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel();
if (simpleModel->isEmpty()) if (simpleModel->isEmpty())
return; return;
@@ -247,24 +184,24 @@ void PixmapCacheModel::loadData()
continue; continue;
PixmapCacheEvent newEvent; PixmapCacheEvent newEvent;
newEvent.pixmapEventType = type.detailType; newEvent.pixmapEventType = static_cast<PixmapEventType>(type.detailType);
qint64 pixmapStartTime = event.startTime; qint64 pixmapStartTime = event.startTime;
newEvent.urlIndex = -1; newEvent.urlIndex = -1;
for (QVector<Pixmap>::const_iterator it(d->pixmaps.cend()); it != d->pixmaps.cbegin();) { for (QVector<Pixmap>::const_iterator it(m_pixmaps.cend()); it != m_pixmaps.cbegin();) {
if ((--it)->url == type.location.filename) { if ((--it)->url == type.location.filename) {
newEvent.urlIndex = it - d->pixmaps.cbegin(); newEvent.urlIndex = it - m_pixmaps.cbegin();
break; break;
} }
} }
newEvent.sizeIndex = -1; newEvent.sizeIndex = -1;
if (newEvent.urlIndex == -1) { if (newEvent.urlIndex == -1) {
newEvent.urlIndex = d->pixmaps.count(); newEvent.urlIndex = m_pixmaps.count();
d->pixmaps << Pixmap(type.location.filename); m_pixmaps << Pixmap(type.location.filename);
} }
Pixmap &pixmap = d->pixmaps[newEvent.urlIndex]; Pixmap &pixmap = m_pixmaps[newEvent.urlIndex];
switch (newEvent.pixmapEventType) { switch (newEvent.pixmapEventType) {
case PixmapSizeKnown: {// pixmap size case PixmapSizeKnown: {// pixmap size
// Look for pixmaps for which we don't know the size, yet and which have actually been // Look for pixmaps for which we don't know the size, yet and which have actually been
@@ -290,7 +227,7 @@ void PixmapCacheModel::loadData()
PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; PixmapState &state = pixmap.sizes[newEvent.sizeIndex];
if (state.cacheState == ToBeCached) { if (state.cacheState == ToBeCached) {
lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, pixmapStartTime, lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime,
state.size.width() * state.size.height(), newEvent, state.size.width() * state.size.height(), newEvent,
event.typeIndex); event.typeIndex);
state.cacheState = Cached; state.cacheState = Cached;
@@ -351,8 +288,8 @@ void PixmapCacheModel::loadData()
pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached); pixmap.sizes << PixmapState(uncache ? Uncached : ToBeCached);
} }
lastCacheSizeEvent = d->updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize, lastCacheSizeEvent = updateCacheCount(lastCacheSizeEvent, pixmapStartTime, pixSize,
newEvent, event.typeIndex); newEvent, event.typeIndex);
break; break;
} }
case PixmapLoadingStarted: { // Load case PixmapLoadingStarted: { // Load
@@ -373,7 +310,7 @@ void PixmapCacheModel::loadData()
PixmapState &state = pixmap.sizes[newEvent.sizeIndex]; PixmapState &state = pixmap.sizes[newEvent.sizeIndex];
state.loadState = Loading; state.loadState = Loading;
state.started = insertStart(pixmapStartTime, event.typeIndex); state.started = insertStart(pixmapStartTime, event.typeIndex);
d->data.insert(state.started, newEvent); m_data.insert(state.started, newEvent);
break; break;
} }
case PixmapLoadingFinished: case PixmapLoadingFinished:
@@ -416,16 +353,16 @@ void PixmapCacheModel::loadData()
// If the pixmap loading wasn't started, start it at traceStartTime() // If the pixmap loading wasn't started, start it at traceStartTime()
if (state.loadState == Initial) { if (state.loadState == Initial) {
newEvent.pixmapEventType = PixmapLoadingStarted; newEvent.pixmapEventType = PixmapLoadingStarted;
state.started = insert(d->modelManager->traceTime()->startTime(), pixmapStartTime - state.started = insert(modelManager()->traceTime()->startTime(), pixmapStartTime -
d->modelManager->traceTime()->startTime(), event.typeIndex); modelManager()->traceTime()->startTime(), event.typeIndex);
d->data.insert(state.started, newEvent); m_data.insert(state.started, newEvent);
// All other indices are wrong now as we've prepended. Fix them ... // All other indices are wrong now as we've prepended. Fix them ...
if (lastCacheSizeEvent >= state.started) if (lastCacheSizeEvent >= state.started)
++lastCacheSizeEvent; ++lastCacheSizeEvent;
for (int pixmapIndex = 0; pixmapIndex < d->pixmaps.count(); ++pixmapIndex) { for (int pixmapIndex = 0; pixmapIndex < m_pixmaps.count(); ++pixmapIndex) {
Pixmap &brokenPixmap = d->pixmaps[pixmapIndex]; Pixmap &brokenPixmap = m_pixmaps[pixmapIndex];
for (int sizeIndex = 0; sizeIndex < brokenPixmap.sizes.count(); ++sizeIndex) { for (int sizeIndex = 0; sizeIndex < brokenPixmap.sizes.count(); ++sizeIndex) {
PixmapState &brokenSize = brokenPixmap.sizes[sizeIndex]; PixmapState &brokenSize = brokenPixmap.sizes[sizeIndex];
if ((pixmapIndex != newEvent.urlIndex || sizeIndex != newEvent.sizeIndex) && if ((pixmapIndex != newEvent.urlIndex || sizeIndex != newEvent.sizeIndex) &&
@@ -461,74 +398,69 @@ void PixmapCacheModel::loadData()
break; break;
} }
d->modelManager->modelProxyCountUpdated(d->modelId, count(), updateProgress(count(), 2 * simpleModel->getEvents().count());
2 * simpleModel->getEvents().count());
} }
if (lastCacheSizeEvent != -1) if (lastCacheSizeEvent != -1)
insertEnd(lastCacheSizeEvent, d->modelManager->traceTime()->endTime() - insertEnd(lastCacheSizeEvent, modelManager()->traceTime()->endTime() -
startTime(lastCacheSizeEvent)); startTime(lastCacheSizeEvent));
d->resizeUnfinishedLoads(); resizeUnfinishedLoads();
d->computeMaxCacheSize(); computeMaxCacheSize();
d->flattenLoads(); flattenLoads();
computeNesting(); computeNesting();
d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); updateProgress(1, 1);
} }
void PixmapCacheModel::clear() void PixmapCacheModel::clear()
{ {
Q_D(PixmapCacheModel); m_pixmaps.clear();
d->pixmaps.clear(); m_maxCacheSize = 1;
d->maxCacheSize = 1; m_data.clear();
d->data.clear();
AbstractTimelineModel::clear(); AbstractTimelineModel::clear();
} }
void PixmapCacheModel::PixmapCacheModelPrivate::computeMaxCacheSize() void PixmapCacheModel::computeMaxCacheSize()
{ {
maxCacheSize = 1; m_maxCacheSize = 1;
foreach (const PixmapCacheModel::PixmapCacheEvent &event, data) { foreach (const PixmapCacheModel::PixmapCacheEvent &event, m_data) {
if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) { if (event.pixmapEventType == PixmapCacheModel::PixmapCacheCountChanged) {
if (event.cacheSize > maxCacheSize) if (event.cacheSize > m_maxCacheSize)
maxCacheSize = event.cacheSize; m_maxCacheSize = event.cacheSize;
} }
} }
} }
void PixmapCacheModel::PixmapCacheModelPrivate::resizeUnfinishedLoads() void PixmapCacheModel::resizeUnfinishedLoads()
{ {
Q_Q(PixmapCacheModel);
// all the "load start" events with duration 0 continue till the end of the trace // all the "load start" events with duration 0 continue till the end of the trace
for (int i = 0; i < q->count(); i++) { for (int i = 0; i < count(); i++) {
if (data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted && if (m_data[i].pixmapEventType == PixmapCacheModel::PixmapLoadingStarted &&
ranges[i].duration == 0) { duration(i) == 0) {
q->insertEnd(i, modelManager->traceTime()->endTime() - ranges[i].start); insertEnd(i, modelManager()->traceTime()->endTime() - startTime(i));
} }
} }
} }
void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads() void PixmapCacheModel::flattenLoads()
{ {
Q_Q(PixmapCacheModel); int collapsedRowCount = 0;
collapsedRowCount = 0;
// computes "compressed row" // computes "compressed row"
QVector <qint64> eventEndTimes; QVector <qint64> eventEndTimes;
for (int i = 0; i < q->count(); i++) { for (int i = 0; i < count(); i++) {
PixmapCacheModel::PixmapCacheEvent &event = data[i]; PixmapCacheModel::PixmapCacheEvent &event = m_data[i];
const Range &start = ranges[i];
if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) { if (event.pixmapEventType == PixmapCacheModel::PixmapLoadingStarted) {
event.rowNumberCollapsed = 0; event.rowNumberCollapsed = 0;
while (eventEndTimes.count() > event.rowNumberCollapsed && while (eventEndTimes.count() > event.rowNumberCollapsed &&
eventEndTimes[event.rowNumberCollapsed] > start.start) eventEndTimes[event.rowNumberCollapsed] > startTime(i))
event.rowNumberCollapsed++; event.rowNumberCollapsed++;
if (eventEndTimes.count() == event.rowNumberCollapsed) if (eventEndTimes.count() == event.rowNumberCollapsed)
eventEndTimes << 0; // increase stack length, proper value added below eventEndTimes << 0; // increase stack length, proper value added below
eventEndTimes[event.rowNumberCollapsed] = start.start + start.duration; eventEndTimes[event.rowNumberCollapsed] = endTime(i);
// readjust to account for category empty row and bargraph // readjust to account for category empty row and bargraph
event.rowNumberCollapsed += 2; event.rowNumberCollapsed += 2;
@@ -538,26 +470,25 @@ void PixmapCacheModel::PixmapCacheModelPrivate::flattenLoads()
} }
// Starting from 0, count is maxIndex+1 // Starting from 0, count is maxIndex+1
collapsedRowCount++; setCollapsedRowCount(collapsedRowCount + 1);
expandedRowCount = pixmaps.count() + 2; setExpandedRowCount(m_pixmaps.count() + 2);
} }
int PixmapCacheModel::PixmapCacheModelPrivate::updateCacheCount(int lastCacheSizeEvent, int PixmapCacheModel::updateCacheCount(int lastCacheSizeEvent,
qint64 startTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId) qint64 pixmapStartTime, qint64 pixSize, PixmapCacheEvent &newEvent, int typeId)
{ {
Q_Q(PixmapCacheModel);
newEvent.pixmapEventType = PixmapCacheCountChanged; newEvent.pixmapEventType = PixmapCacheCountChanged;
newEvent.rowNumberCollapsed = 1; newEvent.rowNumberCollapsed = 1;
qint64 prevSize = 0; qint64 prevSize = 0;
if (lastCacheSizeEvent != -1) { if (lastCacheSizeEvent != -1) {
prevSize = data[lastCacheSizeEvent].cacheSize; prevSize = m_data[lastCacheSizeEvent].cacheSize;
q->insertEnd(lastCacheSizeEvent, startTime - ranges[lastCacheSizeEvent].start); insertEnd(lastCacheSizeEvent, pixmapStartTime - startTime(lastCacheSizeEvent));
} }
newEvent.cacheSize = prevSize + pixSize; newEvent.cacheSize = prevSize + pixSize;
int index = q->insertStart(startTime, typeId); int index = insertStart(pixmapStartTime, typeId);
data.insert(index, newEvent); m_data.insert(index, newEvent);
return index; return index;
} }

View File

@@ -24,6 +24,7 @@
#include <QStringList> #include <QStringList>
#include <QColor> #include <QColor>
#include <QSize>
namespace QmlProfilerExtension { namespace QmlProfilerExtension {
namespace Internal { namespace Internal {
@@ -32,13 +33,36 @@ class PixmapCacheModel : public QmlProfiler::AbstractTimelineModel
{ {
Q_OBJECT Q_OBJECT
public: public:
enum CacheState {
Uncached, // After loading started (or some other proof of existence) or after uncaching
ToBeCached, // After determining the pixmap is to be cached but before knowing its size
Cached, // After caching a pixmap or determining the size of a ToBeCached pixmap
Uncacheable, // If loading failed without ToBeCached or after a corrupt pixmap has been uncached
Corrupt // If after ToBeCached we learn that loading failed
};
struct PixmapCacheEvent { enum LoadState {
int pixmapEventType; Initial,
int urlIndex; Loading,
int sizeIndex; Finished,
int rowNumberCollapsed; Error
qint64 cacheSize; };
struct PixmapState {
PixmapState(int width, int height, CacheState cache = Uncached) :
size(width, height), started(-1), loadState(Initial), cacheState(cache) {}
PixmapState(CacheState cache = Uncached) : started(-1), loadState(Initial), cacheState(cache) {}
QSize size;
int started;
LoadState loadState;
CacheState cacheState;
};
struct Pixmap {
Pixmap() {}
Pixmap(const QString &url) : url(url), sizes(1) {}
QString url;
QVector<PixmapState> sizes;
}; };
enum PixmapEventType { enum PixmapEventType {
@@ -52,6 +76,14 @@ public:
MaximumPixmapEventType MaximumPixmapEventType
}; };
struct PixmapCacheEvent {
PixmapEventType pixmapEventType;
int urlIndex;
int sizeIndex;
int rowNumberCollapsed;
qint64 cacheSize;
};
PixmapCacheModel(QObject *parent = 0); PixmapCacheModel(QObject *parent = 0);
quint64 features() const; quint64 features() const;
@@ -71,10 +103,17 @@ protected:
void clear(); void clear();
private: private:
static const int PixmapCacheCountHue = 240; void computeMaxCacheSize();
void resizeUnfinishedLoads();
void flattenLoads();
int updateCacheCount(int lastCacheSizeEvent, qint64 startTime, qint64 pixSize,
PixmapCacheEvent &newEvent, int typeId);
class PixmapCacheModelPrivate; QVector<PixmapCacheEvent> m_data;
Q_DECLARE_PRIVATE(PixmapCacheModel) QVector<Pixmap> m_pixmaps;
qint64 m_maxCacheSize;
static const int s_pixmapCacheCountHue = 240;
}; };
} // namespace Internal } // namespace Internal

View File

@@ -19,7 +19,6 @@
#include "scenegraphtimelinemodel.h" #include "scenegraphtimelinemodel.h"
#include "qmldebug/qmlprofilereventtypes.h" #include "qmldebug/qmlprofilereventtypes.h"
#include "qmlprofiler/qmlprofilermodelmanager.h" #include "qmlprofiler/qmlprofilermodelmanager.h"
#include "qmlprofiler/abstracttimelinemodel_p.h"
#include <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
@@ -66,64 +65,11 @@ enum SceneGraphCategoryType {
MaximumSceneGraphCategoryType MaximumSceneGraphCategoryType
}; };
enum SceneGraphStage { Q_STATIC_ASSERT(sizeof(StageLabels) ==
MinimumSceneGraphStage = 0, SceneGraphTimelineModel::MaximumSceneGraphStage * sizeof(const char *));
Polish = MinimumSceneGraphStage,
Wait,
GUIThreadSync,
Animations,
MaximumGUIThreadStage,
RenderThreadSync = MaximumGUIThreadStage,
Render,
Swap,
MaximumRenderThreadStage,
RenderPreprocess = MaximumRenderThreadStage,
RenderUpdate,
RenderBind,
RenderRender,
MaximumRenderStage,
Material = MaximumRenderStage,
MaximumMaterialStage,
GlyphRender = MaximumMaterialStage,
GlyphStore,
MaximumGlyphStage,
TextureBind = MaximumGlyphStage,
TextureConvert,
TextureSwizzle,
TextureUpload,
TextureMipmap,
TextureDeletion,
MaximumTextureStage,
MaximumSceneGraphStage = MaximumTextureStage
};
Q_STATIC_ASSERT(sizeof(StageLabels) == MaximumSceneGraphStage * sizeof(const char *));
class SceneGraphTimelineModel::SceneGraphTimelineModelPrivate :
public AbstractTimelineModel::AbstractTimelineModelPrivate
{
public:
void flattenLoads();
QVector<SceneGraphEvent> data;
qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage,
int glyphCount = -1);
static const char *threadLabel(SceneGraphStage stage);
private:
Q_DECLARE_PUBLIC(SceneGraphTimelineModel)
};
SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent) SceneGraphTimelineModel::SceneGraphTimelineModel(QObject *parent)
: AbstractTimelineModel(new SceneGraphTimelineModelPrivate, : AbstractTimelineModel(tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)),
tr(QmlProfilerModelManager::featureName(QmlDebug::ProfileSceneGraph)),
QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent) QmlDebug::SceneGraphFrame, QmlDebug::MaximumRangeType, parent)
{ {
} }
@@ -135,14 +81,12 @@ quint64 SceneGraphTimelineModel::features() const
int SceneGraphTimelineModel::row(int index) const int SceneGraphTimelineModel::row(int index) const
{ {
Q_D(const SceneGraphTimelineModel); return expanded() ? (m_data[index].stage + 1) : m_data[index].rowNumberCollapsed;
return expanded() ? (d->data[index].stage + 1) : d->data[index].rowNumberCollapsed;
} }
int SceneGraphTimelineModel::selectionId(int index) const int SceneGraphTimelineModel::selectionId(int index) const
{ {
Q_D(const SceneGraphTimelineModel); return m_data[index].stage;
return d->data[index].stage;
} }
QColor SceneGraphTimelineModel::color(int index) const QColor SceneGraphTimelineModel::color(int index) const
@@ -152,14 +96,13 @@ QColor SceneGraphTimelineModel::color(int index) const
QVariantList SceneGraphTimelineModel::labels() const QVariantList SceneGraphTimelineModel::labels() const
{ {
Q_D(const SceneGraphTimelineModel);
QVariantList result; QVariantList result;
if (d->expanded && !d->hidden && !isEmpty()) { if (expanded() && !hidden() && !isEmpty()) {
for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage; for (SceneGraphStage i = MinimumSceneGraphStage; i < MaximumSceneGraphStage;
i = static_cast<SceneGraphStage>(i + 1)) { i = static_cast<SceneGraphStage>(i + 1)) {
QVariantMap element; QVariantMap element;
element.insert(QLatin1String("displayName"), tr(d->threadLabel(i))); element.insert(QLatin1String("displayName"), tr(threadLabel(i)));
element.insert(QLatin1String("description"), tr(StageLabels[i])); element.insert(QLatin1String("description"), tr(StageLabels[i]));
element.insert(QLatin1String("id"), i); element.insert(QLatin1String("id"), i);
result << element; result << element;
@@ -171,12 +114,11 @@ QVariantList SceneGraphTimelineModel::labels() const
QVariantMap SceneGraphTimelineModel::details(int index) const QVariantMap SceneGraphTimelineModel::details(int index) const
{ {
Q_D(const SceneGraphTimelineModel);
QVariantMap result; QVariantMap result;
const SceneGraphEvent *ev = &d->data[index]; const SceneGraphEvent *ev = &m_data[index];
result.insert(QLatin1String("displayName"), result.insert(QLatin1String("displayName"),
tr(d->threadLabel(static_cast<SceneGraphStage>(ev->stage)))); tr(threadLabel(static_cast<SceneGraphStage>(ev->stage))));
result.insert(tr("Stage"), tr(StageLabels[ev->stage])); result.insert(tr("Stage"), tr(StageLabels[ev->stage]));
result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index))); result.insert(tr("Duration"), QmlProfilerBaseModel::formatTime(duration(index)));
if (ev->glyphCount >= 0) if (ev->glyphCount >= 0)
@@ -187,9 +129,8 @@ QVariantMap SceneGraphTimelineModel::details(int index) const
void SceneGraphTimelineModel::loadData() void SceneGraphTimelineModel::loadData()
{ {
Q_D(SceneGraphTimelineModel);
clear(); clear();
QmlProfilerDataModel *simpleModel = d->modelManager->qmlModel(); QmlProfilerDataModel *simpleModel = modelManager()->qmlModel();
if (simpleModel->isEmpty()) if (simpleModel->isEmpty())
return; return;
@@ -208,95 +149,91 @@ void SceneGraphTimelineModel::loadData()
// parts of the breakdown are usually very short. // parts of the breakdown are usually very short.
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3 - event.numericData4; event.numericData3 - event.numericData4;
startTime += d->insert(startTime, event.numericData1, event.typeIndex, startTime += insert(startTime, event.numericData1, event.typeIndex, RenderPreprocess);
RenderPreprocess); startTime += insert(startTime, event.numericData2, event.typeIndex, RenderUpdate);
startTime += d->insert(startTime, event.numericData2, event.typeIndex, RenderUpdate); startTime += insert(startTime, event.numericData3, event.typeIndex, RenderBind);
startTime += d->insert(startTime, event.numericData3, event.typeIndex, RenderBind); insert(startTime, event.numericData4, event.typeIndex, RenderRender);
d->insert(startTime, event.numericData4, event.typeIndex, RenderRender);
break; break;
} }
case QmlDebug::SceneGraphAdaptationLayerFrame: { case QmlDebug::SceneGraphAdaptationLayerFrame: {
qint64 startTime = event.startTime - event.numericData2 - event.numericData3; qint64 startTime = event.startTime - event.numericData2 - event.numericData3;
startTime += d->insert(startTime, event.numericData2, event.typeIndex, GlyphRender, startTime += insert(startTime, event.numericData2, event.typeIndex, GlyphRender,
event.numericData1); event.numericData1);
d->insert(startTime, event.numericData3, event.typeIndex, GlyphStore, insert(startTime, event.numericData3, event.typeIndex, GlyphStore, event.numericData1);
event.numericData1);
break; break;
} }
case QmlDebug::SceneGraphContextFrame: { case QmlDebug::SceneGraphContextFrame: {
d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
Material); Material);
break; break;
} }
case QmlDebug::SceneGraphRenderLoopFrame: { case QmlDebug::SceneGraphRenderLoopFrame: {
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3; event.numericData3;
startTime += d->insert(startTime, event.numericData1, event.typeIndex, startTime += insert(startTime, event.numericData1, event.typeIndex,
RenderThreadSync); RenderThreadSync);
startTime += d->insert(startTime, event.numericData2, event.typeIndex, startTime += insert(startTime, event.numericData2, event.typeIndex,
Render); Render);
d->insert(startTime, event.numericData3, event.typeIndex, Swap); insert(startTime, event.numericData3, event.typeIndex, Swap);
break; break;
} }
case QmlDebug::SceneGraphTexturePrepare: { case QmlDebug::SceneGraphTexturePrepare: {
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3 - event.numericData4 - event.numericData5; event.numericData3 - event.numericData4 - event.numericData5;
startTime += d->insert(startTime, event.numericData1, event.typeIndex, TextureBind); startTime += insert(startTime, event.numericData1, event.typeIndex, TextureBind);
startTime += d->insert(startTime, event.numericData2, event.typeIndex, TextureConvert); startTime += insert(startTime, event.numericData2, event.typeIndex, TextureConvert);
startTime += d->insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle); startTime += insert(startTime, event.numericData3, event.typeIndex, TextureSwizzle);
startTime += d->insert(startTime, event.numericData4, event.typeIndex, TextureUpload); startTime += insert(startTime, event.numericData4, event.typeIndex, TextureUpload);
d->insert(startTime, event.numericData5, event.typeIndex, TextureMipmap); insert(startTime, event.numericData5, event.typeIndex, TextureMipmap);
break; break;
} }
case QmlDebug::SceneGraphTextureDeletion: { case QmlDebug::SceneGraphTextureDeletion: {
d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
TextureDeletion); TextureDeletion);
break; break;
} }
case QmlDebug::SceneGraphPolishAndSync: { case QmlDebug::SceneGraphPolishAndSync: {
qint64 startTime = event.startTime - event.numericData1 - event.numericData2 - qint64 startTime = event.startTime - event.numericData1 - event.numericData2 -
event.numericData3 - event.numericData4; event.numericData3 - event.numericData4;
startTime += d->insert(startTime, event.numericData1, event.typeIndex, Polish); startTime += insert(startTime, event.numericData1, event.typeIndex, Polish);
startTime += d->insert(startTime, event.numericData2, event.typeIndex, Wait); startTime += insert(startTime, event.numericData2, event.typeIndex, Wait);
startTime += d->insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync); startTime += insert(startTime, event.numericData3, event.typeIndex, GUIThreadSync);
d->insert(startTime, event.numericData4, event.typeIndex, Animations); insert(startTime, event.numericData4, event.typeIndex, Animations);
break; break;
} }
case QmlDebug::SceneGraphWindowsAnimations: { case QmlDebug::SceneGraphWindowsAnimations: {
// GUI thread, separate animations stage // GUI thread, separate animations stage
d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
Animations); Animations);
break; break;
} }
case QmlDebug::SceneGraphPolishFrame: { case QmlDebug::SceneGraphPolishFrame: {
// GUI thread, separate polish stage // GUI thread, separate polish stage
d->insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex, insert(event.startTime - event.numericData1, event.numericData1, event.typeIndex,
Polish); Polish);
break; break;
} }
default: break; default: break;
} }
d->modelManager->modelProxyCountUpdated(d->modelId, count(), simpleModel->getEvents().count()); updateProgress(count(), simpleModel->getEvents().count());
} }
computeNesting(); computeNesting();
d->flattenLoads(); flattenLoads();
d->modelManager->modelProxyCountUpdated(d->modelId, 1, 1); updateProgress(1, 1);
} }
void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads() void SceneGraphTimelineModel::flattenLoads()
{ {
Q_Q(SceneGraphTimelineModel); int collapsedRowCount = 0;
collapsedRowCount = 0;
// computes "compressed row" // computes "compressed row"
QVector <qint64> eventEndTimes; QVector <qint64> eventEndTimes;
for (int i = 0; i < q->count(); i++) { for (int i = 0; i < count(); i++) {
SceneGraphEvent &event = data[i]; SceneGraphEvent &event = m_data[i];
const Range &start = ranges[i];
// Don't try to put render thread events in GUI row and vice versa. // Don't try to put render thread events in GUI row and vice versa.
// Rows below those are free for all. // Rows below those are free for all.
if (event.stage < MaximumGUIThreadStage) if (event.stage < MaximumGUIThreadStage)
@@ -307,12 +244,12 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads()
event.rowNumberCollapsed = SceneGraphRenderThreadDetails; event.rowNumberCollapsed = SceneGraphRenderThreadDetails;
while (eventEndTimes.count() > event.rowNumberCollapsed && while (eventEndTimes.count() > event.rowNumberCollapsed &&
eventEndTimes[event.rowNumberCollapsed] > start.start) eventEndTimes[event.rowNumberCollapsed] > startTime(i))
++event.rowNumberCollapsed; ++event.rowNumberCollapsed;
while (eventEndTimes.count() <= event.rowNumberCollapsed) while (eventEndTimes.count() <= event.rowNumberCollapsed)
eventEndTimes << 0; // increase stack length, proper value added below eventEndTimes << 0; // increase stack length, proper value added below
eventEndTimes[event.rowNumberCollapsed] = start.start + start.duration; eventEndTimes[event.rowNumberCollapsed] = endTime(i);
// readjust to account for category empty row // readjust to account for category empty row
event.rowNumberCollapsed++; event.rowNumberCollapsed++;
@@ -321,8 +258,8 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads()
} }
// Starting from 0, count is maxIndex+1 // Starting from 0, count is maxIndex+1
collapsedRowCount++; setCollapsedRowCount(collapsedRowCount + 1);
expandedRowCount = MaximumSceneGraphStage + 1; setExpandedRowCount(MaximumSceneGraphStage + 1);
} }
/*! /*!
@@ -330,19 +267,18 @@ void SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::flattenLoads()
* \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its * \a glyphCount (if it's a \c GlyphRender or \c GlyphStore event) into the scene graph model if its
* \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0. * \a duration is greater than 0. Returns \a duration in that case; otherwise returns 0.
*/ */
qint64 SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::insert(qint64 start, qint64 SceneGraphTimelineModel::insert(qint64 start, qint64 duration, int typeIndex,
qint64 duration, int typeIndex, SceneGraphStage stage, int glyphCount) SceneGraphStage stage, int glyphCount)
{ {
if (duration <= 0) if (duration <= 0)
return 0; return 0;
Q_Q(SceneGraphTimelineModel); m_data.insert(AbstractTimelineModel::insert(start, duration, typeIndex),
data.insert(q->insert(start, duration, typeIndex), SceneGraphEvent(stage, glyphCount)); SceneGraphEvent(stage, glyphCount));
return duration; return duration;
} }
const char *SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::threadLabel( const char *SceneGraphTimelineModel::threadLabel(SceneGraphStage stage)
SceneGraphStage stage)
{ {
if (stage < MaximumGUIThreadStage) if (stage < MaximumGUIThreadStage)
return ThreadLabels[SceneGraphGUIThread]; return ThreadLabels[SceneGraphGUIThread];
@@ -355,13 +291,11 @@ const char *SceneGraphTimelineModel::SceneGraphTimelineModelPrivate::threadLabel
void SceneGraphTimelineModel::clear() void SceneGraphTimelineModel::clear()
{ {
Q_D(SceneGraphTimelineModel); m_data.clear();
d->collapsedRowCount = 1;
d->data.clear();
AbstractTimelineModel::clear(); AbstractTimelineModel::clear();
} }
SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(int stage, int glyphCount) : SceneGraphTimelineModel::SceneGraphEvent::SceneGraphEvent(SceneGraphStage stage, int glyphCount) :
stage(stage), rowNumberCollapsed(-1), glyphCount(glyphCount) stage(stage), rowNumberCollapsed(-1), glyphCount(glyphCount)
{ {
} }

View File

@@ -33,10 +33,46 @@ class SceneGraphTimelineModel : public QmlProfiler::AbstractTimelineModel
{ {
Q_OBJECT Q_OBJECT
public: public:
enum SceneGraphStage {
MinimumSceneGraphStage = 0,
Polish = MinimumSceneGraphStage,
Wait,
GUIThreadSync,
Animations,
MaximumGUIThreadStage,
RenderThreadSync = MaximumGUIThreadStage,
Render,
Swap,
MaximumRenderThreadStage,
RenderPreprocess = MaximumRenderThreadStage,
RenderUpdate,
RenderBind,
RenderRender,
MaximumRenderStage,
Material = MaximumRenderStage,
MaximumMaterialStage,
GlyphRender = MaximumMaterialStage,
GlyphStore,
MaximumGlyphStage,
TextureBind = MaximumGlyphStage,
TextureConvert,
TextureSwizzle,
TextureUpload,
TextureMipmap,
TextureDeletion,
MaximumTextureStage,
MaximumSceneGraphStage = MaximumTextureStage
};
struct SceneGraphEvent { struct SceneGraphEvent {
SceneGraphEvent(int stage = -1, int glyphCount = -1); SceneGraphEvent(SceneGraphStage stage = MaximumSceneGraphStage, int glyphCount = -1);
int stage; SceneGraphStage stage;
int rowNumberCollapsed; int rowNumberCollapsed;
int glyphCount; // only used for one event type int glyphCount; // only used for one event type
}; };
@@ -57,8 +93,12 @@ protected:
void clear(); void clear();
private: private:
class SceneGraphTimelineModelPrivate; void flattenLoads();
Q_DECLARE_PRIVATE(SceneGraphTimelineModel) qint64 insert(qint64 start, qint64 duration, int typeIndex, SceneGraphStage stage,
int glyphCount = -1);
static const char *threadLabel(SceneGraphStage stage);
QVector<SceneGraphEvent> m_data;
}; };
} // namespace Internal } // namespace Internal