7#include <QtWaylandCompositor/QWaylandCompositor>
8#include <QtOpenGL/QOpenGLTexture>
9#include <QtGui/QGuiApplication>
10#include <QtGui/QOpenGLContext>
11#include <QtGui/QOffscreenSurface>
12#include <QtCore/QMutexLocker>
14#include <QtGui/private/qeglstreamconvenience_p.h>
15#include <qpa/qplatformnativeinterface.h>
17#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
18#include <QtWaylandCompositor/private/qwlbuffermanager_p.h>
21#include <EGL/eglext.h>
24#ifndef GL_TEXTURE_EXTERNAL_OES
25#define GL_TEXTURE_EXTERNAL_OES 0x8D65
28#ifndef EGL_WAYLAND_BUFFER_WL
29#define EGL_WAYLAND_BUFFER_WL 0x31D5
32#ifndef EGL_WAYLAND_EGLSTREAM_WL
33#define EGL_WAYLAND_EGLSTREAM_WL 0x334B
36#ifndef EGL_WAYLAND_PLANE_WL
37#define EGL_WAYLAND_PLANE_WL 0x31D6
40#ifndef EGL_WAYLAND_Y_INVERTED_WL
41#define EGL_WAYLAND_Y_INVERTED_WL 0x31DB
44#ifndef EGL_TEXTURE_RGB
45#define EGL_TEXTURE_RGB 0x305D
48#ifndef EGL_TEXTURE_RGBA
49#define EGL_TEXTURE_RGBA 0x305E
52#ifndef EGL_TEXTURE_EXTERNAL_WL
53#define EGL_TEXTURE_EXTERNAL_WL 0x31DA
56#ifndef EGL_TEXTURE_Y_U_V_WL
57#define EGL_TEXTURE_Y_U_V_WL 0x31D7
60#ifndef EGL_TEXTURE_Y_UV_WL
61#define EGL_TEXTURE_Y_UV_WL 0x31D8
64#ifndef EGL_TEXTURE_Y_XUXV_WL
65#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
68#ifndef EGL_PLATFORM_X11_KHR
69#define EGL_PLATFORM_X11_KHR 0x31D5
77#ifndef EGL_WL_bind_wayland_display
85#define MYERRCODE(x) case x: return #x;
184 qCDebug(qLcWaylandCompositorHardwareIntegration)
206 qCWarning(qLcWaylandCompositorHardwareIntegration)
208 <<
"Looks like deleteOrphanedTextures() and this function where called simultaneously!"
209 <<
"This might cause issues!";
222 qCDebug(qLcWaylandCompositorHardwareIntegration)
224 <<
"texture deleted due to QOpenGLContext::aboutToBeDestroyed!"
225 <<
"Pointer (now dead) was:" << (
void*)
texture;
230 bool localContextNeeded =
false;
244 localContextNeeded =
true;
247 return localContextNeeded;
260 qCDebug(qLcWaylandCompositorHardwareIntegration)
262 <<
"(eglstream) creating a cleanup-lambda for QOpenGLContext::aboutToBeDestroyed!"
263 <<
", texture: " << bs->
textures[plane]
270 QMutexLocker locker(&bs->texturesLock);
274 if (bs->textures[plane] == nullptr)
277 delete bs->textures[plane];
279 qCDebug(qLcWaylandCompositorHardwareIntegration)
281 <<
"texture deleted due to QOpenGLContext::aboutToBeDestroyed!"
282 <<
"Pointer (now dead) was:" << (void*)(bs->textures[plane])
283 <<
" Associated context (about to die too) is: " << (void*)(bs->texturesContext[plane]);
285 bs->textures[plane] = nullptr;
286 bs->texturesContext[plane] = nullptr;
288 QObject::disconnect(bs->texturesAboutToBeDestroyedConnection[plane]);
289 bs->texturesAboutToBeDestroyedConnection[plane] = QMetaObject::Connection();
298 state.isYInverted =
false;
314 qWarning(
"%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x",
Q_FUNC_INFO, __LINE__, eglGetError());
329 if (usingLocalContext)
333 EGLint code = eglGetError();
356 qWarning(
"%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x",
Q_FUNC_INFO, __LINE__, eglGetError());
359 if (usingLocalContext)
373 if (
d->egl_unbind_wayland_display !=
nullptr &&
d->display_bound) {
375 if (!
d->egl_unbind_wayland_display(
d->egl_display,
d->wlDisplay))
376 qCWarning(qLcWaylandCompositorHardwareIntegration) <<
"eglUnbindWaylandDisplayWL failed";
396 const bool ignoreBindDisplay = !
qgetenv(
"QT_WAYLAND_IGNORE_BIND_DISPLAY").
isEmpty();
399 if (!nativeInterface) {
400 qWarning(
"QtCompositor: Failed to initialize EGL display. No native platform interface available.");
405 if (!
d->egl_display) {
406 qWarning(
"QtCompositor: Failed to initialize EGL display. Could not get EglDisplay for window.");
410 const char *extensionString = eglQueryString(
d->egl_display, EGL_EXTENSIONS);
411 if ((!extensionString || !strstr(extensionString,
"EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) {
412 qWarning(
"QtCompositor: Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension.");
416 d->egl_bind_wayland_display =
reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL
>(eglGetProcAddress(
"eglBindWaylandDisplayWL"));
417 d->egl_unbind_wayland_display =
reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL
>(eglGetProcAddress(
"eglUnbindWaylandDisplayWL"));
418 if ((!
d->egl_bind_wayland_display || !
d->egl_unbind_wayland_display) && !ignoreBindDisplay) {
419 qWarning(
"QtCompositor: Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL.");
423 d->egl_query_wayland_buffer =
reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL_compat
>(eglGetProcAddress(
"eglQueryWaylandBufferWL"));
424 if (!
d->egl_query_wayland_buffer) {
425 qWarning(
"QtCompositor: Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL.");
429 if (
d->egl_bind_wayland_display &&
d->egl_unbind_wayland_display) {
430 d->display_bound =
d->egl_bind_wayland_display(
d->egl_display,
display);
431 if (!
d->display_bound)
432 qCDebug(qLcWaylandCompositorHardwareIntegration) <<
"Wayland display already bound by other client buffer integration.";
440 d->funcs->initialize(
d->egl_display);
445 if (wl_shm_buffer_get(
buffer))
454 , m_integration(integration)
460 p->egl_query_wayland_buffer(
p->egl_display,
buffer, EGL_WIDTH, &
width);
461 p->egl_query_wayland_buffer(
p->egl_display,
buffer, EGL_HEIGHT, &
height);
472 p->funcs->destroy_stream(
p->egl_display, d->
egl_stream);
476 for (
int i=0;
i<3;
i++) {
479 qCDebug(qLcWaylandCompositorHardwareIntegration)
517 p->deleteOrphanedTextures();
527 ClientBuffer::setCommitted(damage);
529 p->handleEglstreamTexture(
this);
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()
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.
@ BufferFormatEgl_EXTERNAL_OES
static QWaylandCompositorPrivate * get(QWaylandCompositor *compositor)
QtWayland::BufferManager * bufferManager() const
Origin
This enum type is used to specify the origin of a QWaylandSurface's buffer.
void registerBuffer(struct ::wl_resource *buffer_resource, ClientBuffer *clientBuffer)
QWaylandCompositor * m_compositor
struct::wl_resource * m_buffer
QOffscreenSurface * offscreenSurface
void deleteGLTextureWhenPossible(QOpenGLTexture *texture, QOpenGLContext *ctx)
void deleteSpecificOrphanedTexture(QOpenGLTexture *texture)
WaylandEglStreamController * eglStreamController
QOpenGLContext * localContext
WaylandEglStreamClientBufferIntegrationPrivate()=default
bool initEglStream(WaylandEglStreamClientBuffer *buffer, struct ::wl_resource *bufferHandle)
PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display
QMutex orphanedTexturesLock
PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display
void setupBufferAndCleanup(BufferState *bs, QOpenGLTexture *texture, int plane)
void handleEglstreamTexture(WaylandEglStreamClientBuffer *buffer)
QList< QMetaObject::Connection > orphanedTexturesAboutToBeDestroyedConnection
PFNEGLQUERYWAYLANDBUFFERWL_compat egl_query_wayland_buffer
QEGLStreamConvenience * funcs
void deleteOrphanedTextures()
static WaylandEglStreamClientBufferIntegrationPrivate * get(WaylandEglStreamClientBufferIntegration *integration)
QList< QOpenGLTexture * > orphanedTextures
void initializeHardware(struct ::wl_display *display) override
void attachEglStreamConsumer(struct ::wl_resource *wl_surface, struct ::wl_resource *wl_buffer)
QtWayland::ClientBuffer * createBufferFor(wl_resource *buffer) override
WaylandEglStreamClientBufferIntegration()
~WaylandEglStreamClientBufferIntegration() override
QOpenGLTexture * toOpenGlTexture(int plane) override
QWaylandSurface::Origin origin() const override
~WaylandEglStreamClientBuffer() override
void setCommitted(QRegion &damage) override
QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const override
QSize size() const 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.
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,...)
GLint GLsizei GLsizei height
GLuint const GLuint GLuint const GLuint * textures
GLintptr GLsizeiptr GLeglClientBufferEXT clientBuffer
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
QMetaObject::Connection texturesAboutToBeDestroyedConnection[3]
QOpenGLContext * texturesContext[3]
QOpenGLTexture * textures[3]
qsizetype indexOf(const AT &t, qsizetype from=0) const noexcept
#define EGL_TEXTURE_EXTERNAL_WL
QT_BEGIN_NAMESPACE typedef struct wl_resource EGLint attribute
static const char * egl_error_string(EGLint code)
QT_BEGIN_NAMESPACE typedef EGLBoolean(EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL_compat)(EGLDisplay dpy
#define EGL_WAYLAND_BUFFER_WL
struct wl_display * display
QT_BEGIN_NAMESPACE typedef struct wl_resource * buffer
QT_BEGIN_NAMESPACE typedef struct wl_resource EGLint EGLint * value
#define GL_TEXTURE_EXTERNAL_OES
#define EGL_WAYLAND_EGLSTREAM_WL