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 <QDebug> |
5 | #include <QAtomicInt> |
6 | |
7 | #include "qwaylandbufferref.h" |
8 | #include "wayland_wrapper/qwlclientbuffer_p.h" |
9 | |
10 | #include <type_traits> |
11 | |
12 | QT_BEGIN_NAMESPACE |
13 | |
14 | #define CHECK1(l, r, op) \ |
15 | static_assert(std::is_same_v< \ |
16 | bool, \ |
17 | decltype(std::declval<QWaylandBufferRef l >() op \ |
18 | std::declval<QWaylandBufferRef r >()) \ |
19 | >) |
20 | #define CHECK2(l, r) \ |
21 | CHECK1(l, r, ==); \ |
22 | CHECK1(l, r, !=) |
23 | #define CHECK(l, r) \ |
24 | CHECK2(l, r); \ |
25 | CHECK2(l &, r); \ |
26 | CHECK2(l &, r &); \ |
27 | CHECK2(l, r &) |
28 | |
29 | CHECK(, ); |
30 | CHECK(const, ); |
31 | CHECK(const, const); |
32 | CHECK(, const); |
33 | |
34 | #undef CHECK |
35 | #undef CHECK2 |
36 | #undef CHECK1 |
37 | |
38 | class QWaylandBufferRefPrivate |
39 | { |
40 | public: |
41 | QtWayland::ClientBuffer *buffer = nullptr; |
42 | |
43 | bool nullOrDestroyed() { |
44 | return !buffer || buffer->isDestroyed(); |
45 | } |
46 | }; |
47 | |
48 | /*! |
49 | * \class QWaylandBufferRef |
50 | * \inmodule QtWaylandCompositor |
51 | * \since 5.8 |
52 | * \brief The QWaylandBufferRef class holds the reference to a surface buffer. |
53 | * |
54 | * This class can be used to reference a surface buffer. As long as a reference |
55 | * to the buffer exists, it is owned by the compositor and the client cannot modify it. |
56 | */ |
57 | |
58 | /*! |
59 | * Constructs a null buffer ref. |
60 | */ |
61 | QWaylandBufferRef::QWaylandBufferRef() |
62 | : d(new QWaylandBufferRefPrivate) |
63 | { |
64 | d->buffer = nullptr; |
65 | } |
66 | |
67 | /*! |
68 | * Constructs a reference to \a buffer. |
69 | */ |
70 | QWaylandBufferRef::QWaylandBufferRef(QtWayland::ClientBuffer *buffer) |
71 | : d(new QWaylandBufferRefPrivate) |
72 | { |
73 | d->buffer = buffer; |
74 | if (buffer) |
75 | buffer->ref(); |
76 | } |
77 | |
78 | /*! |
79 | * Creates a new reference to the buffer referenced by \a ref. |
80 | */ |
81 | QWaylandBufferRef::QWaylandBufferRef(const QWaylandBufferRef &ref) |
82 | : d(new QWaylandBufferRefPrivate) |
83 | { |
84 | d->buffer = ref.d->buffer; |
85 | if (d->buffer) |
86 | d->buffer->ref(); |
87 | } |
88 | |
89 | /*! |
90 | * Dereferences the buffer. |
91 | */ |
92 | QWaylandBufferRef::~QWaylandBufferRef() |
93 | { |
94 | if (d->buffer) |
95 | d->buffer->deref(); |
96 | delete d; |
97 | } |
98 | |
99 | /*! |
100 | * Assigns \a ref to this buffer and adds a reference to it. The previously referenced buffer is |
101 | * dereferenced. |
102 | */ |
103 | QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) |
104 | { |
105 | if (ref.d->buffer) |
106 | ref.d->buffer->ref(); |
107 | |
108 | if (d->buffer) |
109 | d->buffer->deref(); |
110 | |
111 | d->buffer = ref.d->buffer; |
112 | |
113 | return *this; |
114 | } |
115 | |
116 | /*! |
117 | \fn bool QWaylandBufferRef::operator==(const QWaylandBufferRef &lhs, const QWaylandBufferRef &rhs) |
118 | |
119 | Returns \c true if \a lhs references the same buffer as \a rhs. |
120 | Otherwise returns \c{false}. |
121 | */ |
122 | bool operator==(const QWaylandBufferRef &lhs, const QWaylandBufferRef &rhs) noexcept |
123 | { |
124 | return lhs.d->buffer == rhs.d->buffer; |
125 | } |
126 | |
127 | /*! |
128 | \fn bool QWaylandBufferRef::operator!=(const QWaylandBufferRef &lhs, const QWaylandBufferRef &rhs) |
129 | |
130 | Returns \c false if \a lhs references the same buffer as \a rhs. |
131 | Otherwise returns \c {true}. |
132 | */ |
133 | |
134 | /*! |
135 | * Returns true if this QWaylandBufferRef does not reference a buffer. |
136 | * Otherwise returns false. |
137 | * |
138 | * \sa hasBuffer(), hasContent() |
139 | */ |
140 | bool QWaylandBufferRef::isNull() const |
141 | { |
142 | return !d->buffer; |
143 | } |
144 | |
145 | /*! |
146 | * Returns true if this QWaylandBufferRef references a buffer. Otherwise returns false. |
147 | * |
148 | * \sa isNull(), hasContent() |
149 | */ |
150 | bool QWaylandBufferRef::hasBuffer() const |
151 | { |
152 | return d->buffer; |
153 | } |
154 | /*! |
155 | * Returns true if this QWaylandBufferRef references a buffer that has content. Otherwise returns false. |
156 | * |
157 | * \sa isNull(), hasBuffer() |
158 | */ |
159 | bool QWaylandBufferRef::hasContent() const |
160 | { |
161 | return QtWayland::ClientBuffer::hasContent(buffer: d->buffer); |
162 | } |
163 | /*! |
164 | * Returns true if this QWaylandBufferRef references a buffer that has protected content. Otherwise returns false. |
165 | * |
166 | * \note This is an enabler which presumes support in the client buffer integration. None of the |
167 | * client buffer integrations included with Qt currently support protected content buffers. |
168 | * |
169 | * \since 6.2 |
170 | * \sa hasContent() |
171 | */ |
172 | bool QWaylandBufferRef::hasProtectedContent() const |
173 | { |
174 | return QtWayland::ClientBuffer::hasProtectedContent(buffer: d->buffer); |
175 | } |
176 | |
177 | /*! |
178 | * Returns true if this QWaylandBufferRef references a buffer that |
179 | * has been destroyed. Otherwise returns false. |
180 | */ |
181 | bool QWaylandBufferRef::isDestroyed() const |
182 | { |
183 | return d->buffer && d->buffer->isDestroyed(); |
184 | } |
185 | |
186 | /*! |
187 | * Returns the Wayland resource for the buffer. |
188 | */ |
189 | struct ::wl_resource *QWaylandBufferRef::wl_buffer() const |
190 | { |
191 | return d->buffer ? d->buffer->waylandBufferHandle() : nullptr; |
192 | } |
193 | |
194 | /*! |
195 | * \internal |
196 | */ |
197 | QtWayland::ClientBuffer *QWaylandBufferRef::buffer() const |
198 | { |
199 | return d->buffer; |
200 | } |
201 | |
202 | /*! |
203 | * Returns the size of the buffer. |
204 | * If the buffer referenced is null, an invalid QSize() is returned. |
205 | */ |
206 | QSize QWaylandBufferRef::size() const |
207 | { |
208 | if (d->nullOrDestroyed()) |
209 | return QSize(); |
210 | |
211 | return d->buffer->size(); |
212 | } |
213 | |
214 | /*! |
215 | * Returns the origin of the buffer. |
216 | * If the buffer referenced is null, QWaylandSurface::OriginBottomLeft |
217 | * is returned. |
218 | */ |
219 | QWaylandSurface::Origin QWaylandBufferRef::origin() const |
220 | { |
221 | if (d->buffer) |
222 | return d->buffer->origin(); |
223 | |
224 | return QWaylandSurface::OriginBottomLeft; |
225 | } |
226 | |
227 | QWaylandBufferRef::BufferType QWaylandBufferRef::bufferType() const |
228 | { |
229 | if (d->nullOrDestroyed()) |
230 | return BufferType_Null; |
231 | |
232 | if (isSharedMemory()) |
233 | return BufferType_SharedMemory; |
234 | |
235 | return BufferType_Egl; |
236 | } |
237 | |
238 | QWaylandBufferRef::BufferFormatEgl QWaylandBufferRef::bufferFormatEgl() const |
239 | { |
240 | if (d->nullOrDestroyed()) |
241 | return BufferFormatEgl_Null; |
242 | |
243 | return d->buffer->bufferFormatEgl(); |
244 | } |
245 | |
246 | /*! |
247 | * Returns true if the buffer is a shared memory buffer. Otherwise returns false. |
248 | */ |
249 | bool QWaylandBufferRef::isSharedMemory() const |
250 | { |
251 | if (d->nullOrDestroyed()) |
252 | return false; |
253 | |
254 | return d->buffer->isSharedMemory(); |
255 | } |
256 | |
257 | /*! |
258 | * Returns an image with the contents of the buffer. |
259 | */ |
260 | QImage QWaylandBufferRef::image() const |
261 | { |
262 | if (d->nullOrDestroyed()) |
263 | return QImage(); |
264 | |
265 | return d->buffer->image(); |
266 | } |
267 | |
268 | #if QT_CONFIG(opengl) |
269 | /*! |
270 | * Returns an OpenGL texture for the buffer. \a plane is the index for multi-plane formats, such as YUV. |
271 | * |
272 | * The returned texture is owned by the buffer. The texture is only valid for as |
273 | * long as the buffer reference exists. The caller of this function must not delete the texture, and must |
274 | * keep a reference to the buffer for as long as the texture is being used. |
275 | * |
276 | * Returns \c nullptr if there is no valid buffer, or if no texture can be created. |
277 | */ |
278 | QOpenGLTexture *QWaylandBufferRef::toOpenGLTexture(int plane) const |
279 | { |
280 | if (d->nullOrDestroyed()) |
281 | return nullptr; |
282 | |
283 | return d->buffer->toOpenGlTexture(plane); |
284 | } |
285 | |
286 | /*! |
287 | * Returns the native handle for this buffer, and marks it as locked so it will not be |
288 | * released until unlockNativeBuffer() is called. |
289 | * |
290 | * Returns 0 if there is no native handle for this buffer, or if the lock was unsuccessful. |
291 | */ |
292 | quintptr QWaylandBufferRef::lockNativeBuffer() |
293 | { |
294 | return d->buffer->lockNativeBuffer(); |
295 | } |
296 | |
297 | /*! |
298 | * Marks the native buffer as no longer in use. \a handle must correspond to the value returned by |
299 | * a previous call to lockNativeBuffer(). |
300 | */ |
301 | void QWaylandBufferRef::unlockNativeBuffer(quintptr handle) |
302 | { |
303 | d->buffer->unlockNativeBuffer(native_buffer: handle); |
304 | } |
305 | |
306 | #endif |
307 | |
308 | QT_END_NAMESPACE |
309 | |