summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/wayland/qwindow-compositor/qwindowcompositor.cpp17
-rw-r--r--examples/wayland/qwindow-compositor/textureblitter.cpp51
-rw-r--r--examples/wayland/qwindow-compositor/textureblitter.h6
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.cpp12
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.h2
-rw-r--r--src/compositor/hardware_integration/qwlclientbufferintegration_p.h23
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp32
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h2
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp269
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h9
-rw-r--r--src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro2
11 files changed, 369 insertions, 56 deletions
diff --git a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp
index 5d338692f..4e3f6336b 100644
--- a/examples/wayland/qwindow-compositor/qwindowcompositor.cpp
+++ b/examples/wayland/qwindow-compositor/qwindowcompositor.cpp
@@ -92,8 +92,10 @@ public:
shmTex = new QOpenGLTexture(bufferRef.image(), QOpenGLTexture::DontGenerateMipMaps);
shmTex->setWrapMode(QOpenGLTexture::ClampToEdge);
texture = shmTex->textureId();
+ textureTarget = GL_TEXTURE_2D;
} else {
texture = bufferRef.createTexture();
+ textureTarget = bufferRef.textureTarget();
}
}
}
@@ -112,9 +114,16 @@ public:
return bufferRef.image();
}
+ void updateTexture()
+ {
+ if (bufferRef)
+ bufferRef.updateTexture();
+ }
+
QOpenGLTexture *shmTex;
QWaylandBufferRef bufferRef;
GLuint texture;
+ GLenum textureTarget;
};
QWindowCompositor::QWindowCompositor(CompositorWindow *window)
@@ -326,7 +335,7 @@ void QWindowCompositor::render()
if (!m_backgroundTexture)
m_backgroundTexture = new QOpenGLTexture(m_backgroundImage, QOpenGLTexture::DontGenerateMipMaps);
- m_textureBlitter->bind();
+ m_textureBlitter->bind(GL_TEXTURE_2D);
// Draw the background image texture
m_textureBlitter->drawTexture(m_backgroundTexture->textureId(),
QRect(QPoint(0, 0), m_backgroundImage.size()),
@@ -336,7 +345,11 @@ void QWindowCompositor::render()
foreach (QWaylandSurface *surface, m_surfaces) {
if (!surface->visible())
continue;
- GLuint texture = static_cast<BufferAttacher *>(surface->bufferAttacher())->texture;
+ BufferAttacher *ba = static_cast<BufferAttacher *>(surface->bufferAttacher());
+ ba->updateTexture();
+ const GLuint texture = ba->texture;
+ const GLenum target = ba->textureTarget;
+ m_textureBlitter->bind(target);
foreach (QWaylandSurfaceView *view, surface->views()) {
QRect geo(view->pos().toPoint(),surface->size());
m_textureBlitter->drawTexture(texture,geo,m_window->size(),0,false,surface->isYInverted());
diff --git a/examples/wayland/qwindow-compositor/textureblitter.cpp b/examples/wayland/qwindow-compositor/textureblitter.cpp
index a9acfc026..c550985de 100644
--- a/examples/wayland/qwindow-compositor/textureblitter.cpp
+++ b/examples/wayland/qwindow-compositor/textureblitter.cpp
@@ -48,6 +48,9 @@ QT_BEGIN_NAMESPACE
TextureBlitter::TextureBlitter()
: m_shaderProgram(new QOpenGLShaderProgram)
+ , m_shaderProgramExternal(new QOpenGLShaderProgram)
+ , m_currentProgram(0)
+ , m_currentTarget(GL_TEXTURE_2D)
{
static const char *textureVertexProgram =
"uniform highp mat4 matrix;\n"
@@ -66,33 +69,58 @@ TextureBlitter::TextureBlitter()
" gl_FragColor = texture2D(texture, textureCoord);\n"
"}\n";
- //Enable transparent windows
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ static const char *textureFragmentProgramExternal =
+ "#extension GL_OES_EGL_image_external : require\n"
+ "uniform samplerExternalOES texture;\n"
+ "varying highp vec2 textureCoord;\n"
+ "void main() {\n"
+ " gl_FragColor = texture2D(texture, textureCoord);\n"
+ "}\n";
m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
m_shaderProgram->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
m_shaderProgram->link();
+
+ m_shaderProgramExternal->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+ m_shaderProgramExternal->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgramExternal);
+ m_shaderProgramExternal->link();
}
TextureBlitter::~TextureBlitter()
{
delete m_shaderProgram;
+ delete m_shaderProgramExternal;
}
-void TextureBlitter::bind()
+void TextureBlitter::bind(quint32 target)
{
+ m_currentTarget = target;
+ switch (target) {
+ case GL_TEXTURE_2D:
+ m_currentProgram = m_shaderProgram;
+ break;
+ case GL_TEXTURE_EXTERNAL_OES:
+ m_currentProgram = m_shaderProgramExternal;
+ break;
+ default:
+ qFatal("INVALID TARGET TYPE %d", target);
+ break;
+ }
- m_shaderProgram->bind();
+ m_currentProgram->bind();
m_vertexCoordEntry = m_shaderProgram->attributeLocation("vertexCoordEntry");
m_textureCoordEntry = m_shaderProgram->attributeLocation("textureCoordEntry");
m_matrixLocation = m_shaderProgram->uniformLocation("matrix");
+
+ //Enable transparent windows
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void TextureBlitter::release()
{
- m_shaderProgram->release();
+ m_currentProgram->release();
}
void TextureBlitter::drawTexture(int textureId, const QRectF &targetRect, const QSize &targetSize, int depth, bool targethasInvertedY, bool sourceHasInvertedY)
@@ -148,16 +176,17 @@ void TextureBlitter::drawTexture(int textureId, const QRectF &targetRect, const
currentContext->functions()->glVertexAttribPointer(m_vertexCoordEntry, 3, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
currentContext->functions()->glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
- m_shaderProgram->setUniformValue(m_matrixLocation, m_transformMatrix);
- glBindTexture(GL_TEXTURE_2D, textureId);
+ m_currentProgram->setUniformValue(m_matrixLocation, m_transformMatrix);
+
+ glBindTexture(m_currentTarget, textureId);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(m_currentTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(m_currentTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- glBindTexture(GL_TEXTURE_2D, 0);
+ glBindTexture(m_currentTarget, 0);
currentContext->functions()->glDisableVertexAttribArray(m_vertexCoordEntry);
currentContext->functions()->glDisableVertexAttribArray(m_textureCoordEntry);
diff --git a/examples/wayland/qwindow-compositor/textureblitter.h b/examples/wayland/qwindow-compositor/textureblitter.h
index b46d354e0..85e2bbfb4 100644
--- a/examples/wayland/qwindow-compositor/textureblitter.h
+++ b/examples/wayland/qwindow-compositor/textureblitter.h
@@ -51,7 +51,7 @@ class TextureBlitter
public:
TextureBlitter();
~TextureBlitter();
- void bind();
+ void bind(quint32 target);
void release();
void drawTexture(int textureId, const QRectF &sourceGeometry,
const QSize &targetRect, int depth,
@@ -59,11 +59,15 @@ public:
private:
QOpenGLShaderProgram *m_shaderProgram;
+ QOpenGLShaderProgram *m_shaderProgramExternal;
+ QOpenGLShaderProgram *m_currentProgram;
QMatrix4x4 m_transformMatrix;
int m_matrixLocation;
int m_vertexCoordEntry;
int m_textureCoordEntry;
+
+ quint32 m_currentTarget;
};
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp
index abea24afb..894f50a1c 100644
--- a/src/compositor/compositor_api/qwaylandbufferref.cpp
+++ b/src/compositor/compositor_api/qwaylandbufferref.cpp
@@ -104,6 +104,12 @@ QImage QWaylandBufferRef::image() const
#ifdef QT_COMPOSITOR_WAYLAND_GL
+GLenum QWaylandBufferRef::textureTarget() const
+{
+ Q_ASSERT(d->buffer->textureCreated());
+ return d->buffer->textureTarget();
+}
+
GLuint QWaylandBufferRef::createTexture()
{
if (!d->buffer->isShmBuffer() && !d->buffer->textureCreated()) {
@@ -112,6 +118,12 @@ GLuint QWaylandBufferRef::createTexture()
return d->buffer->texture();
}
+void QWaylandBufferRef::updateTexture()
+{
+ if (!d->buffer->isShmBuffer() && d->buffer->textureCreated())
+ d->buffer->updateTexture();
+}
+
void QWaylandBufferRef::destroyTexture()
{
if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) {
diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h
index 103a1b388..0a5f6cd85 100644
--- a/src/compositor/compositor_api/qwaylandbufferref.h
+++ b/src/compositor/compositor_api/qwaylandbufferref.h
@@ -69,6 +69,8 @@ public:
* referring to the same underlying buffer will be destroyed or reset.
*/
GLuint createTexture();
+ GLenum textureTarget() const;
+ void updateTexture();
void destroyTexture();
void *nativeBuffer() const;
#endif
diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
index e4bbb45b9..c19b90309 100644
--- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
+++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
@@ -75,14 +75,29 @@ public:
virtual void initializeHardware(QtWayland::Display *waylandDisplay) = 0;
- // Used when the hardware integration wants to provide its own texture for a given buffer.
- // In most cases the compositor creates and manages the texture so this is not needed.
- virtual GLuint textureForBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); return 0; }
- virtual void destroyTextureForBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); }
+ virtual void initialize(struct ::wl_resource *buffer) { Q_UNUSED(buffer); }
+
+ virtual GLenum textureTargetForBuffer(struct ::wl_resource *buffer) const { Q_UNUSED(buffer); return GL_TEXTURE_2D; }
+
+ virtual GLuint textureForBuffer(struct ::wl_resource *buffer) {
+ Q_UNUSED(buffer);
+ GLuint texture;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ return texture;
+ }
+
+ virtual void destroyTextureForBuffer(struct ::wl_resource *buffer, GLuint texture)
+ {
+ Q_UNUSED(buffer);
+ glDeleteTextures(1, &texture);
+ }
// Called with the texture bound.
virtual void bindTextureToBuffer(struct ::wl_resource *buffer) = 0;
+ virtual void updateTextureForBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); }
+
virtual bool isYInverted(struct ::wl_resource *) const { return true; }
virtual void *lockNativeBuffer(struct ::wl_resource *) const { return 0; }
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
index 066ffd15b..1229d286f 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
+++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
@@ -99,8 +99,12 @@ void SurfaceBuffer::initialize(struct ::wl_resource *buffer)
m_size = QSize();
m_destroy_listener.surfaceBuffer = this;
m_destroy_listener.listener.notify = destroy_listener_callback;
- if (buffer)
+ if (buffer) {
+ ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration();
+ hwIntegration->unlockNativeBuffer(m_handle);
+ hwIntegration->initialize(buffer);
wl_signal_add(&buffer->destroy_signal, &m_destroy_listener.listener);
+ }
}
void SurfaceBuffer::destructBufferState()
@@ -186,12 +190,22 @@ void SurfaceBuffer::destroyTexture()
if (hwIntegration->textureForBuffer(m_buffer) == 0)
glDeleteTextures(1, &m_texture);
else
- hwIntegration->destroyTextureForBuffer(m_buffer);
+ hwIntegration->destroyTextureForBuffer(m_buffer, m_texture);
m_texture = 0;
}
#endif
}
+uint SurfaceBuffer::textureTarget() const
+{
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration();
+ return hwIntegration->textureTargetForBuffer(m_buffer);
+#endif
+
+ return 0;
+}
+
void SurfaceBuffer::handleAboutToBeDisplayed()
{
qDebug() << Q_FUNC_INFO;
@@ -264,17 +278,21 @@ void SurfaceBuffer::createTexture()
ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration();
#ifdef QT_COMPOSITOR_WAYLAND_GL
- if (!m_texture)
- m_texture = hwIntegration->textureForBuffer(m_buffer);
- if (!m_texture)
- glGenTextures(1, &m_texture);
- glBindTexture(GL_TEXTURE_2D, m_texture);
+ m_texture = hwIntegration->textureForBuffer(m_buffer);
hwIntegration->bindTextureToBuffer(m_buffer);
#else
Q_UNUSED(hwIntegration);
#endif
}
+void SurfaceBuffer::updateTexture()
+{
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration();
+ hwIntegration->updateTextureForBuffer(m_buffer);
+#endif
+}
+
bool SurfaceBuffer::isYInverted() const
{
bool ret = false;
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
index 5d09c5a9f..3401d218b 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
+++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
@@ -106,6 +106,8 @@ public:
bool isDestroyed() { return m_destroyed; }
void createTexture();
+ uint textureTarget() const;
+ void updateTexture();
#ifdef QT_COMPOSITOR_WAYLAND_GL
inline GLuint texture() const;
#else
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
index 2d5a182c7..e28d2f53e 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
@@ -48,11 +48,16 @@
#include <qpa/qplatformscreen.h>
#include <QtGui/QWindow>
#include <QtCore/QPointer>
-
#include <QDebug>
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
+#include <QMutex>
+#include <QMutexLocker>
+#include <QtCore/private/qcore_unix_p.h>
+#include <QtPlatformSupport/private/qeglstreamconvenience_p.h>
+
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#endif
/* Needed for compatibility with Mesa older than 10.0. */
typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL_compat) (EGLDisplay dpy, struct wl_resource *buffer, EGLint attribute, EGLint *value);
@@ -74,6 +79,28 @@ typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenu
QT_BEGIN_NAMESPACE
+struct BufferState
+{
+ BufferState()
+ : gl_texture(0)
+ , gl_texture_target(GL_TEXTURE_2D)
+ , egl_stream(EGL_NO_STREAM_KHR)
+ , isYInverted(true)
+ {}
+
+ GLuint gl_texture;
+ GLenum gl_texture_target;
+ EGLStreamKHR egl_stream;
+ bool isYInverted;
+ QSize size;
+};
+
+struct buffer_destroy_listener
+{
+ struct wl_listener listener;
+ class WaylandEglClientBufferIntegrationPrivate *d;
+};
+
class WaylandEglClientBufferIntegrationPrivate
{
public:
@@ -87,10 +114,40 @@ public:
, egl_create_image(0)
, egl_destroy_image(0)
, gl_egl_image_target_texture_2d(0)
- { }
+ , funcs(Q_NULLPTR)
+ {
+ destroy_listener.d = this;
+ destroy_listener.listener.notify = destroy_listener_callback;
+ }
+
+ static void destroy_listener_callback(wl_listener *listener, void *data) {
+ static QMutex mutex;
+ QMutexLocker locker(&mutex);
+
+ buffer_destroy_listener *destroy_listener = reinterpret_cast<buffer_destroy_listener *>(listener);
+ WaylandEglClientBufferIntegrationPrivate *self = destroy_listener->d;
+ struct ::wl_resource *buffer = static_cast<struct ::wl_resource *>(data);
+ if (!self->buffers.contains(buffer))
+ return;
+
+ Q_ASSERT(self);
+ Q_ASSERT(buffer);
+
+ BufferState state = self->buffers.take(buffer);
+
+ if (state.gl_texture != 0)
+ glDeleteTextures(1, &state.gl_texture);
+
+ if (state.egl_stream != EGL_NO_STREAM_KHR)
+ self->funcs->destroy_stream(self->egl_display, state.egl_stream);
+ }
+
EGLDisplay egl_display;
bool valid;
bool display_bound;
+ QHash<struct ::wl_resource *, BufferState> buffers;
+ buffer_destroy_listener destroy_listener;
+
PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display;
PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display;
PFNEGLQUERYWAYLANDBUFFERWL_compat egl_query_wayland_buffer;
@@ -99,6 +156,8 @@ public:
PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image;
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d;
+
+ QEGLStreamConvenience *funcs;
};
WaylandEglClientBufferIntegration::WaylandEglClientBufferIntegration()
@@ -163,51 +222,193 @@ void WaylandEglClientBufferIntegration::initializeHardware(QtWayland::Display *w
}
}
+ d->funcs = new QEGLStreamConvenience;
+ d->funcs->initialize(d->egl_display);
+
d->valid = true;
}
-void WaylandEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
+static GLuint make_texture(GLenum target)
+{
+ GLuint texture;
+
+ glGenTextures(1, &texture);
+ glBindTexture(target, texture);
+
+ return texture;
+}
+
+static void set_texture_params(GLenum target)
+{
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+void WaylandEglClientBufferIntegration::initialize(struct ::wl_resource *buffer)
+{
+ Q_D(WaylandEglClientBufferIntegration);
+
+ if (wl_shm_buffer_get(buffer))
+ return;
+
+ if (!buffer || d->buffers.contains(buffer))
+ return;
+
+ wl_signal_add(&buffer->destroy_signal, &d->destroy_listener.listener);
+}
+
+GLenum WaylandEglClientBufferIntegration::textureTargetForBuffer(struct ::wl_resource *buffer) const
+{
+ Q_D(const WaylandEglClientBufferIntegration);
+
+ return d->buffers.value(buffer).gl_texture_target;
+}
+
+GLuint WaylandEglClientBufferIntegration::textureForBuffer(struct ::wl_resource *buffer)
+{
+ Q_D(WaylandEglClientBufferIntegration);
+
+ if (!buffer)
+ return 0;
+
+ BufferState state = d->buffers.value(buffer);
+
+ if (state.gl_texture != 0) {
+ glBindTexture(state.gl_texture_target, state.gl_texture);
+ return state.gl_texture;
+ }
+
+ EGLint format;
+ EGLNativeFileDescriptorKHR streamFd = EGL_NO_FILE_DESCRIPTOR_KHR;
+
+ EGLint width, height;
+ d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WIDTH, &width);
+ d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_HEIGHT, &height);
+ state.size = QSize(width, height);
+
+#if defined(EGL_WAYLAND_Y_INVERTED_WL)
+ EGLint isYInverted;
+ EGLBoolean ret = d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WAYLAND_Y_INVERTED_WL, &isYInverted);
+ // Yes, this looks strange, but the specification says that EGL_FALSE return
+ // value (not supported) should be treated the same as EGL_TRUE return value
+ // and EGL_TRUE in value.
+ state.isYInverted = (ret == EGL_FALSE || isYInverted == EGL_TRUE);
+#endif
+
+ if (d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_TEXTURE_FORMAT, &format)) {
+ state.gl_texture_target = GL_TEXTURE_2D;
+ state.gl_texture = make_texture(state.gl_texture_target);
+ } else if (d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WAYLAND_BUFFER_WL, &streamFd)) {
+ state.egl_stream = d->funcs->create_stream_from_file_descriptor(d->egl_display, streamFd);
+ close(streamFd);
+
+ if (state.egl_stream == EGL_NO_STREAM_KHR) {
+ qWarning("%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
+ return 0;
+ }
+
+ state.isYInverted = false;
+ state.gl_texture_target = GL_TEXTURE_EXTERNAL_OES;
+ state.gl_texture = make_texture(state.gl_texture_target);
+ set_texture_params(state.gl_texture_target);
+
+ if (d->funcs->stream_consumer_gltexture(d->egl_display, state.egl_stream) != EGL_TRUE)
+ qWarning("%s:%d: eglStreamConsumerGLTextureExternalKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
+ }
+
+ d->buffers[buffer] = state;
+ return state.gl_texture;
+}
+
+void WaylandEglClientBufferIntegration::destroyTextureForBuffer(struct ::wl_resource *buffer, GLuint texture)
{
Q_D(WaylandEglClientBufferIntegration);
+ Q_UNUSED(texture);
+ if (!buffer || !d->buffers.contains(buffer))
+ return;
+
+ BufferState &state = d->buffers[buffer];
+
+ if (state.egl_stream != EGL_NO_STREAM_KHR)
+ return;
+
+ if (state.gl_texture != 0) {
+ glDeleteTextures(1, &state.gl_texture);
+ state.gl_texture = 0;
+ }
+}
+
+void WaylandEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
+{
+ Q_D(WaylandEglClientBufferIntegration);
if (!d->valid) {
qWarning("QtCompositor: bindTextureToBuffer() failed");
return;
}
- // Vivante drivers on the iMX6 don't resolve this function early enough for us, they seem to require the EGL/GLES setup to be further
- // along than they are in initializeHardware(), so do the lookup here instead.
- if (!d->gl_egl_image_target_texture_2d)
- d->gl_egl_image_target_texture_2d = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
-
- if (!d->gl_egl_image_target_texture_2d) {
- qWarning("QtCompositor: bindTextureToBuffer() failed. Could not find glEGLImageTargetTexture2DOES.");
+ if (!buffer)
return;
+
+ const BufferState state = d->buffers.value(buffer);
+
+ if (state.egl_stream != EGL_NO_STREAM_KHR) {
+ d->funcs->stream_consumer_acquire(d->egl_display, state.egl_stream);
+ } else {
+ Q_ASSERT(QOpenGLContext::currentContext());
+
+ // Resolving GL functions may need a context current, so do it only here.
+ if (!d->gl_egl_image_target_texture_2d)
+ d->gl_egl_image_target_texture_2d = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
+
+ if (!d->gl_egl_image_target_texture_2d) {
+ qWarning("QtCompositor: bindTextureToBuffer() failed. Could not find glEGLImageTargetTexture2DOES.");
+ return;
+ }
+
+ EGLImageKHR image = d->egl_create_image(d->egl_display, EGL_NO_CONTEXT,
+ EGL_WAYLAND_BUFFER_WL,
+ buffer, NULL);
+
+ d->gl_egl_image_target_texture_2d(GL_TEXTURE_2D, image);
+ set_texture_params(GL_TEXTURE_2D);
+ d->egl_destroy_image(d->egl_display, image);
}
+}
- EGLImageKHR image = d->egl_create_image(d->egl_display, EGL_NO_CONTEXT,
- EGL_WAYLAND_BUFFER_WL,
- buffer, NULL);
+// Update is only needed for the EGLStream path as that requires calling acquire
+// on every frame. bindTextureToBuffer() is typically invoked only upon attach
+// so that is insufficient.
+void WaylandEglClientBufferIntegration::updateTextureForBuffer(struct ::wl_resource *buffer)
+{
+ Q_D(WaylandEglClientBufferIntegration);
+ if (!d->valid) {
+ qWarning("QtCompositor: updateTextureForBuffer() failed");
+ return;
+ }
- d->gl_egl_image_target_texture_2d(GL_TEXTURE_2D, image);
+ if (!buffer)
+ return;
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ const BufferState state = d->buffers.value(buffer);
- d->egl_destroy_image(d->egl_display, image);
+ if (state.egl_stream != EGL_NO_STREAM_KHR)
+ d->funcs->stream_consumer_acquire(d->egl_display, state.egl_stream);
}
bool WaylandEglClientBufferIntegration::isYInverted(struct ::wl_resource *buffer) const
{
-#if defined(EGL_WAYLAND_Y_INVERTED_WL)
Q_D(const WaylandEglClientBufferIntegration);
+ if (d->buffers.contains(buffer))
+ return d->buffers[buffer].isYInverted;
+
+#if defined(EGL_WAYLAND_Y_INVERTED_WL)
EGLint isYInverted;
- EGLBoolean ret;
+ EGLBoolean ret = EGL_FALSE;
ret = d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WAYLAND_Y_INVERTED_WL, &isYInverted);
-
// Yes, this looks strange, but the specification says that EGL_FALSE return
// value (not supported) should be treated the same as EGL_TRUE return value
// and EGL_TRUE in value.
@@ -224,6 +425,9 @@ void *WaylandEglClientBufferIntegration::lockNativeBuffer(struct ::wl_resource *
{
Q_D(const WaylandEglClientBufferIntegration);
+ if (d->buffers.contains(buffer) && d->buffers[buffer].egl_stream != EGL_NO_STREAM_KHR)
+ return 0;
+
EGLImageKHR image = d->egl_create_image(d->egl_display, EGL_NO_CONTEXT,
EGL_WAYLAND_BUFFER_WL,
buffer, NULL);
@@ -233,8 +437,11 @@ void *WaylandEglClientBufferIntegration::lockNativeBuffer(struct ::wl_resource *
void WaylandEglClientBufferIntegration::unlockNativeBuffer(void *native_buffer) const
{
Q_D(const WaylandEglClientBufferIntegration);
- EGLImageKHR image = static_cast<EGLImageKHR>(native_buffer);
+ if (!native_buffer)
+ return;
+
+ EGLImageKHR image = static_cast<EGLImageKHR>(native_buffer);
d->egl_destroy_image(d->egl_display, image);
}
@@ -242,11 +449,15 @@ QSize WaylandEglClientBufferIntegration::bufferSize(struct ::wl_resource *buffer
{
Q_D(const WaylandEglClientBufferIntegration);
- int width, height;
- d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WIDTH, &width);
- d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_HEIGHT, &height);
+ if (d->buffers.contains(buffer)) {
+ return d->buffers[buffer].size;
+ } else {
+ int width, height;
+ d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_WIDTH, &width);
+ d->egl_query_wayland_buffer(d->egl_display, buffer, EGL_HEIGHT, &height);
- return QSize(width, height);
+ return QSize(width, height);
+ }
}
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
index 5f660e98a..c3f584835 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
@@ -56,7 +56,15 @@ public:
void initializeHardware(QtWayland::Display *waylandDisplay) Q_DECL_OVERRIDE;
+ void initialize(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
+
+ GLenum textureTargetForBuffer(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
+
+ GLuint textureForBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
+ void destroyTextureForBuffer(struct ::wl_resource *buffer, GLuint texture) Q_DECL_OVERRIDE;
+
void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
+ void updateTextureForBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
bool isYInverted(struct ::wl_resource *) const Q_DECL_OVERRIDE;
void *lockNativeBuffer(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
@@ -72,4 +80,3 @@ private:
QT_END_NAMESPACE
#endif // WAYLANDEGLINTEGRATION_H
-
diff --git a/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro b/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro
index 98977591d..c1a23cd64 100644
--- a/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro
+++ b/src/plugins/hardwareintegration/compositor/wayland-egl/wayland-egl.pro
@@ -1,7 +1,7 @@
PLUGIN_TYPE = wayland-graphics-integration-server
load(qt_plugin)
-QT = compositor compositor-private core-private gui-private
+QT = compositor compositor-private core-private gui-private platformsupport-private
OTHER_FILES += wayland-egl.json