6#include <QtWaylandCompositor/QWaylandCompositor>
7#include <QtWaylandCompositor/private/qwltextureorphanage_p.h>
8#include <qpa/qplatformnativeinterface.h>
9#include <QtOpenGL/QOpenGLTexture>
10#include <QtGui/QGuiApplication>
11#include <QtGui/QOpenGLContext>
12#include <QtGui/QOffscreenSurface>
13#include <qpa/qplatformscreen.h>
14#include <QtGui/QWindow>
15#include <QtCore/QPointer>
19#include <QMutexLocker>
20#include <QVarLengthArray>
21#include <QtCore/private/qcore_unix_p.h>
22#include <QtGui/private/qeglstreamconvenience_p.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
75#ifndef EGL_WL_bind_wayland_display
85#ifndef GL_OES_EGL_image
95#define MYERRCODE(x) case x: return #x;
201 qCWarning(qLcWaylandCompositorHardwareIntegration)
202 <<
"BindTextureToBuffer() failed. Could not find glEGLImageTargetTexture2DOES.";
210#if defined(EGL_WAYLAND_Y_INVERTED_WL)
216 state.isYInverted = (
ret == EGL_FALSE || isYInverted == EGL_TRUE);
239 for (
int i = 0;
i < planes;
i++) {
241#ifdef EGL_EXT_protected_content
242 if (
buffer->isProtected()) {
243 attribs[2] = EGL_PROTECTED_CONTENT_EXT;
251 buffer->waylandBufferHandle(),
254 if (
image == EGL_NO_IMAGE_KHR) {
255 qCWarning(qLcWaylandCompositorHardwareIntegration)
256 <<
"Failed to create EGL image for plane" <<
i;
262 state.textures[
i] =
nullptr;
268 bool localContextNeeded =
false;
282 localContextNeeded =
true;
285 return localContextNeeded;
296 Q_ASSERT(bs->texturesContext[plane] !=
nullptr);
298 qCDebug(qLcWaylandCompositorHardwareIntegration)
300 <<
"(egl) creating a cleanup-lambda for QOpenGLContext::aboutToBeDestroyed!"
301 <<
", texture: " << bs->textures[plane]
302 <<
", ctx: " << (
void*)bs->texturesContext[plane];
304 bs->texturesAboutToBeDestroyedConnection[plane] =
306 bs->texturesContext[plane], [bs, plane]() {
308 QMutexLocker locker(&bs->texturesLock);
312 if (bs->textures[plane] == nullptr)
315 delete bs->textures[plane];
317 qCDebug(qLcWaylandCompositorHardwareIntegration)
319 <<
"texture deleted due to QOpenGLContext::aboutToBeDestroyed!"
320 <<
"Pointer (now dead) was:" << (void*)(bs->textures[plane])
321 <<
" Associated context (about to die too) is: " << (void*)(bs->texturesContext[plane]);
323 bs->textures[plane] = nullptr;
324 bs->texturesContext[plane] = nullptr;
326 QObject::disconnect(bs->texturesAboutToBeDestroyedConnection[plane]);
327 bs->texturesAboutToBeDestroyedConnection[plane] = QMetaObject::Connection();
336 state.isYInverted =
false;
352 qCWarning(qLcWaylandCompositorHardwareIntegration,
"%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x",
Q_FUNC_INFO, __LINE__, eglGetError());
358 qCWarning(qLcWaylandCompositorHardwareIntegration)
359 <<
"EglClientBufferIntegration: creating texture with no current context";
367 qCDebug(qLcWaylandCompositorHardwareIntegration)
368 <<
" NEW texture! It's pointer and ctx pointer: "
369 << (
void*)
state.textures[0] <<
"; " << (
void*)
state.texturesContext[0];
375 EGLint code = eglGetError();
404 qCWarning(qLcWaylandCompositorHardwareIntegration,
405 "%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x",
Q_FUNC_INFO, __LINE__,
409 if (usingLocalContext)
422 if (
d->egl_unbind_wayland_display &&
d->display_bound) {
424 if (!
d->egl_unbind_wayland_display(
d->egl_display,
d->wlDisplay))
425 qCWarning(qLcWaylandCompositorHardwareIntegration) <<
"eglUnbindWaylandDisplayWL failed";
433 const bool ignoreBindDisplay = !
qgetenv(
"QT_WAYLAND_IGNORE_BIND_DISPLAY").isEmpty();
436 if (!nativeInterface) {
437 qCWarning(qLcWaylandCompositorHardwareIntegration)
438 <<
"Failed to initialize EGL display. No native platform interface available.";
443 if (!
d->egl_display) {
444 qCWarning(qLcWaylandCompositorHardwareIntegration)
445 <<
"Failed to initialize EGL display. Could not get EglDisplay for window.";
449 const char *extensionString = eglQueryString(
d->egl_display, EGL_EXTENSIONS);
450 if ((!extensionString || !strstr(extensionString,
"EGL_WL_bind_wayland_display")) && !ignoreBindDisplay) {
451 qCWarning(qLcWaylandCompositorHardwareIntegration)
452 <<
"Failed to initialize EGL display. There is no EGL_WL_bind_wayland_display extension.";
456 d->egl_bind_wayland_display =
reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL
>(eglGetProcAddress(
"eglBindWaylandDisplayWL"));
457 d->egl_unbind_wayland_display =
reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL
>(eglGetProcAddress(
"eglUnbindWaylandDisplayWL"));
458 if ((!
d->egl_bind_wayland_display || !
d->egl_unbind_wayland_display) && !ignoreBindDisplay) {
459 qCWarning(qLcWaylandCompositorHardwareIntegration)
460 <<
"Failed to initialize EGL display. Could not find eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL.";
464 d->egl_query_wayland_buffer =
reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL_compat
>(eglGetProcAddress(
"eglQueryWaylandBufferWL"));
465 if (!
d->egl_query_wayland_buffer) {
466 qCWarning(qLcWaylandCompositorHardwareIntegration)
467 <<
"Failed to initialize EGL display. Could not find eglQueryWaylandBufferWL.";
471 d->egl_create_image =
reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC
>(eglGetProcAddress(
"eglCreateImageKHR"));
472 d->egl_destroy_image =
reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC
>(eglGetProcAddress(
"eglDestroyImageKHR"));
473 if (!
d->egl_create_image || !
d->egl_destroy_image) {
474 qCWarning(qLcWaylandCompositorHardwareIntegration)
475 <<
"Failed to initialize EGL display. Could not find eglCreateImageKHR and eglDestroyImageKHR.";
479 if (
d->egl_bind_wayland_display &&
d->egl_unbind_wayland_display) {
480 d->display_bound =
d->egl_bind_wayland_display(
d->egl_display,
display);
481 if (!
d->display_bound)
482 qCDebug(qLcWaylandCompositorHardwareIntegration) <<
"Wayland display already bound by other client buffer integration.";
494 bool q =
d->egl_query_wayland_buffer(
d->egl_display,
buffer, EGL_WIDTH, &
w);
502 , m_integration(integration)
508 p->egl_query_wayland_buffer(
p->egl_display,
buffer, EGL_WIDTH, &
width);
509 p->egl_query_wayland_buffer(
p->egl_display,
buffer, EGL_HEIGHT, &
height);
523 p->egl_destroy_image(
p->egl_display,
image);
526 p->funcs->destroy_stream(
p->egl_display, d->
egl_stream);
533 for (
int i=0;
i<3;
i++) {
536 qCDebug(qLcWaylandCompositorHardwareIntegration)
609 p->setupBufferAndCleanup(this->d,
texture, plane);
615 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
617#ifdef GL_EXT_protected_textures
627 ClientBuffer::setCommitted(damage);
669 p->egl_destroy_image(
p->egl_display,
image);
void initialize(EGLDisplay dpy)
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()
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.
void bind()
Binds this texture to the currently active texture unit ready for rendering.
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
static QWaylandTextureOrphanage * instance()
void handleEglstreamTexture(WaylandEglClientBuffer *buffer, wl_resource *bufferHandle)
QOpenGLContext * localContext
static WaylandEglClientBufferIntegrationPrivate * get(WaylandEglClientBufferIntegration *integration)
PFNEGLCREATEIMAGEKHRPROC egl_create_image
PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image
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)
QEGLStreamConvenience * funcs
void registerBuffer(struct ::wl_resource *buffer, BufferState state)
void setupBufferAndCleanup(BufferState *bs, QOpenGLTexture *texture, int plane)
PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display
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
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]
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