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"
5#include "qwaylandview_p.h"
6#include "qwaylandsurface.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
16QT_BEGIN_NAMESPACE
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())
27 clearFrontBuffer();
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(output: d->output)->removeView(view: this, surface: d->surface);
71
72 QWaylandSurfacePrivate::get(surface: d->surface)->derefView(view: this);
73 }
74
75}
76
77/*!
78* \internal
79* Didn't we decide to remove this property?
80*/
81QObject *QWaylandView::renderObject() const
82{
83 Q_D(const QWaylandView);
84 return d->renderObject;
85}
86
87/*!
88 * \qmlproperty WaylandSurface QtWayland.Compositor::WaylandView::surface
89 *
90 * This property holds the surface viewed by this WaylandView.
91 */
92
93/*!
94 * \property QWaylandView::surface
95 *
96 * This property holds the surface viewed by this QWaylandView.
97 */
98QWaylandSurface *QWaylandView::surface() const
99{
100 Q_D(const QWaylandView);
101 return d->surface;
102}
103
104
105void QWaylandViewPrivate::setSurface(QWaylandSurface *newSurface)
106{
107 Q_Q(QWaylandView);
108 if (surface) {
109 QWaylandSurfacePrivate::get(surface)->derefView(view: q);
110 if (output)
111 QWaylandOutputPrivate::get(output)->removeView(view: q, surface);
112 }
113
114 surface = newSurface;
115
116 nextBuffer = QWaylandBufferRef();
117 nextBufferCommitted = false;
118 nextDamage = QRegion();
119
120 if (surface) {
121 QWaylandSurfacePrivate::get(surface)->refView(view: q);
122 if (output)
123 QWaylandOutputPrivate::get(output)->addView(view: q, surface);
124 }
125}
126
127void QWaylandViewPrivate::clearFrontBuffer()
128{
129 if (!bufferLocked) {
130 currentBuffer = QWaylandBufferRef();
131 currentDamage = QRegion();
132 }
133}
134
135void QWaylandView::setSurface(QWaylandSurface *newSurface)
136{
137 Q_D(QWaylandView);
138 if (d->surface == newSurface)
139 return;
140
141 d->setSurface(newSurface);
142 d->clearFrontBuffer();
143 emit surfaceChanged();
144}
145
146/*!
147 * \qmlproperty WaylandOutput QtWayland.Compositor::WaylandView::output
148 *
149 * This property holds the output on which this view displays its surface.
150 */
151
152/*!
153 * \property QWaylandView::output
154 *
155 * This property holds the output on which this view displays its surface.
156 */
157QWaylandOutput *QWaylandView::output() const
158{
159 Q_D(const QWaylandView);
160 return d->output;
161}
162
163void QWaylandView::setOutput(QWaylandOutput *newOutput)
164{
165 Q_D(QWaylandView);
166 if (d->output == newOutput)
167 return;
168
169 if (d->output && d->surface)
170 QWaylandOutputPrivate::get(output: d->output)->removeView(view: this, surface: d->surface);
171
172 d->output = newOutput;
173
174 if (d->output && d->surface)
175 QWaylandOutputPrivate::get(output: d->output)->addView(view: this, surface: d->surface);
176
177 emit outputChanged();
178}
179
180/*!
181 * This function is called when a new \a buffer is committed to this view's surface.
182 * \a damage contains the region that is different from the current buffer, i.e. the
183 * region that needs to be updated.
184 * The new \a buffer will become current on the next call to advance().
185 *
186 * Subclasses that reimplement this function \e must call the base implementation.
187 */
188void QWaylandView::bufferCommitted(const QWaylandBufferRef &buffer, const QRegion &damage)
189{
190 Q_D(QWaylandView);
191 QMutexLocker locker(&d->bufferMutex);
192 d->nextBuffer = buffer;
193 d->nextDamage = damage;
194 d->nextBufferCommitted = true;
195}
196
197/*!
198 * Updates the current buffer and damage region to the latest version committed by the client.
199 * Returns true if new content was committed since the previous call to advance().
200 * Otherwise returns false.
201 *
202 * \sa currentBuffer(), currentDamage()
203 */
204bool QWaylandView::advance()
205{
206 Q_D(QWaylandView);
207
208 if (!d->nextBufferCommitted && !d->forceAdvanceSucceed)
209 return false;
210
211 if (d->bufferLocked)
212 return false;
213
214 if (d->surface && d->surface->primaryView() == this) {
215 const auto views = d->surface->views();
216 for (QWaylandView *view : views) {
217 if (view != this && view->allowDiscardFrontBuffer() && view->d_func()->currentBuffer == d->currentBuffer)
218 view->discardCurrentBuffer();
219 }
220 }
221
222 QMutexLocker locker(&d->bufferMutex);
223 d->forceAdvanceSucceed = false;
224 d->nextBufferCommitted = false;
225 d->currentBuffer = d->nextBuffer;
226 d->currentDamage = d->nextDamage;
227 return true;
228}
229
230/*!
231 * Force the view to discard its current buffer, to allow it to be reused on the client side.
232 */
233void QWaylandView::discardCurrentBuffer()
234{
235 Q_D(QWaylandView);
236 QMutexLocker locker(&d->bufferMutex);
237 d->currentBuffer = QWaylandBufferRef();
238 d->forceAdvanceSucceed = true;
239}
240
241/*!
242 * Returns a reference to this view's current buffer.
243 */
244QWaylandBufferRef QWaylandView::currentBuffer()
245{
246 Q_D(QWaylandView);
247 QMutexLocker locker(&d->bufferMutex);
248 return d->currentBuffer;
249}
250
251/*!
252 * Returns the current damage region of this view.
253 */
254QRegion QWaylandView::currentDamage()
255{
256 Q_D(QWaylandView);
257 QMutexLocker locker(&d->bufferMutex);
258 return d->currentDamage;
259}
260
261/*!
262 * \qmlproperty bool QtWayland.Compositor::WaylandView::bufferLocked
263 *
264 * This property holds whether the view's buffer is currently locked. When
265 * the buffer is locked, advance() will not advance to the next buffer and
266 * returns \c false.
267 *
268 * The default is \c false.
269 */
270
271/*!
272 * \property QWaylandView::bufferLocked
273 *
274 * This property holds whether the view's buffer is currently locked. When
275 * the buffer is locked, advance() will not advance to the next buffer
276 * and returns \c false.
277 *
278 * The default is \c false.
279 */
280bool QWaylandView::isBufferLocked() const
281{
282 Q_D(const QWaylandView);
283 return d->bufferLocked;
284}
285
286void QWaylandView::setBufferLocked(bool locked)
287{
288 Q_D(QWaylandView);
289 if (d->bufferLocked == locked)
290 return;
291 d->bufferLocked = locked;
292 emit bufferLockedChanged();
293}
294/*!
295 * \qmlproperty bool QtWayland.Compositor::WaylandView::allowDiscardFrontBuffer
296 *
297 * By default, the view locks the current buffer until advance() is called. Set this property
298 * to true to allow Qt to release the buffer when the primary view is no longer using it.
299 *
300 * This can be used to avoid the situation where a secondary view that updates on a lower
301 * frequency will throttle the frame rate of the client application.
302 */
303
304/*!
305 * \property QWaylandView::allowDiscardFrontBuffer
306 *
307 * By default, the view locks the current buffer until advance() is called. Set this property
308 * to \c true to allow Qt to release the buffer when the primary view is no longer using it.
309 *
310 * This can be used to avoid the situation where a secondary view that updates on a lower
311 * frequency will throttle the frame rate of the client application.
312 */
313bool QWaylandView::allowDiscardFrontBuffer() const
314{
315 Q_D(const QWaylandView);
316 return d->allowDiscardFrontBuffer;
317}
318
319void QWaylandView::setAllowDiscardFrontBuffer(bool discard)
320{
321 Q_D(QWaylandView);
322 if (d->allowDiscardFrontBuffer == discard)
323 return;
324 d->allowDiscardFrontBuffer = discard;
325 emit allowDiscardFrontBufferChanged();
326}
327
328/*!
329 * Makes this QWaylandView the primary view for the surface.
330 *
331 * It has no effect if this QWaylandView is not holding any QWaylandSurface
332 *
333 * \sa QWaylandSurface::primaryView
334 */
335void QWaylandView::setPrimary()
336{
337 Q_D(QWaylandView);
338 if (d->surface)
339 d->surface->setPrimaryView(this);
340 else
341 qWarning(msg: "Calling setPrimary() on a QWaylandView without a surface has no effect.");
342}
343
344/*!
345 * Returns true if this QWaylandView is the primary view for the QWaylandSurface
346 *
347 * \sa QWaylandSurface::primaryView
348 */
349bool QWaylandView::isPrimary() const
350{
351 Q_D(const QWaylandView);
352 return d->surface && d->surface->primaryView() == this;
353}
354
355/*!
356 * Returns the Wayland surface resource for this QWaylandView.
357 */
358struct wl_resource *QWaylandView::surfaceResource() const
359{
360 Q_D(const QWaylandView);
361 if (!d->surface)
362 return nullptr;
363 return d->surface->resource();
364}
365
366QT_END_NAMESPACE
367
368#include "moc_qwaylandview.cpp"
369

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtwayland/src/compositor/compositor_api/qwaylandview.cpp