summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/wayland/qwindow-compositor/compositorwindow.cpp10
-rw-r--r--examples/wayland/qwindow-compositor/windowcompositor.cpp33
-rw-r--r--examples/wayland/qwindow-compositor/windowcompositor.h3
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.cpp10
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.h3
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp64
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem_p.h5
-rw-r--r--src/compositor/hardware_integration/qwlclientbufferintegration_p.h1
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp8
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h1
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp51
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h1
12 files changed, 165 insertions, 25 deletions
diff --git a/examples/wayland/qwindow-compositor/compositorwindow.cpp b/examples/wayland/qwindow-compositor/compositorwindow.cpp
index 7e10a1739..537a3d08a 100644
--- a/examples/wayland/qwindow-compositor/compositorwindow.cpp
+++ b/examples/wayland/qwindow-compositor/compositorwindow.cpp
@@ -116,10 +116,18 @@ void CompositorWindow::paintGL()
functions->glEnable(GL_BLEND);
functions->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ GLenum currentTarget = GL_TEXTURE_2D;
Q_FOREACH (WindowCompositorView *view, m_compositor->views()) {
if (view->isCursor())
continue;
- GLuint textureId = view->getTexture();
+ GLenum target;
+ GLuint textureId = view->getTexture(&target);
+ if (!textureId || !target)
+ continue;
+ if (target != currentTarget) {
+ currentTarget = target;
+ m_textureBlitter.bind(currentTarget);
+ }
QWaylandSurface *surface = view->surface();
if (surface && surface->isMapped()) {
QSize s = surface->size();
diff --git a/examples/wayland/qwindow-compositor/windowcompositor.cpp b/examples/wayland/qwindow-compositor/windowcompositor.cpp
index bd39908e5..ecbbc5041 100644
--- a/examples/wayland/qwindow-compositor/windowcompositor.cpp
+++ b/examples/wayland/qwindow-compositor/windowcompositor.cpp
@@ -50,25 +50,42 @@
#include <QtWaylandCompositor/qwaylanddrag.h>
#include <QDebug>
+#include <QOpenGLContext>
+
+#ifndef GL_TEXTURE_EXTERNAL_OES
+#define GL_TEXTURE_EXTERNAL_OES 0x8D65
+#endif
WindowCompositorView::WindowCompositorView()
- : m_texture(0)
+ : m_textureTarget(GL_TEXTURE_2D)
+ , m_texture(0)
, m_wlShellSurface(nullptr)
, m_xdgSurface(nullptr)
, m_xdgPopup(nullptr)
, m_parentView(nullptr)
{}
-GLuint WindowCompositorView::getTexture() {
+GLuint WindowCompositorView::getTexture(GLenum *target)
+{
+ QWaylandBufferRef buf = currentBuffer();
+ m_texture = buf.textureForPlane(0);
+
+ if (buf.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES)
+ m_textureTarget = GL_TEXTURE_EXTERNAL_OES;
+
if (advance()) {
- if (m_texture)
- glDeleteTextures(1, &m_texture);
+ if (!m_texture)
+ glGenTextures(1, &m_texture);
- glGenTextures(1, &m_texture);
- glBindTexture(GL_TEXTURE_2D, m_texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- currentBuffer().bindToTexture();
+ glBindTexture(m_textureTarget, m_texture);
+ buf.bindToTexture();
}
+
+ buf.updateTexture();
+
+ if (target)
+ *target = m_textureTarget;
+
return m_texture;
}
diff --git a/examples/wayland/qwindow-compositor/windowcompositor.h b/examples/wayland/qwindow-compositor/windowcompositor.h
index 5290d7c85..80a7bebe4 100644
--- a/examples/wayland/qwindow-compositor/windowcompositor.h
+++ b/examples/wayland/qwindow-compositor/windowcompositor.h
@@ -59,7 +59,7 @@ class WindowCompositorView : public QWaylandView
Q_OBJECT
public:
WindowCompositorView();
- GLuint getTexture();
+ GLuint getTexture(GLenum *target = 0);
QPointF position() const { return m_position; }
void setPosition(const QPointF &pos) { m_position = pos; }
bool isCursor() const;
@@ -72,6 +72,7 @@ public:
private:
friend class WindowCompositor;
+ GLenum m_textureTarget;
GLuint m_texture;
QPointF m_position;
QWaylandWlShellSurface *m_wlShellSurface;
diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp
index 929503b4f..e9fbcfbdb 100644
--- a/src/compositor/compositor_api/qwaylandbufferref.cpp
+++ b/src/compositor/compositor_api/qwaylandbufferref.cpp
@@ -241,6 +241,16 @@ QImage QWaylandBufferRef::image() const
return d->buffer->image();
}
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+GLuint QWaylandBufferRef::textureForPlane(int plane) const
+{
+ if (d->nullOrDestroyed())
+ return 0;
+
+ return d->buffer->textureForPlane(plane);
+}
+#endif
+
/*!
* Binds the buffer to the current OpenGL texture. This may
* perform a copy of the buffer data, depending on the platform
diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h
index 4ded8f17b..50c85b965 100644
--- a/src/compositor/compositor_api/qwaylandbufferref.h
+++ b/src/compositor/compositor_api/qwaylandbufferref.h
@@ -96,6 +96,9 @@ public:
bool isShm() const;
QImage image() const;
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ GLuint textureForPlane(int plane) const;
+#endif
void bindToTexture() const;
void updateTexture() const;
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 9fa81cfb2..ab11ff4f8 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -179,17 +179,6 @@ QWaylandBufferMaterial::QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEg
{
QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
- for (int i = 0; i < bufferTypes[m_format].planeCount; i++) {
- GLuint texture;
- gl->glGenTextures(1, &texture);
- gl->glBindTexture(bufferTypes[m_format].textureTarget, texture);
- gl->glTexParameteri(bufferTypes[m_format].textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- gl->glTexParameteri(bufferTypes[m_format].textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- gl->glTexParameteri(bufferTypes[m_format].textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- gl->glTexParameteri(bufferTypes[m_format].textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- m_textures << texture;
- }
-
gl->glBindTexture(bufferTypes[m_format].textureTarget, 0);
setFlag(bufferTypes[m_format].materialFlags);
}
@@ -202,11 +191,36 @@ QWaylandBufferMaterial::~QWaylandBufferMaterial()
gl->glDeleteTextures(1, &texture);
}
+void QWaylandBufferMaterial::setTextureForPlane(int plane, uint texture)
+{
+ if (plane < 0 || plane >= bufferTypes[m_format].planeCount) {
+ qWarning("plane index is out of range");
+ return;
+ }
+
+ QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
+ const GLenum target = bufferTypes[m_format].textureTarget;
+
+ gl->glBindTexture(target, texture);
+ setTextureParameters(target);
+
+ ensureTextures(plane - 1);
+
+ if (m_textures.size() <= plane) {
+ m_textures << texture;
+ } else {
+ std::swap(m_textures[plane], texture);
+ gl->glDeleteTextures(1, &texture);
+ }
+}
+
void QWaylandBufferMaterial::bind()
{
QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
const GLenum target = bufferTypes[m_format].textureTarget;
+ ensureTextures(bufferTypes[m_format].planeCount);
+
switch (m_textures.size()) {
case 3:
gl->glActiveTexture(GL_TEXTURE2);
@@ -230,6 +244,31 @@ QSGMaterialShader *QWaylandBufferMaterial::createShader() const
return new QWaylandBufferMaterialShader(m_format);
}
+
+void QWaylandBufferMaterial::setTextureParameters(GLenum target)
+{
+ QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
+ gl->glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ gl->glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ gl->glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ gl->glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+}
+
+//TODO move this into a separate centralized texture management class
+void QWaylandBufferMaterial::ensureTextures(int count)
+{
+ QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
+ const GLenum target = bufferTypes[m_format].textureTarget;
+ GLuint texture;
+
+ for (int plane = m_textures.size(); plane < count; plane++) {
+ gl->glGenTextures(1, &texture);
+ gl->glBindTexture(target, texture);
+ setTextureParameters(target);
+ m_textures << texture;
+ }
+}
+
QMutex *QWaylandQuickItemPrivate::mutex = 0;
class QWaylandSurfaceTextureProvider : public QSGTextureProvider
@@ -1047,6 +1086,9 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->newTexture) {
d->newTexture = false;
+ for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++)
+ if (uint texture = ref.textureForPlane(plane))
+ material->setTextureForPlane(plane, texture);
material->bind();
ref.bindToTexture();
}
diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h
index 679d218ee..b529ba959 100644
--- a/src/compositor/compositor_api/qwaylandquickitem_p.h
+++ b/src/compositor/compositor_api/qwaylandquickitem_p.h
@@ -85,12 +85,17 @@ public:
QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEgl format);
~QWaylandBufferMaterial();
+ void setTextureForPlane(int plane, uint texture);
+
void bind();
QSGMaterialType *type() const Q_DECL_OVERRIDE;
QSGMaterialShader *createShader() const Q_DECL_OVERRIDE;
private:
+ void setTextureParameters(GLenum target);
+ void ensureTextures(int count);
+
const QWaylandBufferRef::BufferFormatEgl m_format;
QVarLengthArray<GLuint, 3> m_textures;
};
diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
index 1fbcb7991..90762437b 100644
--- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
+++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
@@ -73,6 +73,7 @@ public:
virtual void initializeBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); }
virtual QWaylandBufferRef::BufferFormatEgl bufferFormat(struct ::wl_resource *buffer) { Q_UNUSED(buffer); return QWaylandBufferRef::BufferFormatEgl_RGBA; }
+ virtual uint textureForBuffer(struct ::wl_resource *buffer, int plane) { Q_UNUSED(buffer); Q_UNUSED(plane); return 0; }
virtual void bindTextureToBuffer(struct ::wl_resource *buffer) = 0;
virtual void updateTextureForBuffer(struct ::wl_resource *buffer) { Q_UNUSED(buffer); }
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
index c7bdbcee5..14ccde13a 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
+++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
@@ -232,6 +232,14 @@ void SurfaceBuffer::bindToTexture() const
}
}
+uint SurfaceBuffer::textureForPlane(int plane) const
+{
+ if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration())
+ return clientInt->textureForBuffer(m_buffer, plane);
+
+ return 0;
+}
+
void SurfaceBuffer::updateTexture() const
{
if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration())
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
index 85f78d41b..95e7e8158 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
+++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
@@ -106,6 +106,7 @@ public:
QImage image() const;
QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const;
void bindToTexture() const;
+ uint textureForPlane(int plane) const;
void updateTexture() const;
static bool hasContent(SurfaceBuffer *buffer) { return buffer && buffer->waylandBufferHandle(); }
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
index e6b68225b..1c009d342 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
@@ -117,6 +117,7 @@ struct BufferState
EGLint egl_format;
QVarLengthArray<EGLImageKHR, 3> egl_images;
EGLStreamKHR egl_stream;
+ GLuint eglstream_texture;
bool isYInverted;
QSize size;
@@ -167,6 +168,7 @@ struct buffer_destroy_listener : wl_listener
BufferState::BufferState()
: egl_format(EGL_TEXTURE_RGBA)
, egl_stream(EGL_NO_STREAM_KHR)
+ , eglstream_texture(0)
, isYInverted(true)
{}
@@ -269,7 +271,21 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_fd_texture(struct ::wl
return;
}
+ if (!QOpenGLContext::currentContext())
+ qWarning("EglClientBufferIntegration: creating texture with no current context");
+
+ //TODO This texture might end up in a different context than the quick item which wants to use it, this needs to be fixed somehow.
+ glGenTextures(1, &state.eglstream_texture);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, state.eglstream_texture);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
register_buffer(buffer, state);
+
+ bindBuffer(buffer);
}
void WaylandEglClientBufferIntegrationPrivate::register_buffer(struct ::wl_resource *buffer, BufferState state)
@@ -301,8 +317,12 @@ void WaylandEglClientBufferIntegrationPrivate::bindBuffer(struct ::wl_resource *
const BufferState state = buffers.value(buffer);
if (state.egl_stream != EGL_NO_STREAM_KHR) {
- if (funcs->stream_consumer_gltexture(egl_display, state.egl_stream) != EGL_TRUE)
- qWarning("%s:%d: eglStreamConsumerGLTextureExternalKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
+ EGLint stream_state;
+ funcs->query_stream(egl_display, state.egl_stream, EGL_STREAM_STATE_KHR, &stream_state);
+
+ if (stream_state == EGL_STREAM_STATE_CREATED_KHR)
+ if (funcs->stream_consumer_gltexture(egl_display, state.egl_stream) != EGL_TRUE)
+ qWarning("%s:%d: eglStreamConsumerGLTextureExternalKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
} else {
GLint previousTexture = GL_TEXTURE0;
glGetIntegerv(GL_ACTIVE_TEXTURE, &previousTexture);
@@ -340,6 +360,11 @@ void WaylandEglClientBufferIntegrationPrivate::handle_buffer_destroy(wl_listener
BufferState state = self->buffers.take(buffer);
+ /* TODO This texture shouldn't get deleted here as the compositor might want to show an transition. But at the same time we need to make sure
+ that the texture is deleted properly although if the compositor didn't use it (e.g. by creating a quick item)*/
+ if (state.eglstream_texture)
+ glDeleteTextures(1, &state.eglstream_texture);
+
for (int i = 0; i < state.egl_images.size(); i++)
self->egl_destroy_image(self->egl_display, state.egl_images[i]);
@@ -453,6 +478,17 @@ QWaylandBufferRef::BufferFormatEgl WaylandEglClientBufferIntegration::bufferForm
return formatFromEglFormat(d->buffers.value(buffer).egl_format);
}
+uint WaylandEglClientBufferIntegration::textureForBuffer(wl_resource *buffer, int plane)
+{
+ Q_UNUSED(plane)
+ Q_D(WaylandEglClientBufferIntegration);
+ if (!buffer)
+ return 0;
+
+ const BufferState state = d->buffers.value(buffer);
+ return state.eglstream_texture;
+}
+
void WaylandEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
{
Q_D(WaylandEglClientBufferIntegration);
@@ -475,8 +511,15 @@ void WaylandEglClientBufferIntegration::updateTextureForBuffer(struct ::wl_resou
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);
+ if (state.egl_stream != EGL_NO_STREAM_KHR) {
+ EGLint stream_state;
+ d->funcs->query_stream(d->egl_display, state.egl_stream, EGL_STREAM_STATE_KHR, &stream_state);
+
+ if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
+ if (d->funcs->stream_consumer_acquire(d->egl_display, state.egl_stream) != EGL_TRUE)
+ qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
+ }
+ }
}
QWaylandSurface::Origin WaylandEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
index 57e83717a..74cad708d 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
@@ -54,6 +54,7 @@ public:
void initializeBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
QWaylandBufferRef::BufferFormatEgl bufferFormat(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
+ uint textureForBuffer(struct ::wl_resource *buffer, int plane) Q_DECL_OVERRIDE;
void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
void updateTextureForBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;