Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandview.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
4#include "qwaylandview.h"
7#include <QtWaylandCompositor/QWaylandSeat>
8#include <QtWaylandCompositor/QWaylandCompositor>
9
10#include <QtWaylandCompositor/private/qwaylandsurface_p.h>
11#include <QtWaylandCompositor/private/qwaylandoutput_p.h>
12
13#include <QtCore/QMutex>
14#include <QtCore/qpointer.h>
15
17
18void QWaylandViewPrivate::markSurfaceAsDestroyed(QWaylandSurface *surface)
19{
20 Q_Q(QWaylandView);
21 Q_ASSERT(surface == this->surface);
22
23 setSurface(nullptr);
24 QPointer<QWaylandView> deleteGuard(q);
25 emit q->surfaceDestroyed();
26 if (!deleteGuard.isNull())
28}
29
30/*!
31 * \qmltype WaylandView
32 * \nativetype QWaylandView
33 * \inqmlmodule QtWayland.Compositor
34 * \since 5.8
35 * \brief Represents a view of a surface on an output.
36 *
37 * The WaylandView corresponds to the presentation of a surface on a specific
38 * output, managing the buffers that contain the contents to be rendered.
39 * You can have several views into the same surface.
40 */
41
42/*!
43 * \class QWaylandView
44 * \inmodule QtWaylandCompositor
45 * \since 5.8
46 * \brief The QWaylandView class represents a view of a surface on an output.
47 *
48 * The QWaylandView corresponds to the presentation of a surface on a specific
49 * output, managing the buffers that contain the contents to be rendered.
50 * You can have several views into the same surface.
51 */
52
53/*!
54 * Constructs a QWaylandView with the given \a renderObject and \a parent.
55 */
56QWaylandView::QWaylandView(QObject *renderObject, QObject *parent)
57 : QObject(*new QWaylandViewPrivate(),parent)
58{
59 d_func()->renderObject = renderObject;
60}
61
62/*!
63 * Destroys the QWaylandView.
64 */
65QWaylandView::~QWaylandView()
66{
67 Q_D(QWaylandView);
68 if (d->surface) {
69 if (d->output)
70 QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface);
71
72 QWaylandSurfacePrivate::get(d->surface)->derefView(this);
73 }
74
75}
76
77/*!
78 * \property QWaylandView::renderObject
79 * \internal
80 * Didn't we decide to remove this property?
81 */
82QObject *QWaylandView::renderObject() const
83{
84 Q_D(const QWaylandView);
85 return d->renderObject;
86}
87
88/*!
89 * \qmlproperty WaylandSurface QtWayland.Compositor::WaylandView::surface
90 *
91 * This property holds the surface viewed by this WaylandView.
92 */
93
94/*!
95 * \property QWaylandView::surface
96 *
97 * This property holds the surface viewed by this QWaylandView.
98 */
99QWaylandSurface *QWaylandView::surface() const
100{
101 Q_D(const QWaylandView);
102 return d->surface;
103}
104
105
106void QWaylandViewPrivate::setSurface(QWaylandSurface *newSurface)
107{
108 Q_Q(QWaylandView);
109 if (surface) {
110 QWaylandSurfacePrivate::get(surface)->derefView(q);
111 if (output)
112 QWaylandOutputPrivate::get(output)->removeView(q, surface);
113 }
114
115 surface = newSurface;
116
117 nextBuffer = QWaylandBufferRef();
118 nextBufferCommitted = false;
119 nextDamage = QRegion();
120 forceAdvanceSucceed = false;
121
122 if (surface) {
123 QWaylandSurfacePrivate::get(surface)->refView(q);
124 if (output)
125 QWaylandOutputPrivate::get(output)->addView(q, surface);
126 }
127}
128
130{
131 if (!bufferLocked) {
132 currentBuffer = QWaylandBufferRef();
133 currentDamage = QRegion();
134 }
135}
136
137void QWaylandView::setSurface(QWaylandSurface *newSurface)
138{
139 Q_D(QWaylandView);
140 if (d->surface == newSurface)
141 return;
142
143 d->setSurface(newSurface);
144 d->clearFrontBuffer();
145 emit surfaceChanged();
146}
147
148/*!
149 * \qmlproperty WaylandOutput QtWayland.Compositor::WaylandView::output
150 *
151 * This property holds the output on which this view displays its surface.
152 */
153
154/*!
155 * \property QWaylandView::output
156 *
157 * This property holds the output on which this view displays its surface.
158 */
159QWaylandOutput *QWaylandView::output() const
160{
161 Q_D(const QWaylandView);
162 return d->output;
163}
164
165void QWaylandView::setOutput(QWaylandOutput *newOutput)
166{
167 Q_D(QWaylandView);
168 if (d->output == newOutput)
169 return;
170
171 if (d->output && d->surface)
172 QWaylandOutputPrivate::get(d->output)->removeView(this, d->surface);
173
174 d->output = newOutput;
175
176 if (d->output && d->surface)
177 QWaylandOutputPrivate::get(d->output)->addView(this, d->surface);
178
179 emit outputChanged();
180}
181
182/*!
183 * This function is called when a new \a buffer is committed to this view's surface.
184 * \a damage contains the region that is different from the current buffer, i.e. the
185 * region that needs to be updated.
186 * The new \a buffer will become current on the next call to advance().
187 *
188 * Subclasses that reimplement this function \e must call the base implementation.
189 */
190void QWaylandView::bufferCommitted(const QWaylandBufferRef &buffer, const QRegion &damage)
191{
192 Q_D(QWaylandView);
193 QMutexLocker locker(&d->bufferMutex);
194 d->nextBuffer = buffer;
195 d->nextDamage = damage;
196 d->nextBufferCommitted = true;
197}
198
199/*!
200 * Updates the current buffer and damage region to the latest version committed by the client.
201 * Returns true if new content was committed since the previous call to advance().
202 * Otherwise returns false.
203 *
204 * \sa currentBuffer(), currentDamage()
205 */
206bool QWaylandView::advance()
207{
208 Q_D(QWaylandView);
209
210 if (!d->nextBufferCommitted && !d->forceAdvanceSucceed)
211 return false;
212
213 if (d->bufferLocked)
214 return false;
215
216 if (d->surface && d->surface->primaryView() == this) {
217 const auto views = d->surface->views();
218 for (QWaylandView *view : views) {
219 if (view != this && view->allowDiscardFrontBuffer() && view->d_func()->currentBuffer == d->currentBuffer)
220 view->discardCurrentBuffer();
221 }
222 }
223
224 QMutexLocker locker(&d->bufferMutex);
225 d->forceAdvanceSucceed = false;
226 d->nextBufferCommitted = false;
227 d->currentBuffer = std::exchange(d->nextBuffer, {});
228 d->currentDamage = std::exchange(d->nextDamage, {});
229 return true;
230}
231
232/*!
233 * Force the view to discard its current buffer, to allow it to be reused on the client side.
234 */
235void QWaylandView::discardCurrentBuffer()
236{
237 Q_D(QWaylandView);
238 QMutexLocker locker(&d->bufferMutex);
239 d->currentBuffer = QWaylandBufferRef();
240 d->forceAdvanceSucceed = true;
241}
242
243/*!
244 * Returns a reference to this view's current buffer.
245 */
246QWaylandBufferRef QWaylandView::currentBuffer()
247{
248 Q_D(QWaylandView);
249 QMutexLocker locker(&d->bufferMutex);
250 return d->currentBuffer;
251}
252
253/*!
254 * Returns the current damage region of this view.
255 */
256QRegion QWaylandView::currentDamage()
257{
258 Q_D(QWaylandView);
259 QMutexLocker locker(&d->bufferMutex);
260 return d->currentDamage;
261}
262
263/*!
264 * \qmlproperty bool QtWayland.Compositor::WaylandView::bufferLocked
265 *
266 * This property holds whether the view's buffer is currently locked. When
267 * the buffer is locked, advance() will not advance to the next buffer and
268 * returns \c false.
269 *
270 * The default is \c false.
271 */
272
273/*!
274 * \property QWaylandView::bufferLocked
275 *
276 * This property holds whether the view's buffer is currently locked. When
277 * the buffer is locked, advance() will not advance to the next buffer
278 * and returns \c false.
279 *
280 * The default is \c false.
281 */
282bool QWaylandView::isBufferLocked() const
283{
284 Q_D(const QWaylandView);
285 return d->bufferLocked;
286}
287
288void QWaylandView::setBufferLocked(bool locked)
289{
290 Q_D(QWaylandView);
291 if (d->bufferLocked == locked)
292 return;
293 d->bufferLocked = locked;
294 emit bufferLockedChanged();
295
296 if (d->surface == nullptr && !d->bufferLocked)
297 d->clearFrontBuffer();
298}
299/*!
300 * \qmlproperty bool QtWayland.Compositor::WaylandView::allowDiscardFrontBuffer
301 *
302 * By default, the view locks the current buffer until advance() is called. Set this property
303 * to true to allow Qt to release the buffer when the primary view is no longer using it.
304 *
305 * This can be used to avoid the situation where a secondary view that updates on a lower
306 * frequency will throttle the frame rate of the client application.
307 */
308
309/*!
310 * \property QWaylandView::allowDiscardFrontBuffer
311 *
312 * By default, the view locks the current buffer until advance() is called. Set this property
313 * to \c true to allow Qt to release the buffer when the primary view is no longer using it.
314 *
315 * This can be used to avoid the situation where a secondary view that updates on a lower
316 * frequency will throttle the frame rate of the client application.
317 */
318bool QWaylandView::allowDiscardFrontBuffer() const
319{
320 Q_D(const QWaylandView);
321 return d->allowDiscardFrontBuffer;
322}
323
324void QWaylandView::setAllowDiscardFrontBuffer(bool discard)
325{
326 Q_D(QWaylandView);
327 if (d->allowDiscardFrontBuffer == discard)
328 return;
329 d->allowDiscardFrontBuffer = discard;
330 emit allowDiscardFrontBufferChanged();
331}
332
333/*!
334 * Makes this QWaylandView the primary view for the surface.
335 *
336 * It has no effect if this QWaylandView is not holding any QWaylandSurface
337 *
338 * \sa QWaylandSurface::primaryView
339 */
340void QWaylandView::setPrimary()
341{
342 Q_D(QWaylandView);
343 if (d->surface)
344 d->surface->setPrimaryView(this);
345 else
346 qWarning("Calling setPrimary() on a QWaylandView without a surface has no effect.");
347}
348
349/*!
350 * Returns true if this QWaylandView is the primary view for the QWaylandSurface
351 *
352 * \sa QWaylandSurface::primaryView
353 */
354bool QWaylandView::isPrimary() const
355{
356 Q_D(const QWaylandView);
357 return d->surface && d->surface->primaryView() == this;
358}
359
360/*!
361 * Returns the Wayland surface resource for this QWaylandView.
362 */
363struct wl_resource *QWaylandView::surfaceResource() const
364{
365 Q_D(const QWaylandView);
366 if (!d->surface)
367 return nullptr;
368 return d->surface->resource();
369}
370
371QT_END_NAMESPACE
372
373#include "moc_qwaylandview.cpp"
void setSurface(QWaylandSurface *newSurface)
QWaylandSurface * surface
Combined button and popup list for selecting options.