Qt 6.x
The Qt SDK
Loading...
Searching...
No Matches
linuxdmabufclientbufferintegration.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3
5#include "linuxdmabuf.h"
6
7#include <QtWaylandCompositor/QWaylandCompositor>
8#include <QtWaylandCompositor/private/qwayland-server-wayland.h>
9#include <qpa/qplatformnativeinterface.h>
10#include <QtOpenGL/QOpenGLTexture>
11#include <QtCore/QVarLengthArray>
12#include <QtGui/QGuiApplication>
13#include <QtGui/QOpenGLContext>
14
15#include <EGL/egl.h>
16#include <EGL/eglext.h>
17#include <unistd.h>
18#include <drm_fourcc.h>
19
21
23 switch (format) {
24 case DRM_FORMAT_RGB332:
25 case DRM_FORMAT_BGR233:
26 case DRM_FORMAT_XRGB4444:
27 case DRM_FORMAT_XBGR4444:
28 case DRM_FORMAT_RGBX4444:
29 case DRM_FORMAT_BGRX4444:
30 case DRM_FORMAT_XRGB1555:
31 case DRM_FORMAT_XBGR1555:
32 case DRM_FORMAT_RGBX5551:
33 case DRM_FORMAT_BGRX5551:
35 case DRM_FORMAT_BGR565:
38 case DRM_FORMAT_XRGB8888:
39 case DRM_FORMAT_XBGR8888:
40 case DRM_FORMAT_RGBX8888:
41 case DRM_FORMAT_BGRX8888:
42 case DRM_FORMAT_XRGB2101010:
43 case DRM_FORMAT_XBGR2101010:
44 case DRM_FORMAT_RGBX1010102:
45 case DRM_FORMAT_BGRX1010102:
47 case DRM_FORMAT_ARGB4444:
48 case DRM_FORMAT_ABGR4444:
49 case DRM_FORMAT_RGBA4444:
50 case DRM_FORMAT_BGRA4444:
51 case DRM_FORMAT_ARGB1555:
52 case DRM_FORMAT_ABGR1555:
53 case DRM_FORMAT_RGBA5551:
54 case DRM_FORMAT_BGRA5551:
55 case DRM_FORMAT_ARGB8888:
58 case DRM_FORMAT_BGRA8888:
59 case DRM_FORMAT_ARGB2101010:
60 case DRM_FORMAT_ABGR2101010:
61 case DRM_FORMAT_RGBA1010102:
64 case DRM_FORMAT_YUYV:
66 default:
67 qCDebug(qLcWaylandCompositorHardwareIntegration) << "Buffer format" << Qt::hex << format << "not supported";
69 }
70}
71
73 switch (format) {
78 default:
80 }
81}
82
83// Initialize the EGLImage for a dmabuf buffer which conceptually consists of a
84// single plane. Note that depending on the modifiers, the buffer may be actually
85// transported as multiple dmabuf planes which must be combined into a single
86// EGLImage. For formats where the buffer needs to be represented as multiple
87// EGLImages (e.g., various YUV formats) a different approach is required.
88bool LinuxDmabufClientBufferIntegration::initSimpleTexture(LinuxDmabufWlBuffer *dmabufBuffer)
89{
90 bool success = true;
91
92 // Resolving GL functions may need a context current, so do it only here.
94 gl_egl_image_target_texture_2d = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
95
96 if (dmabufBuffer->plane(0).modifiers != DRM_FORMAT_MOD_INVALID && !m_supportsDmabufModifiers) {
97 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Buffer uses dmabuf modifiers, which are not supported.";
98 success = false;
99 }
100
101 // 6 entries for the common attribs plus 10 per possible plane, plus 1 for
102 // the final EGL_NONE sentinel.
104
105 attribs.append(EGL_WIDTH);
106 attribs.append(dmabufBuffer->size().width());
107 attribs.append(EGL_HEIGHT);
108 attribs.append(dmabufBuffer->size().height());
109 attribs.append(EGL_LINUX_DRM_FOURCC_EXT);
110 attribs.append(EGLint(dmabufBuffer->drmFormat()));
111
112#define ADD_PLANE_ATTRIBS(plane_idx) { \
113 attribs.append(EGL_DMA_BUF_PLANE ## plane_idx ## _FD_EXT); \
114 attribs.append(dmabufBuffer->plane(plane_idx).fd); \
115 attribs.append(EGL_DMA_BUF_PLANE ## plane_idx ## _OFFSET_EXT); \
116 attribs.append(EGLint(dmabufBuffer->plane(plane_idx).offset)); \
117 attribs.append(EGL_DMA_BUF_PLANE ## plane_idx ## _PITCH_EXT); \
118 attribs.append(EGLint(dmabufBuffer->plane(plane_idx).stride)); \
119 if (dmabufBuffer->plane(plane_idx).modifiers != DRM_FORMAT_MOD_INVALID) { \
120 attribs.append(EGL_DMA_BUF_PLANE ## plane_idx ## _MODIFIER_LO_EXT); \
121 attribs.append(EGLint(dmabufBuffer->plane(plane_idx).modifiers & 0xffffffff)); \
122 attribs.append(EGL_DMA_BUF_PLANE ## plane_idx ## _MODIFIER_HI_EXT); \
123 attribs.append(EGLint(dmabufBuffer->plane(plane_idx).modifiers >> 32)); \
124 } \
125}
126
127 switch (dmabufBuffer->planesNumber()) {
128 case 4:
131 case 3:
134 case 2:
137 case 1:
139 break;
140 default:
141 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Buffer uses invalid number of planes:" << dmabufBuffer->planesNumber();
142 return false;
143 }
144
145 attribs.append(EGL_NONE);
146
147 // note: EGLImageKHR does NOT take ownership of the file descriptors
148 EGLImageKHR image = egl_create_image(m_eglDisplay,
149 EGL_NO_CONTEXT,
150 EGL_LINUX_DMA_BUF_EXT,
151 (EGLClientBuffer) nullptr,
152 attribs.constData());
153
154 if (image == EGL_NO_IMAGE_KHR) {
155 qCWarning(qLcWaylandCompositorHardwareIntegration) << "failed to create EGL image from" <<
156 dmabufBuffer->planesNumber() << "plane(s)";
157 success = false;
158 }
159
160 dmabufBuffer->initImage(0, image);
161
162 return success;
163}
164
165bool LinuxDmabufClientBufferIntegration::initYuvTexture(LinuxDmabufWlBuffer *dmabufBuffer)
166{
167 bool success = true;
168
169 const YuvFormatConversion conversion = m_yuvFormats.value(dmabufBuffer->drmFormat());
170 if (conversion.inputPlanes != dmabufBuffer->planesNumber()) {
171 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Buffer for this format must provide" << conversion.inputPlanes
172 << "planes but only" << dmabufBuffer->planesNumber() << "received";
173 return false;
174 }
175
176 // Resolving GL functions may need a context current, so do it only here.
178 gl_egl_image_target_texture_2d = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
179
180
181 if (dmabufBuffer->plane(0).modifiers != DRM_FORMAT_MOD_INVALID && !m_supportsDmabufModifiers) {
182 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Buffer uses dmabuf modifiers, which are not supported.";
183 success = false;
184 }
185
186 for (uint32_t i = 0; i < conversion.outputPlanes; ++i) {
187 const YuvPlaneConversion plane = conversion.plane[i];
188
190 EGL_WIDTH, dmabufBuffer->size().width() / plane.widthDivisor,
191 EGL_HEIGHT, dmabufBuffer->size().height() / plane.heightDivisor,
192 EGL_LINUX_DRM_FOURCC_EXT, plane.format,
193 EGL_DMA_BUF_PLANE0_FD_EXT, dmabufBuffer->plane(plane.planeIndex).fd,
194 EGL_DMA_BUF_PLANE0_OFFSET_EXT, EGLint(dmabufBuffer->plane(plane.planeIndex).offset),
195 EGL_DMA_BUF_PLANE0_PITCH_EXT, EGLint(dmabufBuffer->plane(plane.planeIndex).stride),
196 EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, EGLint(dmabufBuffer->plane(plane.planeIndex).modifiers & 0xffffffff),
197 EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, EGLint(dmabufBuffer->plane(plane.planeIndex).modifiers >> 32),
198 EGL_NONE
199 };
200
201 // note: EGLImageKHR does NOT take ownership of the file descriptors
202 EGLImageKHR image = egl_create_image(m_eglDisplay,
203 EGL_NO_CONTEXT,
204 EGL_LINUX_DMA_BUF_EXT,
205 (EGLClientBuffer) nullptr,
206 attribs.constData());
207
208 if (image == EGL_NO_IMAGE_KHR) {
209 qCWarning(qLcWaylandCompositorHardwareIntegration) << "failed to create EGL image for plane" << i;
210 success = false;
211 }
212
213 dmabufBuffer->initImage(i, image);
214 }
215 return success;
216}
217
219{
220 YuvPlaneConversion firstPlane;
221 firstPlane.format = DRM_FORMAT_GR88;
222 firstPlane.widthDivisor = 1;
223 firstPlane.heightDivisor = 1;
224 firstPlane.planeIndex = 0;
225
226 YuvPlaneConversion secondPlane;
227 secondPlane.format = DRM_FORMAT_ARGB8888;
228 secondPlane.widthDivisor = 2;
229 secondPlane.heightDivisor = 1;
230 secondPlane.planeIndex = 0;
231
232 YuvFormatConversion formatConversion;
233 formatConversion.inputPlanes = 1;
234 formatConversion.outputPlanes = 2;
235 formatConversion.plane[0] = firstPlane;
236 formatConversion.plane[1] = secondPlane;
237
238 m_yuvFormats.insert(DRM_FORMAT_YUYV, formatConversion);
239}
240
242{
243 m_importedBuffers.clear();
244
245 if (egl_unbind_wayland_display != nullptr && m_displayBound) {
246 Q_ASSERT(m_wlDisplay != nullptr);
247 if (!egl_unbind_wayland_display(m_eglDisplay, m_wlDisplay))
248 qCWarning(qLcWaylandCompositorHardwareIntegration) << "eglUnbindWaylandDisplayWL failed";
249 }
250}
251
253{
254 m_linuxDmabuf.reset(new LinuxDmabuf(display, this));
255
256 const bool ignoreBindDisplay = !qgetenv("QT_WAYLAND_IGNORE_BIND_DISPLAY").isEmpty() && qgetenv("QT_WAYLAND_IGNORE_BIND_DISPLAY").toInt() != 0;
257
258 // initialize hardware extensions
259 egl_query_dmabuf_modifiers_ext = reinterpret_cast<PFNEGLQUERYDMABUFMODIFIERSEXTPROC>(eglGetProcAddress("eglQueryDmaBufModifiersEXT"));
260 egl_query_dmabuf_formats_ext = reinterpret_cast<PFNEGLQUERYDMABUFFORMATSEXTPROC>(eglGetProcAddress("eglQueryDmaBufFormatsEXT"));
261 if (!egl_query_dmabuf_modifiers_ext || !egl_query_dmabuf_formats_ext) {
262 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglQueryDmaBufModifiersEXT and eglQueryDmaBufFormatsEXT.";
263 return;
264 }
265
266 egl_bind_wayland_display = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL"));
267 egl_unbind_wayland_display = reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL"));
268 if ((!egl_bind_wayland_display || !egl_unbind_wayland_display) && !ignoreBindDisplay) {
269 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL.";
270 return;
271 }
272
273 egl_create_image = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
274 egl_destroy_image = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
275 if (!egl_create_image || !egl_destroy_image) {
276 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR.";
277 return;
278 }
279
280 // initialize EGL display
282 if (!nativeInterface) {
283 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. No native platform interface available.";
284 return;
285 }
286
287 m_eglDisplay = nativeInterface->nativeResourceForIntegration("EglDisplay");
288 if (!m_eglDisplay) {
289 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. Could not get EglDisplay for window.";
290 return;
291 }
292
293 const char *extensionString = eglQueryString(m_eglDisplay, EGL_EXTENSIONS);
294 if (!extensionString || !strstr(extensionString, "EGL_EXT_image_dma_buf_import")) {
295 qCWarning(qLcWaylandCompositorHardwareIntegration) << "Failed to initialize EGL display. There is no EGL_EXT_image_dma_buf_import extension.";
296 return;
297 }
298 if (strstr(extensionString, "EGL_EXT_image_dma_buf_import_modifiers"))
299 m_supportsDmabufModifiers = true;
300
301 if (egl_bind_wayland_display && egl_unbind_wayland_display) {
302 m_displayBound = egl_bind_wayland_display(m_eglDisplay, display);
303 if (!m_displayBound)
304 qCDebug(qLcWaylandCompositorHardwareIntegration) << "Wayland display already bound by other client buffer integration.";
305 m_wlDisplay = display;
306 }
307
308 // request and sent formats/modifiers only after egl_display is bound
310 for (const auto &format : supportedDrmFormats()) {
311 modifiers[format] = supportedDrmModifiers(format);
312 }
313 m_linuxDmabuf->setSupportedModifiers(modifiers);
314}
315
316QList<uint32_t> LinuxDmabufClientBufferIntegration::supportedDrmFormats()
317{
318 if (!egl_query_dmabuf_formats_ext)
319 return QList<uint32_t>();
320
321 // request total number of formats
322 EGLint count = 0;
323 EGLBoolean success = egl_query_dmabuf_formats_ext(m_eglDisplay, 0, nullptr, &count);
324
325 if (success && count > 0) {
326 QList<uint32_t> drmFormats(count);
327 if (egl_query_dmabuf_formats_ext(m_eglDisplay, count, (EGLint *) drmFormats.data(), &count))
328 return drmFormats;
329 }
330
331 return QList<uint32_t>();
332}
333
334QList<uint64_t> LinuxDmabufClientBufferIntegration::supportedDrmModifiers(uint32_t format)
335{
336 if (!egl_query_dmabuf_modifiers_ext)
337 return QList<uint64_t>();
338
339 // request total number of formats
340 EGLint count = 0;
341 EGLBoolean success = egl_query_dmabuf_modifiers_ext(m_eglDisplay, format, 0, nullptr, nullptr, &count);
342
343 if (success && count > 0) {
345 if (egl_query_dmabuf_modifiers_ext(m_eglDisplay, format, count, modifiers.data(), nullptr, &count)) {
346 return modifiers;
347 }
348 }
349
350 return QList<uint64_t>();
351}
352
353
355 QMutexLocker locker(&m_orphanedTexturesLock);
356
357 Q_ASSERT(m_orphanedTextures.size() == m_orphanedTexturesAboutToBeDestroyedConnection.size());
358
359 m_orphanedTextures << texture;
360 m_orphanedTexturesAboutToBeDestroyedConnection << QObject::connect(ctx, &QOpenGLContext::aboutToBeDestroyed,
361 ctx, [this, texture]() {
362 this->deleteSpecificOrphanedTexture(texture);
364}
365
366
368{
370
371 QMutexLocker locker(&m_orphanedTexturesLock);
372
373 if (!m_orphanedTextures.isEmpty())
374 qCDebug(qLcWaylandCompositorHardwareIntegration) << "About to delete some textures: "
375 << m_orphanedTextures;
376
377 qDeleteAll(m_orphanedTextures);
378
379 for (QMetaObject::Connection con : m_orphanedTexturesAboutToBeDestroyedConnection)
381
382 m_orphanedTexturesAboutToBeDestroyedConnection.clear();
383 m_orphanedTextures.clear();
384}
385
387{
388 Q_ASSERT(m_orphanedTextures.size() == m_orphanedTexturesAboutToBeDestroyedConnection.size());
389
390 QMutexLocker locker(&m_orphanedTexturesLock);
391
392 // In this case, deleteOrphanedTextures was called while we entered (see lock!) this function!
393 if (m_orphanedTextures.length()==0) {
394 qCWarning(qLcWaylandCompositorHardwareIntegration)
395 << Q_FUNC_INFO
396 << "Looks like deleteOrphanedTextures() and this function where called simultaneously!"
397 << "This might cause issues!";
398 return;
399 }
400
401 int i = m_orphanedTextures.indexOf(texture);
402 Q_ASSERT(i!=-1); // If it isn't empty (see above if), then it should be guaranteed to still contain this texture
403
404 m_orphanedTextures.removeAt(i);
405 QMetaObject::Connection con = m_orphanedTexturesAboutToBeDestroyedConnection.takeAt(i);
406
408 delete texture;
409
410 qCDebug(qLcWaylandCompositorHardwareIntegration)
411 << Q_FUNC_INFO
412 << "texture deleted due to QOpenGLContext::aboutToBeDestroyed!"
413 << "Pointer (now dead) was:" << (void*)texture;
414}
415
417{
418 egl_destroy_image(m_eglDisplay, image);
419}
420
422{
423 auto it = m_importedBuffers.find(resource);
424 if (it != m_importedBuffers.end()) {
425 m_importedBuffers.value(resource);
426 return new LinuxDmabufClientBuffer(this, it.value()->resource()->handle, m_importedBuffers.value(resource));
427 }
428
429 return nullptr;
430}
431
432bool LinuxDmabufClientBufferIntegration::importBuffer(wl_resource *resource, LinuxDmabufWlBuffer *linuxDmabufBuffer)
433{
434 if (m_importedBuffers.contains(resource)) {
435 qCWarning(qLcWaylandCompositorHardwareIntegration) << "buffer has already been added";
436 return false;
437 }
438 m_importedBuffers[resource] = linuxDmabufBuffer;
439 if (m_yuvFormats.contains(linuxDmabufBuffer->drmFormat()))
440 return initYuvTexture(linuxDmabufBuffer);
441 else
442 return initSimpleTexture(linuxDmabufBuffer);
443}
444
446{
447 m_importedBuffers.remove(resource);
448}
449
450LinuxDmabufClientBuffer::LinuxDmabufClientBuffer(LinuxDmabufClientBufferIntegration *integration,
451 wl_resource *bufferResource,
452 LinuxDmabufWlBuffer *dmabufBuffer)
453 : ClientBuffer(bufferResource)
454 , m_integration(integration)
455{
456 d = dmabufBuffer;
457}
458
460{
461 // At this point we should have a valid OpenGL context, so it's safe to destroy textures
462 m_integration->deleteOrphanedTextures();
463
464 if (!m_buffer)
465 return nullptr;
466
467 QOpenGLTexture *texture = d->texture(plane);
468
469 const auto target = static_cast<QOpenGLTexture::Target>(GL_TEXTURE_2D);
470
471 if (!texture) {
474 texture->setSize(d->size().width(), d->size().height());
475 texture->create();
476 d->initTexture(plane, texture);
477 }
478
479 if (m_textureDirty) {
480 m_textureDirty = false;
481 texture->bind();
482 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
483 m_integration->gl_egl_image_target_texture_2d(target, d->image(plane));
484 }
485 return texture;
486}
487
489{
490 m_integration->removeBuffer(m_buffer);
491 ClientBuffer::setDestroyed();
492}
493
495{
496 // resources are deleted by buffer_destroy_resource
497 m_buffer = nullptr;
498 d = nullptr;
499}
500
502{
503 return formatFromDrmFormat(d->drmFormat());
504}
505
507{
508 return d->size();
509}
510
512{
513 return (d->flags() & QtWaylandServer::zwp_linux_buffer_params_v1::flags_y_invert) ? QWaylandSurface::OriginBottomLeft : QWaylandSurface::OriginTopLeft;
514}
515
void deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx)
QtWayland::ClientBuffer * createBufferFor(wl_resource *resource) override
bool importBuffer(wl_resource *resource, LinuxDmabufWlBuffer *linuxDmabufBuffer)
void initializeHardware(struct ::wl_display *display) override
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d
QOpenGLTexture * toOpenGlTexture(int plane) override
QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const override
QWaylandSurface::Origin origin() const override
uint32_t flags() const
QSize size() const
Plane & plane(uint index)
void initTexture(uint32_t plane, QOpenGLTexture *texture)
uint32_t drmFormat() const
void initImage(uint32_t plane, EGLImageKHR image)
QOpenGLTexture * texture(uint32_t plane) const
EGLImageKHR image(uint32_t plane)
uint32_t planesNumber() const
void setSupportedModifiers(const QHash< uint32_t, QList< uint64_t > > &modifiers)
int toInt(bool *ok=nullptr, int base=10) const
Returns the byte array converted to an int using base base, which is ten by default.
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
Definition qbytearray.h:106
static QPlatformNativeInterface * platformNativeInterface()
\inmodule QtCore
Definition qhash.h:818
bool remove(const Key &key)
Removes the item that has the key from the hash.
Definition qhash.h:956
iterator find(const Key &key)
Returns an iterator pointing to the item with the key in the hash.
Definition qhash.h:1258
bool contains(const Key &key) const noexcept
Returns true if the hash contains an item with the key; otherwise returns false.
Definition qhash.h:991
T value(const Key &key) const noexcept
Definition qhash.h:1044
iterator end() noexcept
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary item after the last ...
Definition qhash.h:1206
void clear() noexcept(std::is_nothrow_destructible< Node >::value)
Removes all items from the hash and frees up all memory used by it.
Definition qhash.h:949
iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition qhash.h:1283
Definition qlist.h:74
qsizetype size() const noexcept
Definition qlist.h:386
bool isEmpty() const noexcept
Definition qlist.h:390
void removeAt(qsizetype i)
Definition qlist.h:573
T takeAt(qsizetype i)
Definition qlist.h:592
qsizetype length() const noexcept
Definition qlist.h:388
void clear()
Definition qlist.h:417
\inmodule QtCore Represents a handle to a signal-slot (or signal-functor) connection.
\inmodule QtCore
Definition qmutex.h:317
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2823
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
Definition qobject.cpp:3099
\inmodule QtGui
void aboutToBeDestroyed()
This signal is emitted before the underlying native OpenGL context is destroyed, such that users may ...
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
\inmodule QtGui
TextureFormat
This enum defines the possible texture formats.
Target
This enum defines the texture target of a QOpenGLTexture object.
The QPlatformNativeInterface class provides an abstraction for retrieving native resource handles.
virtual void * nativeResourceForIntegration(const QByteArray &resource)
void reset(T *other=nullptr) noexcept(noexcept(Cleanup::cleanup(std::declval< T * >())))
Deletes the existing object it is pointing to (if any), and sets its pointer to other.
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:132
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:129
Origin
This enum type is used to specify the origin of a QWaylandSurface's buffer.
struct::wl_resource * m_buffer
EGLContext ctx
EGLImageKHR int int EGLuint64KHR * modifiers
qDeleteAll(list.begin(), list.end())
QSet< QString >::iterator it
struct wl_display * display
Definition linuxdmabuf.h:41
#define DRM_FORMAT_MOD_INVALID
Definition linuxdmabuf.h:36
#define ADD_PLANE_ATTRIBS(plane_idx)
static QT_BEGIN_NAMESPACE QWaylandBufferRef::BufferFormatEgl formatFromDrmFormat(EGLint format)
static QOpenGLTexture::TextureFormat openGLFormatFromBufferFormat(QWaylandBufferRef::BufferFormatEgl format)
QT_BEGIN_NAMESPACE typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL_compat)(EGLDisplay dpy
EGLint EGLint EGLuint64KHR * modifiers
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
@ DirectConnection
Definition image.cpp:4
#define Q_FALLTHROUGH()
#define Q_FUNC_INFO
#define DRM_FORMAT_BGR888
#define DRM_FORMAT_RGB565
#define DRM_FORMAT_RGB888
#define DRM_FORMAT_ABGR8888
#define DRM_FORMAT_GR88
#define DRM_FORMAT_BGRA1010102
#define DRM_FORMAT_RGBA8888
#define qCWarning(category,...)
#define qCDebug(category,...)
GLenum GLenum GLsizei count
GLenum target
GLenum GLuint texture
GLint GLsizei GLsizei GLenum format
const GLint * attribs
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
int fd
Definition linuxdmabuf.h:53
uint32_t stride
Definition linuxdmabuf.h:55
uint64_t modifiers
Definition linuxdmabuf.h:56
uint32_t offset
Definition linuxdmabuf.h:54
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
Definition qlist.h:955
struct YuvPlaneConversion plane[LinuxDmabufWlBuffer::MaxDmabufPlanes]