1 | // Copyright (C) 2021 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
3 | |
4 | #include "qquick3dprofiler_p.h" |
5 | |
6 | #include <QtQml/qqmlfile.h> |
7 | |
8 | #include <QtCore/qcoreapplication.h> |
9 | #include <QtCore/qthread.h> |
10 | |
11 | QT_BEGIN_NAMESPACE |
12 | |
13 | #if QT_CONFIG(qml_debug) |
14 | |
15 | // Enable to debug profiling without client app. |
16 | //#define PROFILE_WITHOUT_CLIENT |
17 | |
18 | // instance will be set, unset in constructor. Allows static methods to be inlined. |
19 | QQuick3DProfiler *QQuick3DProfiler::s_instance = nullptr; |
20 | #ifdef PROFILE_WITHOUT_CLIENT |
21 | quint64 QQuick3DProfiler::featuresEnabled = 0xffffffff; |
22 | #else |
23 | quint64 QQuick3DProfiler::featuresEnabled = 0; |
24 | #endif |
25 | QHash<QByteArray, int> QQuick3DProfiler::s_eventData = {}; |
26 | QHash<int, QByteArray> QQuick3DProfiler::s_eventDataRev = {}; |
27 | QMutex QQuick3DProfiler::s_eventDataMutex; |
28 | |
29 | QQuick3DProfilerData::QQuick3DProfilerData(qint64 time, int messageType, int detailType, qint64 d1, qint64 d2, const QList<int> &ids) |
30 | : QQuick3DProfilerData(time, messageType, detailType, d1, d2) |
31 | { |
32 | static int ID_MARKER = 0xed000000; |
33 | int size = qMin(a: ids.size(), b: s_numSupportedIds); |
34 | for (int i = 0; i < size; i++) |
35 | this->ids[i] = ids[i] | ID_MARKER; |
36 | } |
37 | |
38 | int QQuick3DProfiler::registerObject(const QObject *object) |
39 | { |
40 | QMutexLocker lock(&s_eventDataMutex); |
41 | |
42 | #ifdef PROFILE_WITHOUT_CLIENT |
43 | if (!s_instance) |
44 | s_instance = new QQuick3DProfiler(nullptr); |
45 | #else |
46 | if (!s_instance) |
47 | return 0; |
48 | #endif |
49 | QQmlData *qmlData = QQmlData::get(object); |
50 | QByteArray typeAndLocation; |
51 | int id = 0; |
52 | if (qmlData) { |
53 | QQmlType qmlType = QQmlMetaType::qmlType(object->metaObject()); |
54 | QString fileName = qmlData->compilationUnit->fileName(); |
55 | typeAndLocation = (qmlType.qmlTypeName() + QLatin1Char(' ') + fileName + QLatin1Char(':') + QString::number(qmlData->lineNumber)).toUtf8(); |
56 | if (!s_eventData.contains(key: typeAndLocation)) { |
57 | id = s_eventData.size() + 1; |
58 | s_eventData.insert(key: typeAndLocation, value: id); |
59 | s_eventDataRev.insert(key: id, value: typeAndLocation); |
60 | s_instance->processMessage(message: QQuick3DProfilerData(s_instance->timestamp(), Quick3DFrame, Quick3DEventData, id, 0)); |
61 | } else { |
62 | id = s_eventData.value(key: typeAndLocation); |
63 | } |
64 | } |
65 | return id; |
66 | } |
67 | |
68 | int QQuick3DProfiler::registerString(const QByteArray &string) |
69 | { |
70 | QMutexLocker lock(&s_eventDataMutex); |
71 | #ifdef PROFILE_WITHOUT_CLIENT |
72 | if (!s_instance) |
73 | s_instance = new QQuick3DProfiler(nullptr); |
74 | #else |
75 | if (!s_instance) |
76 | return 0; |
77 | #endif |
78 | int id = 0; |
79 | if (!s_eventData.contains(key: string)) { |
80 | id = s_eventData.size() + 1; |
81 | s_eventData.insert(key: string, value: id); |
82 | s_eventDataRev.insert(key: id, value: string); |
83 | s_instance->processMessage(message: QQuick3DProfilerData(s_instance->timestamp(), Quick3DFrame, Quick3DEventData, id, 0)); |
84 | } else { |
85 | id = s_eventData.value(key: string); |
86 | } |
87 | return id; |
88 | } |
89 | |
90 | void QQuick3DProfiler::initialize(QObject *parent) |
91 | { |
92 | Q_ASSERT(s_instance == nullptr); |
93 | s_instance = new QQuick3DProfiler(parent); |
94 | } |
95 | |
96 | QQuick3DProfiler::QQuick3DProfiler(QObject *parent) |
97 | : QObject(parent) |
98 | { |
99 | m_timer.start(); |
100 | } |
101 | |
102 | QQuick3DProfiler::~QQuick3DProfiler() |
103 | { |
104 | QMutexLocker lock(&m_dataMutex); |
105 | featuresEnabled = 0; |
106 | s_instance = nullptr; |
107 | } |
108 | |
109 | void QQuick3DProfiler::startProfilingImpl(quint64 features) |
110 | { |
111 | QMutexLocker lock(&m_dataMutex); |
112 | featuresEnabled = features; |
113 | } |
114 | |
115 | void QQuick3DProfiler::stopProfilingImpl() |
116 | { |
117 | QMutexLocker lock(&m_dataMutex); |
118 | featuresEnabled = 0; |
119 | emit dataReady(data: m_data, eventData: s_eventDataRev); |
120 | m_data.clear(); |
121 | } |
122 | |
123 | void QQuick3DProfiler::reportDataImpl() |
124 | { |
125 | QMutexLocker lock(&m_dataMutex); |
126 | emit dataReady(data: m_data, eventData: s_eventDataRev); |
127 | m_data.clear(); |
128 | } |
129 | |
130 | void QQuick3DProfiler::setTimer(const QElapsedTimer &t) |
131 | { |
132 | QMutexLocker lock(&m_dataMutex); |
133 | m_timer = t; |
134 | } |
135 | |
136 | #endif |
137 | QT_END_NAMESPACE |
138 | |