Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qwaylandpresentationtime.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 LG Electronics Inc.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
6
7#include <time.h>
8#include <QQuickWindow>
9#include <QtWaylandCompositor/QWaylandView>
10#include <QtWaylandCompositor/QWaylandQuickItem>
11
13
69
77
82{
84
85 if (isInitialized()) {
86 qWarning() << "QWaylandPresentationTime is already initialized";
87 return;
88 }
89
91 if (compositor == nullptr) {
92 qWarning() << "Failed to find QWaylandCompositor when initializing QWaylandPresentationTime";
93 return;
94 }
95
97
98 d->init(compositor->display(), /* version */ 1);
99}
100
102{
103 return qobject_cast<QWaylandCompositor *>(extensionContainer());
104}
105
122{
123 if (!window)
124 return;
125
126 quint32 refresh_nsec = window->screen()->refreshRate() != 0 ? 1000000000 / window->screen()->refreshRate() : 0;
127
128 emit presented(sequence, tv_sec, tv_nsec, refresh_nsec);
129}
130
134const struct wl_interface *QWaylandPresentationTime::interface()
135{
136 return QWaylandPresentationTimePrivate::interface();
137}
138
143{
144 return QWaylandPresentationTimePrivate::interfaceName();
145}
146
147PresentationFeedback::PresentationFeedback(QWaylandPresentationTime *pTime, QWaylandSurface *surface, struct ::wl_client *client, uint32_t id, int version)
148 : wp_presentation_feedback(client, id, version)
149 , m_presentationTime(pTime)
150{
152}
153
155{
156 if (!qwls) {
157 discard();
158 return;
159 }
160
161 m_surface = qwls;
162
163 connect(qwls, &QWaylandSurface::damaged, this, &PresentationFeedback::onSurfaceCommit);
164 connect(qwls, &QWaylandSurface::destroyed, this, &PresentationFeedback::discard);
165
166 QWaylandView *view = qwls ? qwls->primaryView() : nullptr;
167 //The surface has not committed yet.
168 if (!view) {
169 connect(qwls, &QWaylandSurface::hasContentChanged, this, &PresentationFeedback::onSurfaceMapped);
170 return;
171 }
172
173 maybeConnectToWindow(view);
174}
175
176void PresentationFeedback::onSurfaceCommit()
177{
178 // There is a new commit before sync so that discard this feedback.
179 if (m_committed) {
180 discard();
181 return;
182 }
183 m_committed = true;
184}
185
186void PresentationFeedback::onSurfaceMapped()
187{
189 if (!view) {
190 qWarning() << "The mapped surface has no view";
191 discard();
192 return;
193 }
194
195 maybeConnectToWindow(view);
196}
197
198void PresentationFeedback::maybeConnectToWindow(QWaylandView *view)
199{
200 QWaylandQuickItem *item = view ? qobject_cast<QWaylandQuickItem *>(view->renderObject()) : nullptr;
201 if (!item) {
202 qWarning() << "QWaylandPresentationTime only works with QtQuick compositors" << view;
203 discard();
204 return;
205 }
206
207 connect(item, &QQuickItem::windowChanged, this, &PresentationFeedback::onWindowChanged);
208 // wait for having window
209 if (!item->window()) {
210 return;
211 }
212
213 connectToWindow(item->window());
214}
215
216void PresentationFeedback::onWindowChanged()
217{
218 QWaylandQuickItem *item = qobject_cast<QWaylandQuickItem *>(sender());
219 QQuickWindow *window = item ? item->window() : nullptr;
220
221 if (!window) {
222 qWarning() << "QWaylandPresentationTime only works with QtQuick compositors" << item;
223 discard();
224 /* Actually, the commit is not discarded yet. If the related item has new window,
225 the commit can be presented on screen. So we can choose not to discard the feedback
226 until item has new window or the surface is destroyed. */
227 return;
228 }
229
230 // Check if the connected window is changed
233
234 connectToWindow(window);
235}
236
237void PresentationFeedback::connectToWindow(QQuickWindow *window)
238{
239 if (!window) {
240 discard();
241 return;
242 }
243
245
246 connect(window, &QQuickWindow::beforeSynchronizing, this, &PresentationFeedback::onSync);
247 connect(window, &QQuickWindow::afterFrameEnd, this, &PresentationFeedback::onSwapped);
248}
249
250void PresentationFeedback::onSync()
251{
252 QQuickWindow *window = qobject_cast<QQuickWindow *>(sender());
253
254 if (m_committed) {
255 disconnect(m_surface, &QWaylandSurface::damaged, this, &PresentationFeedback::onSurfaceCommit);
256 disconnect(window, &QQuickWindow::beforeSynchronizing, this, &PresentationFeedback::onSync);
257 m_sync = true;
258 }
259}
260
261void PresentationFeedback::onSwapped()
262{
263 QQuickWindow *window = qobject_cast<QQuickWindow *>(sender());
264
265 if (m_sync) {
266 disconnect(window, &QQuickWindow::afterFrameEnd, this, &PresentationFeedback::onSwapped);
267 connect(m_presentationTime, &QWaylandPresentationTime::presented, this, &PresentationFeedback::sendPresented);
268 }
269}
270
271void PresentationFeedback::discard()
272{
273 send_discarded();
274 destroy();
275}
276
278{
279 QWaylandCompositor *compositor = presentationTime()->compositor();
280 if (!compositor) {
281 qWarning() << "No compositor container to send sync_output";
282 return;
283 }
284
286 QWaylandOutput *output = view ? view->output() : nullptr;
287 struct ::wl_resource *r = output ? output->resourceForClient(QWaylandClient::fromWlClient(compositor, resource()->client())) : nullptr;
288
289 if (r)
290 send_sync_output(r);
291}
292
293void PresentationFeedback::sendPresented(quint64 sequence, quint64 tv_sec, quint32 tv_nsec, quint32 refresh_nsec)
294{
296
297 send_presented(tv_sec >> 32, tv_sec, tv_nsec, refresh_nsec, sequence >> 32, sequence,
298 QtWaylandServer::wp_presentation_feedback::kind_vsync
299 | QtWaylandServer::wp_presentation_feedback::kind_hw_clock
300 | QtWaylandServer::wp_presentation_feedback::kind_hw_completion);
301
302 destroy();
303}
304
306{
307 wl_resource_destroy(resource()->handle);
308}
309
311{
312 Q_UNUSED(resource);
313 delete this;
314}
315
319
321{
322 send_clock_id(resource->handle, CLOCK_MONOTONIC);
323}
324
325void QWaylandPresentationTimePrivate::wp_presentation_feedback(Resource *resource, struct ::wl_resource *surface, uint32_t callback)
326{
328
330 if (!qwls)
331 return;
332
333 new PresentationFeedback(q, qwls, resource->client(), callback, /* version */ 1);
334}
335
337
338#include "moc_qwaylandpresentationtime_p_p.cpp"
339
340#include "moc_qwaylandpresentationtime_p.cpp"
void setSurface(QWaylandSurface *)
void wp_presentation_feedback_destroy_resource(Resource *resource) override
QWaylandPresentationTime * m_presentationTime
PresentationFeedback(QWaylandPresentationTime *, QWaylandSurface *, struct ::wl_client *, uint32_t, int)
\inmodule QtCore
Definition qbytearray.h:57
QGraphicsWidget * window() const
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition qobject.cpp:2658
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3236
void destroyed(QObject *=nullptr)
This signal is emitted immediately before the object obj is destroyed, after any instances of QPointe...
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void beforeSynchronizing()
This signal is emitted before the scene graph is synchronized with the QML state.
static QWaylandClient * fromWlClient(QWaylandCompositor *compositor, wl_client *wlClient)
Returns the QWaylandClient corresponding to the Wayland client wlClient and compositor.
virtual void initialize()
Initializes the QWaylandCompositorExtension.
\qmltype WaylandCompositor \instantiates QWaylandCompositor \inqmlmodule QtWayland....
\qmltype WaylandOutput \instantiates QWaylandOutput \inqmlmodule QtWayland.Compositor
void wp_presentation_bind_resource(Resource *resource) override
void wp_presentation_feedback(Resource *resource, struct ::wl_resource *surface, uint32_t callback) override
\qmltype PresentationTime \instantiates QWaylandPresentationTime \inqmlmodule QtWayland....
QWaylandPresentationTime()
Constructs an empty QWaylandPresentationTime object.
void initialize() override
Initializes the extension.
static const struct wl_interface * interface()
Returns the Wayland interface for the QWaylandPresentationTime.
QWaylandCompositor * compositor() const
Q_INVOKABLE void sendFeedback(QQuickWindow *window, quint64 sequence, quint64 tv_sec, quint32 tv_nsec)
\qmlmethod void PresentationTime::sendFeedback(Window window, int sequence, int sec,...
void presented(quint64 sequence, quint64 tv_sec, quint32 tv_nsec, quint32 refresh_nsec)
\qmltype WaylandQuickItem \instantiates QWaylandQuickItem \inqmlmodule QtWayland.Compositor
\qmltype WaylandSurface \instantiates QWaylandSurface \inqmlmodule QtWayland.Compositor
void hasContentChanged()
static QWaylandSurface * fromResource(::wl_resource *resource)
Returns the QWaylandSurface corresponding to the Wayland resource resource.
QWaylandView * primaryView() const
Updates the surface with the compositor's retained clipboard selection.
void damaged(const QRegion &rect)
\qmltype WaylandView \instantiates QWaylandView \inqmlmodule QtWayland.Compositor
Combined button and popup list for selecting options.
#define qWarning
Definition qlogging.h:166
static QOpenGLCompositor * compositor
GLuint64 GLenum void * handle
GLboolean r
[2]
GLenum GLuint id
[7]
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
#define emit
#define Q_UNUSED(x)
unsigned int quint32
Definition qtypes.h:50
unsigned long long quint64
Definition qtypes.h:61
QT_BEGIN_NAMESPACE typedef uchar * output
QObject::connect nullptr
myObject disconnect()
[26]
QGraphicsItem * item
aWidget window() -> setWindowTitle("New Window Title")
[2]
QQuickView * view
[0]