1// Copyright (C) 2016 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 "qquickprofileradapter.h"
5
6#include <QCoreApplication>
7#include <private/qqmldebugconnector_p.h>
8#include <private/qversionedpacket_p.h>
9#include <private/qqmldebugserviceinterfaces_p.h>
10#include <private/qquickprofiler_p.h>
11
12QT_BEGIN_NAMESPACE
13
14using QQmlDebugPacket = QVersionedPacket<QQmlDebugConnector>;
15
16QQuickProfilerAdapter::QQuickProfilerAdapter(QObject *parent) :
17 QQmlAbstractProfilerAdapter(parent), next(0)
18{
19 QQuickProfiler::initialize(parent: this);
20
21 // We can always do DirectConnection here as all methods are protected by mutexes
22 connect(sender: this, signal: &QQmlAbstractProfilerAdapter::profilingEnabled,
23 context: QQuickProfiler::s_instance, slot: &QQuickProfiler::startProfilingImpl, type: Qt::DirectConnection);
24 connect(sender: this, signal: &QQmlAbstractProfilerAdapter::profilingEnabledWhileWaiting,
25 context: QQuickProfiler::s_instance, slot: &QQuickProfiler::startProfilingImpl, type: Qt::DirectConnection);
26 connect(sender: this, signal: &QQmlAbstractProfilerAdapter::referenceTimeKnown,
27 context: QQuickProfiler::s_instance, slot: &QQuickProfiler::setTimer, type: Qt::DirectConnection);
28 connect(sender: this, signal: &QQmlAbstractProfilerAdapter::profilingDisabled,
29 context: QQuickProfiler::s_instance, slot: &QQuickProfiler::stopProfilingImpl, type: Qt::DirectConnection);
30 connect(sender: this, signal: &QQmlAbstractProfilerAdapter::profilingDisabledWhileWaiting,
31 context: QQuickProfiler::s_instance, slot: &QQuickProfiler::stopProfilingImpl, type: Qt::DirectConnection);
32 connect(sender: this, signal: &QQmlAbstractProfilerAdapter::dataRequested,
33 context: QQuickProfiler::s_instance, slot: &QQuickProfiler::reportDataImpl, type: Qt::DirectConnection);
34 connect(sender: QQuickProfiler::s_instance, signal: &QQuickProfiler::dataReady,
35 context: this, slot: &QQuickProfilerAdapter::receiveData, type: Qt::DirectConnection);
36}
37
38QQuickProfilerAdapter::~QQuickProfilerAdapter()
39{
40 if (service)
41 service->removeGlobalProfiler(profiler: this);
42}
43
44// convert to QByteArrays that can be sent to the debug client
45static void qQuickProfilerDataToByteArrays(const QQuickProfilerData &data,
46 QList<QByteArray> &messages)
47{
48 QQmlDebugPacket ds;
49 Q_ASSERT_X(((data.messageType | data.detailType) & (1 << 31)) == 0, Q_FUNC_INFO,
50 "You can use at most 31 message types and 31 detail types.");
51 for (uint decodedMessageType = 0; (data.messageType >> decodedMessageType) != 0;
52 ++decodedMessageType) {
53 if ((data.messageType & (1 << decodedMessageType)) == 0)
54 continue;
55
56 for (uint decodedDetailType = 0; (data.detailType >> decodedDetailType) != 0;
57 ++decodedDetailType) {
58 if ((data.detailType & (1 << decodedDetailType)) == 0)
59 continue;
60
61 ds << data.time << decodedMessageType << decodedDetailType;
62
63 switch (decodedMessageType) {
64 case QQuickProfiler::Event:
65 switch (decodedDetailType) {
66 case QQuickProfiler::AnimationFrame:
67 ds << data.framerate << data.count << data.threadId;
68 break;
69 case QQuickProfiler::Key:
70 case QQuickProfiler::Mouse:
71 ds << data.inputType << data.inputA << data.inputB;
72 break;
73 }
74 break;
75 case QQuickProfiler::PixmapCacheEvent:
76 ds << data.detailUrl.toString();
77 switch (decodedDetailType) {
78 case QQuickProfiler::PixmapSizeKnown: ds << data.x << data.y; break;
79 case QQuickProfiler::PixmapReferenceCountChanged: ds << data.count; break;
80 case QQuickProfiler::PixmapCacheCountChanged: ds << data.count; break;
81 default: break;
82 }
83 break;
84 case QQuickProfiler::SceneGraphFrame:
85 switch (decodedDetailType) {
86 // RendererFrame: preprocessTime, updateTime, bindingTime, renderTime
87 case QQuickProfiler::SceneGraphRendererFrame: ds << data.subtime_1 << data.subtime_2 << data.subtime_3 << data.subtime_4; break;
88 // AdaptationLayerFrame: glyphCount (which is an integer), glyphRenderTime, glyphStoreTime
89 case QQuickProfiler::SceneGraphAdaptationLayerFrame: ds << data.subtime_3 << data.subtime_1 << data.subtime_2; break;
90 // ContextFrame: compiling material time
91 case QQuickProfiler::SceneGraphContextFrame: ds << data.subtime_1; break;
92 // RenderLoop: syncTime, renderTime, swapTime
93 case QQuickProfiler::SceneGraphRenderLoopFrame: ds << data.subtime_1 << data.subtime_2 << data.subtime_3; break;
94 // TexturePrepare: bind, convert, swizzle, upload, mipmap
95 case QQuickProfiler::SceneGraphTexturePrepare: ds << data.subtime_1 << data.subtime_2 << data.subtime_3 << data.subtime_4 << data.subtime_5; break;
96 // TextureDeletion: deletionTime
97 case QQuickProfiler::SceneGraphTextureDeletion: ds << data.subtime_1; break;
98 // PolishAndSync: polishTime, waitTime, syncTime, animationsTime,
99 case QQuickProfiler::SceneGraphPolishAndSync: ds << data.subtime_1 << data.subtime_2 << data.subtime_3 << data.subtime_4; break;
100 // WindowsRenderLoop: GL time, make current time, SceneGraph time
101 case QQuickProfiler::SceneGraphWindowsRenderShow: ds << data.subtime_1 << data.subtime_2 << data.subtime_3; break;
102 // WindowsAnimations: update time
103 case QQuickProfiler::SceneGraphWindowsAnimations: ds << data.subtime_1; break;
104 // non-threaded rendering: polish time
105 case QQuickProfiler::SceneGraphPolishFrame: ds << data.subtime_1; break;
106 default:break;
107 }
108 break;
109 default:
110 Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid message type.");
111 break;
112 }
113 messages.append(t: ds.squeezedData());
114 ds.clear();
115 }
116 }
117}
118
119qint64 QQuickProfilerAdapter::sendMessages(qint64 until, QList<QByteArray> &messages)
120{
121 while (next < m_data.size()) {
122 if (m_data[next].time <= until && messages.size() <= s_numMessagesPerBatch)
123 qQuickProfilerDataToByteArrays(data: m_data[next++], messages);
124 else
125 return m_data[next].time;
126 }
127 m_data.clear();
128 next = 0;
129 return -1;
130}
131
132void QQuickProfilerAdapter::receiveData(const QVector<QQuickProfilerData> &new_data)
133{
134 if (m_data.isEmpty())
135 m_data = new_data;
136 else
137 m_data.append(l: new_data);
138 service->dataReady(profiler: this);
139}
140
141QT_END_NAMESPACE
142
143#include "moc_qquickprofileradapter.cpp"
144

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_quickprofiler/qquickprofileradapter.cpp