6#include <QtWaylandCompositor/QWaylandCompositor>
7#include <qpa/qplatformnativeinterface.h>
8#include <QtOpenGL/QOpenGLTexture>
9#include <QtGui/QGuiApplication>
10#include <QtGui/QOpenGLContext>
11#include <QtGui/QOffscreenSurface>
12#include <qpa/qplatformscreen.h>
13#include <QtGui/QWindow>
14#include <QtCore/QPointer>
18#include <QMutexLocker>
19#include <QVarLengthArray>
20#include <QtCore/private/qcore_unix_p.h>
21#include <QtGui/private/qeglstreamconvenience_p.h>
23#ifndef GL_TEXTURE_EXTERNAL_OES
24#define GL_TEXTURE_EXTERNAL_OES 0x8D65
27#ifndef EGL_WAYLAND_BUFFER_WL
28#define EGL_WAYLAND_BUFFER_WL 0x31D5
31#ifndef EGL_WAYLAND_EGLSTREAM_WL
32#define EGL_WAYLAND_EGLSTREAM_WL 0x334B
35#ifndef EGL_WAYLAND_PLANE_WL
36#define EGL_WAYLAND_PLANE_WL 0x31D6
39#ifndef EGL_WAYLAND_Y_INVERTED_WL
40#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB
43#ifndef EGL_TEXTURE_RGB
44#define EGL_TEXTURE_RGB 0x305D
47#ifndef EGL_TEXTURE_RGBA
48#define EGL_TEXTURE_RGBA 0x305E
51#ifndef EGL_TEXTURE_EXTERNAL_WL
52#define EGL_TEXTURE_EXTERNAL_WL 0x31DA
55#ifndef EGL_TEXTURE_Y_U_V_WL
56#define EGL_TEXTURE_Y_U_V_WL 0x31D7
59#ifndef EGL_TEXTURE_Y_UV_WL
60#define EGL_TEXTURE_Y_UV_WL 0x31D8
63#ifndef EGL_TEXTURE_Y_XUXV_WL
64#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
67#ifndef EGL_PLATFORM_X11_KHR
68#define EGL_PLATFORM_X11_KHR 0x31D5
74#ifndef EGL_WL_bind_wayland_display
84#ifndef GL_OES_EGL_image
94#define MYERRCODE(x) case x: return #x;
208 qCWarning(qLcWaylandCompositorHardwareIntegration)
209 <<
"BindTextureToBuffer() failed. Could not find glEGLImageTargetTexture2DOES.";
217#if defined(EGL_WAYLAND_Y_INVERTED_WL)
223 state.isYInverted = (
ret == EGL_FALSE || isYInverted == EGL_TRUE);
246 for (
int i = 0;
i < planes;
i++) {
248#ifdef EGL_EXT_protected_content
249 if (
buffer->isProtected()) {
250 attribs[2] = EGL_PROTECTED_CONTENT_EXT;
258 buffer->waylandBufferHandle(),
261 if (
image == EGL_NO_IMAGE_KHR) {
262 qCWarning(qLcWaylandCompositorHardwareIntegration)
263 <<
"Failed to create EGL image for plane" <<
i;
269 state.textures[
i] =
nullptr;
275 bool localContextNeeded =
false;
289 localContextNeeded =
true;
292 return localContextNeeded;
305 qCDebug(qLcWaylandCompositorHardwareIntegration)
307 <<
"(egl) creating a cleanup-lambda for QOpenGLContext::aboutToBeDestroyed!"
308 <<
", texture: " << bs->
textures[plane]
315 QMutexLocker locker(&bs->texturesLock);
319 if (bs->textures[plane] == nullptr)
322 delete bs->textures[plane];
324 qCDebug(qLcWaylandCompositorHardwareIntegration)
326 <<
"texture deleted due to QOpenGLContext::aboutToBeDestroyed!"
327 <<
"Pointer (now dead) was:" << (void*)(bs->textures[plane])
328 <<
" Associated context (about to die too) is: " << (void*)(bs->texturesContext[plane]);
330 bs->textures[plane] = nullptr;
331 bs->texturesContext[plane] = nullptr;
333 QObject::disconnect(bs->texturesAboutToBeDestroyedConnection[plane]);
334 bs->texturesAboutToBeDestroyedConnection[plane] = QMetaObject::Connection();
343 state.isYInverted =
false;
359 qCWarning(qLcWaylandCompositorHardwareIntegration,
"%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x",
Q_FUNC_INFO, __LINE__, eglGetError());
365 qCWarning(qLcWaylandCompositorHardwareIntegration)
366 <<
"EglClientBufferIntegration: creating texture with no current context";
374 qCDebug(qLcWaylandCompositorHardwareIntegration)
375 <<
" NEW texture! It's pointer and ctx pointer: "
376 << (
void*)
state.textures[0] <<
"; " << (
void*)
state.texturesContext[0];
382 EGLint code = eglGetError();
411 qCWarning(qLcWaylandCompositorHardwareIntegration,
412 "%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x",
Q_FUNC_INFO, __LINE__,
416 if (usingLocalContext)
426 qCDebug(qLcWaylandCompositorHardwareIntegration)
427 <<
Q_FUNC_INFO <<
" got texture and ctx to be deleted!"
444 qCDebug(qLcWaylandCompositorHardwareIntegration)
466 qCWarning(qLcWaylandCompositorHardwareIntegration)
468 <<
"Looks like deleteOrphanedTextures() and this function where called simultaneously!"
469 <<
"This might cause issues!";
482 qCDebug(qLcWaylandCompositorHardwareIntegration)
484 <<
"texture deleted due to QOpenGLContext::aboutToBeDestroyed!"
485 <<
"Pointer (now dead) was:" << (
void*)
texture;
497 if (
d->egl_unbind_wayland_display &&
d->display_bound) {
499 if (!
d->egl_unbind_wayland_display(
d->egl_display,
d->wlDisplay))
500 qCWarning(qLcWaylandCompositorHardwareIntegration) <<
"eglUnbindWaylandDisplayWL failed";
508 const bool ignoreBindDisplay = !
qgetenv(
"QT_WAYLAND_IGNORE_BIND_DISPLAY").
isEmpty();
511 if (!nativeInterface) {
512 qCWarning(qLcWaylandCompositorHardwareIntegration)
513 <<
"Failed to initialize EGL display. No native platform interface available.";
518 if (!
d->egl_display) {
519 qCWarning(qLcWaylandCompositorHardwareIntegration)
520 <<
"Failed to initialize EGL display. Could not get EglDisplay for window.";
524 const char *extensionString = eglQueryString(
d->egl_display, EGL_EXTENSIONS);
525 if ((!extensionString || !strstr(extensionString,
"EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) {
526 qCWarning(qLcWaylandCompositorHardwareIntegration)
527 <<
"Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension.";
531 d->egl_bind_wayland_display =
reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL
>(eglGetProcAddress(
"eglBindWaylandDisplayWL"));
532 d->egl_unbind_wayland_display =
reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL
>(eglGetProcAddress(
"eglUnbindWaylandDisplayWL"));
533 if ((!
d->egl_bind_wayland_display || !
d->egl_unbind_wayland_display) && !ignoreBindDisplay) {
534 qCWarning(qLcWaylandCompositorHardwareIntegration)
535 <<
"Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL.";
539 d->egl_query_wayland_buffer =
reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL_compat
>(eglGetProcAddress(
"eglQueryWaylandBufferWL"));
540 if (!
d->egl_query_wayland_buffer) {
541 qCWarning(qLcWaylandCompositorHardwareIntegration)
542 <<
"Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL.";
546 d->egl_create_image =
reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC
>(eglGetProcAddress(
"eglCreateImageKHR"));
547 d->egl_destroy_image =
reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC
>(eglGetProcAddress(
"eglDestroyImageKHR"));
548 if (!
d->egl_create_image || !
d->egl_destroy_image) {
549 qCWarning(qLcWaylandCompositorHardwareIntegration)
550 <<
"Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR.";
554 if (
d->egl_bind_wayland_display &&
d->egl_unbind_wayland_display) {
555 d->display_bound =
d->egl_bind_wayland_display(
d->egl_display,
display);
556 if (!
d->display_bound)
557 qCDebug(qLcWaylandCompositorHardwareIntegration) <<
"Wayland display already bound by other client buffer integration.";
562 d->funcs->initialize(
d->egl_display);
569 bool q =
d->egl_query_wayland_buffer(
d->egl_display,
buffer, EGL_WIDTH, &
w);
577 , m_integration(integration)
583 p->egl_query_wayland_buffer(
p->egl_display,
buffer, EGL_WIDTH, &
width);
584 p->egl_query_wayland_buffer(
p->egl_display,
buffer, EGL_HEIGHT, &
height);
598 p->egl_destroy_image(
p->egl_display,
image);
601 p->funcs->destroy_stream(
p->egl_display, d->
egl_stream);
606 for (
int i=0;
i<3;
i++) {
609 qCDebug(qLcWaylandCompositorHardwareIntegration)
665 p->deleteOrphanedTextures();
681 p->setupBufferAndCleanup(this->d,
texture, plane);
687 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
689#ifdef GL_EXT_protected_textures
699 ClientBuffer::setCommitted(damage);
741 p->egl_destroy_image(
p->egl_display,
image);
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
PFNEGLQUERYSTREAMKHRPROC query_stream
PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC create_stream_from_file_descriptor
PFNEGLDESTROYSTREAMKHRPROC destroy_stream
PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC stream_consumer_gltexture
PFNEGLCREATESTREAMATTRIBNVPROC create_stream_attrib_nv
PFNEGLSTREAMCONSUMERACQUIREKHRPROC stream_consumer_acquire
static QPlatformNativeInterface * platformNativeInterface()
qsizetype size() const noexcept
void removeAt(qsizetype i)
qsizetype length() const noexcept
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void create()
Allocates the platform resources associated with the offscreen surface.
void setFormat(const QSurfaceFormat &format)
Sets the offscreen surface format.
bool create()
Attempts to create the OpenGL context with the current configuration.
bool makeCurrent(QSurface *surface)
Makes the context current in the current thread, against the given surface.
QSurfaceFormat format() const
Returns the format of the underlying platform context, if create() has been called.
void setShareContext(QOpenGLContext *shareContext)
Makes this context share textures, shaders, and other OpenGL resources with shareContext.
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,...
void doneCurrent()
Convenience function for calling makeCurrent with a 0 surface.
static QOpenGLContext * globalShareContext()
TextureFormat
This enum defines the possible texture formats.
Target
This enum defines the texture target of a QOpenGLTexture object.
The QRegion class specifies a clip region for a painter.
T * data() const noexcept
Returns the value of the pointer referenced by this object.
constexpr int height() const noexcept
Returns the height.
constexpr int width() const noexcept
Returns the width.
@ BufferFormatEgl_EXTERNAL_OES
Origin
This enum type is used to specify the origin of a QWaylandSurface's buffer.
virtual bool isProtected(struct ::wl_resource *buffer)
virtual QImage image() const
struct::wl_resource * m_buffer
struct::wl_resource * waylandBufferHandle() const
QMutex orphanedTexturesLock
void deleteOrphanedTextures()
void handleEglstreamTexture(WaylandEglClientBuffer *buffer, wl_resource *bufferHandle)
QOpenGLContext * localContext
static WaylandEglClientBufferIntegrationPrivate * get(WaylandEglClientBufferIntegration *integration)
PFNEGLCREATEIMAGEKHRPROC egl_create_image
PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image
QList< QMetaObject::Connection > orphanedTexturesAboutToBeDestroyedConnection
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d
void initEglTexture(WaylandEglClientBuffer *buffer, EGLint format)
bool initEglStream(WaylandEglClientBuffer *buffer, struct ::wl_resource *bufferHandle)
PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display
void initBuffer(WaylandEglClientBuffer *buffer)
QList< QOpenGLTexture * > orphanedTextures
QEGLStreamConvenience * funcs
void deleteSpecificOrphanedTexture(QOpenGLTexture *texture)
void registerBuffer(struct ::wl_resource *buffer, BufferState state)
void setupBufferAndCleanup(BufferState *bs, QOpenGLTexture *texture, int plane)
PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display
void deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx)
QOffscreenSurface * offscreenSurface
WaylandEglClientBufferIntegrationPrivate()
PFNEGLQUERYWAYLANDBUFFERWL_compat egl_query_wayland_buffer
void initializeHardware(struct ::wl_display *display) override
WaylandEglClientBufferIntegration()
~WaylandEglClientBufferIntegration() override
QtWayland::ClientBuffer * createBufferFor(wl_resource *buffer) override
QSize size() const override
QOpenGLTexture * toOpenGlTexture(int plane) override
bool isProtected() override
quintptr lockNativeBuffer() override
WaylandEglClientBuffer(WaylandEglClientBufferIntegration *integration, wl_resource *bufferResource)
void unlockNativeBuffer(quintptr native_buffer) const override
QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const override
~WaylandEglClientBuffer() override
QWaylandSurface::Origin origin() const override
void setCommitted(QRegion &damage) override
qDeleteAll(list.begin(), list.end())
struct wl_display * display
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
int EGLNativeFileDescriptorKHR
#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR
typedef EGLDisplay(EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC)(EGLenum platform
#define EGL_STREAM_STATE_KHR
#define EGL_NO_STREAM_KHR
#define EGL_NO_FILE_DESCRIPTOR_KHR
#define qCWarning(category,...)
#define qCDebug(category,...)
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLuint const GLuint GLuint const GLuint * textures
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
#define GL_TEXTURE_PROTECTED_EXT
#define GL_TEXTURE_EXTERNAL_OES
GLint GLsizei GLsizei GLenum format
GLdouble GLdouble GLdouble GLdouble q
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
QVarLengthArray< EGLImageKHR, 3 > egl_images
QMetaObject::Connection texturesAboutToBeDestroyedConnection[3]
QOpenGLContext * texturesContext[3]
QOpenGLTexture * textures[3]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
static QOpenGLTexture::TextureFormat openGLFormatFromEglFormat(EGLint format)
#define EGL_TEXTURE_Y_U_V_WL
#define EGL_TEXTURE_EXTERNAL_WL
struct wl_resource EGLint EGLint * value
EGLContext EGLenum EGLClientBuffer const EGLint * attrib_list
typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL_compat)(EGLDisplay dpy
#define EGL_WAYLAND_BUFFER_WL
#define EGL_TEXTURE_Y_XUXV_WL
struct wl_display * display
struct wl_resource * buffer
#define EGL_WAYLAND_Y_INVERTED_WL
#define EGL_WAYLAND_PLANE_WL
static QT_BEGIN_NAMESPACE const char * egl_error_string(EGLint code)
static QWaylandBufferRef::BufferFormatEgl formatFromEglFormat(EGLint format)
#define EGL_TEXTURE_Y_UV_WL
EGLContext EGLenum target
#define GL_TEXTURE_EXTERNAL_OES
#define EGL_WAYLAND_EGLSTREAM_WL
struct wl_resource EGLint attribute