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