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