summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@gmail.com>2016-09-07 17:10:49 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2016-10-01 15:42:54 +0000
commit844204b2b04d0f3477d069db326f0e70129c71e2 (patch)
treec7134c0b7991192131c82fb14455cfbdfc4d9a14
parent2cfefb35b755e1489aff1a3c427d781e8b887223 (diff)
Refactor buffer handling
We cannot support bindToTexture() functions. On some platforms the texture is provided by the driver. Therefore, the HW integration must always provide a texture. This has the added bonus of unifying the two separate code paths that were introduced when EGLStream support was added. Add a separate buffer manager that owns all buffers. Don't destroy buffer objects on release. The client will probably attach them again later. Also, release shm buffers immediately after uploading to texture (needs to be documented that image() will not work afterwards). Make the old SurfaceBuffer class into an abstract base class, so we can store state in the buffer class instead of having to map from the wl_resource in each buffer integration. Move the shared memory buffer handling into a separate subclass. Change-Id: I81e471d13c92913d31ea1efe487f93fa908b5e0c Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com> Reviewed-by: Louai Al-Khanji <louai.al-khanji@qt.io> Reviewed-by: Johan Helsing <johan.helsing@qt.io>
-rw-r--r--examples/wayland/minimal-cpp/compositor.cpp14
-rw-r--r--examples/wayland/minimal-cpp/compositor.h5
-rw-r--r--examples/wayland/minimal-cpp/window.cpp6
-rw-r--r--examples/wayland/qwindow-compositor/compositor.cpp25
-rw-r--r--examples/wayland/qwindow-compositor/compositor.h5
-rw-r--r--examples/wayland/qwindow-compositor/window.cpp11
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.cpp68
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.h13
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp16
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor_p.h3
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp13
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp58
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem_p.h5
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp98
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h10
-rw-r--r--src/compositor/compositor_api/qwaylandview.cpp6
-rw-r--r--src/compositor/compositor_api/qwaylandview_p.h2
-rw-r--r--src/compositor/hardware_integration/qwlclientbufferintegration_p.h16
-rw-r--r--src/compositor/wayland_wrapper/qwlbuffermanager.cpp111
-rw-r--r--src/compositor/wayland_wrapper/qwlbuffermanager_p.h77
-rw-r--r--src/compositor/wayland_wrapper/qwlclientbuffer.cpp189
-rw-r--r--src/compositor/wayland_wrapper/qwlclientbuffer_p.h (renamed from src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h)84
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp261
-rw-r--r--src/compositor/wayland_wrapper/wayland_wrapper.pri6
-rw-r--r--src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp59
-rw-r--r--src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h22
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp356
-rw-r--r--src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h35
-rw-r--r--src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp50
-rw-r--r--src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h28
-rw-r--r--src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp58
-rw-r--r--src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h29
32 files changed, 941 insertions, 798 deletions
diff --git a/examples/wayland/minimal-cpp/compositor.cpp b/examples/wayland/minimal-cpp/compositor.cpp
index ea685923b..5e46895c4 100644
--- a/examples/wayland/minimal-cpp/compositor.cpp
+++ b/examples/wayland/minimal-cpp/compositor.cpp
@@ -44,17 +44,9 @@
#include <QtWaylandCompositor/qwaylandoutput.h>
#include <QOpenGLFunctions>
-GLuint View::getTexture() {
- if (advance()) {
- QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
- if (m_texture)
- functions->glDeleteTextures(1, &m_texture);
-
- functions->glGenTextures(1, &m_texture);
- functions->glBindTexture(GL_TEXTURE_2D, m_texture);
- functions->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- currentBuffer().bindToTexture();
- }
+QOpenGLTexture *View::getTexture() {
+ if (advance())
+ m_texture = currentBuffer().toOpenGLTexture();
return m_texture;
}
diff --git a/examples/wayland/minimal-cpp/compositor.h b/examples/wayland/minimal-cpp/compositor.h
index fe379082c..e44a8eb52 100644
--- a/examples/wayland/minimal-cpp/compositor.h
+++ b/examples/wayland/minimal-cpp/compositor.h
@@ -48,17 +48,18 @@
QT_BEGIN_NAMESPACE
class Window;
+class QOpenGLTexture;
class View : public QWaylandView
{
Q_OBJECT
public:
View() : m_texture(0) {}
- GLuint getTexture();
+ QOpenGLTexture *getTexture();
bool isCursor() const;
private:
friend class Compositor;
- GLuint m_texture;
+ QOpenGLTexture *m_texture;
};
class Compositor : public QWaylandCompositor
diff --git a/examples/wayland/minimal-cpp/window.cpp b/examples/wayland/minimal-cpp/window.cpp
index 2d529cce5..6ae89be4f 100644
--- a/examples/wayland/minimal-cpp/window.cpp
+++ b/examples/wayland/minimal-cpp/window.cpp
@@ -44,6 +44,7 @@
#include <QPainter>
#include <QMatrix4x4>
#include <QOpenGLFunctions>
+#include <QOpenGLTexture>
Window::Window()
: m_compositor(0)
@@ -83,7 +84,10 @@ void Window::paintGL()
Q_FOREACH (View *view, m_compositor->views()) {
if (view->isCursor())
continue;
- GLuint textureId = view->getTexture();
+ auto texture = view->getTexture();
+ if (!texture)
+ continue;
+ GLuint textureId = texture->textureId();
QWaylandSurface *surface = view->surface();
if (surface && surface->hasContent()) {
QSize s = surface->size();
diff --git a/examples/wayland/qwindow-compositor/compositor.cpp b/examples/wayland/qwindow-compositor/compositor.cpp
index e9231faf9..a55bb3b72 100644
--- a/examples/wayland/qwindow-compositor/compositor.cpp
+++ b/examples/wayland/qwindow-compositor/compositor.cpp
@@ -65,32 +65,13 @@ View::View()
, m_parentView(nullptr)
{}
-GLuint View::getTexture(GLenum *target)
+QOpenGLTexture *View::getTexture()
{
- QWaylandBufferRef buf = currentBuffer();
- GLuint streamingTexture = buf.textureForPlane(0);
- if (streamingTexture)
- m_texture = streamingTexture;
-
- if (!buf.isSharedMemory() && buf.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES)
- m_textureTarget = GL_TEXTURE_EXTERNAL_OES;
-
if (advance()) {
- buf = currentBuffer();
- if (!m_texture)
- glGenTextures(1, &m_texture);
-
- glBindTexture(m_textureTarget, m_texture);
- if (buf.isSharedMemory())
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- buf.bindToTexture();
+ QWaylandBufferRef buf = currentBuffer();
+ m_texture = buf.toOpenGLTexture();
}
- buf.updateTexture();
-
- if (target)
- *target = m_textureTarget;
-
return m_texture;
}
diff --git a/examples/wayland/qwindow-compositor/compositor.h b/examples/wayland/qwindow-compositor/compositor.h
index b7569082f..bf52c8c7e 100644
--- a/examples/wayland/qwindow-compositor/compositor.h
+++ b/examples/wayland/qwindow-compositor/compositor.h
@@ -53,13 +53,14 @@ QT_BEGIN_NAMESPACE
class QWaylandWlShell;
class QWaylandWlShellSurface;
class QWaylandXdgShellV5;
+class QOpenGLTexture;
class View : public QWaylandView
{
Q_OBJECT
public:
View();
- GLuint getTexture(GLenum *target = 0);
+ QOpenGLTexture *getTexture();
QPointF position() const { return m_position; }
void setPosition(const QPointF &pos) { m_position = pos; }
bool isCursor() const;
@@ -73,7 +74,7 @@ public:
private:
friend class Compositor;
GLenum m_textureTarget;
- GLuint m_texture;
+ QOpenGLTexture *m_texture;
QPointF m_position;
QWaylandWlShellSurface *m_wlShellSurface;
QWaylandXdgSurfaceV5 *m_xdgSurface;
diff --git a/examples/wayland/qwindow-compositor/window.cpp b/examples/wayland/qwindow-compositor/window.cpp
index 617d79c0e..371e0de80 100644
--- a/examples/wayland/qwindow-compositor/window.cpp
+++ b/examples/wayland/qwindow-compositor/window.cpp
@@ -120,12 +120,11 @@ void Window::paintGL()
Q_FOREACH (View *view, m_compositor->views()) {
if (view->isCursor())
continue;
- GLenum target;
- GLuint textureId = view->getTexture(&target);
- if (!textureId || !target)
+ auto texture = view->getTexture();
+ if (!texture)
continue;
- if (target != currentTarget) {
- currentTarget = target;
+ if (texture->target() != currentTarget) {
+ currentTarget = texture->target();
m_textureBlitter.bind(currentTarget);
}
QWaylandSurface *surface = view->surface();
@@ -141,7 +140,7 @@ void Window::paintGL()
? QOpenGLTextureBlitter::OriginTopLeft
: QOpenGLTextureBlitter::OriginBottomLeft;
QMatrix4x4 targetTransform = QOpenGLTextureBlitter::targetTransform(surfaceGeometry, QRect(QPoint(), size()));
- m_textureBlitter.blit(textureId, targetTransform, surfaceOrigin);
+ m_textureBlitter.blit(texture->textureId(), targetTransform, surfaceOrigin);
}
}
}
diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp
index 7cc17fcbe..8f7c63f40 100644
--- a/src/compositor/compositor_api/qwaylandbufferref.cpp
+++ b/src/compositor/compositor_api/qwaylandbufferref.cpp
@@ -38,14 +38,14 @@
#include <QAtomicInt>
#include "qwaylandbufferref.h"
-#include "wayland_wrapper/qwlsurfacebuffer_p.h"
+#include "wayland_wrapper/qwlclientbuffer_p.h"
QT_BEGIN_NAMESPACE
class QWaylandBufferRefPrivate
{
public:
- QtWayland::SurfaceBuffer *buffer;
+ QtWayland::ClientBuffer *buffer;
bool nullOrDestroyed() {
return !buffer || buffer->isDestroyed();
@@ -74,7 +74,7 @@ QWaylandBufferRef::QWaylandBufferRef()
/*!
* Constructs a reference to \a buffer.
*/
-QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer)
+QWaylandBufferRef::QWaylandBufferRef(QtWayland::ClientBuffer *buffer)
: d(new QWaylandBufferRefPrivate)
{
d->buffer = buffer;
@@ -104,17 +104,18 @@ QWaylandBufferRef::~QWaylandBufferRef()
}
/*!
- * Assigns \a ref to this buffer. The previously referenced buffer is
- * dereferenced and the new one gets a new reference.
+ * Assigns \a ref to this buffer and adds a reference to it. The previously referenced buffer is
+ * dereferenced.
*/
QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref)
{
+ if (ref.d->buffer)
+ ref.d->buffer->ref();
+
if (d->buffer)
d->buffer->deref();
d->buffer = ref.d->buffer;
- if (d->buffer)
- d->buffer->ref();
return *this;
}
@@ -141,7 +142,7 @@ bool QWaylandBufferRef::operator!=(const QWaylandBufferRef &ref)
* Returns true if this QWaylandBufferRef does not reference a buffer.
* Otherwise returns false.
*
- * \sa hasBuffer()
+ * \sa hasBuffer(), hasContent()
*/
bool QWaylandBufferRef::isNull() const
{
@@ -151,12 +152,21 @@ bool QWaylandBufferRef::isNull() const
/*!
* Returns true if this QWaylandBufferRef references a buffer. Otherwise returns false.
*
- * \sa isNull()
+ * \sa isNull(), hasContent()
*/
bool QWaylandBufferRef::hasBuffer() const
{
return d->buffer;
}
+/*!
+ * Returns true if this QWaylandBufferRef references a buffer that has content. Otherwise returns false.
+ *
+ * \sa isNull(), hasBuffer()
+ */
+bool QWaylandBufferRef::hasContent() const
+{
+ return QtWayland::ClientBuffer::hasContent(d->buffer);
+}
/*!
* Returns true if this QWaylandBufferRef references a buffer that
@@ -176,6 +186,14 @@ struct ::wl_resource *QWaylandBufferRef::wl_buffer() const
}
/*!
+ * \internal
+ */
+QtWayland::ClientBuffer *QWaylandBufferRef::buffer() const
+{
+ return d->buffer;
+}
+
+/*!
* Returns the size of the buffer.
* If the buffer referenced is null, an invalid QSize() is returned.
*/
@@ -242,35 +260,23 @@ QImage QWaylandBufferRef::image() const
}
#ifdef QT_WAYLAND_COMPOSITOR_GL
-GLuint QWaylandBufferRef::textureForPlane(int plane) const
-{
- if (d->nullOrDestroyed())
- return 0;
-
- return d->buffer->textureForPlane(plane);
-}
-
/*!
- * Binds the buffer to the current OpenGL texture. This may
- * perform a copy of the buffer data, depending on the platform
- * and the type of the buffer.
+ * Returns an OpenGL texture for the buffer. \a plane is the index for multi-plane formats, such as YUV.
+ *
+ * The returned texture is owned by the buffer. The texture is only valid for as
+ * long as the buffer reference exists. The caller of this function must not delete the texture, and must
+ * keep a reference to the buffer for as long as the texture is being used.
+ *
+ * Returns \c nullptr if there is no valid buffer, or if no texture can be created.
*/
-void QWaylandBufferRef::bindToTexture() const
+QOpenGLTexture *QWaylandBufferRef::toOpenGLTexture(int plane) const
{
if (d->nullOrDestroyed())
- return;
-
- return d->buffer->bindToTexture();
+ return nullptr;
+ return d->buffer->toOpenGlTexture(plane);
}
-void QWaylandBufferRef::updateTexture() const
-{
- if (d->nullOrDestroyed() || d->buffer->isSharedMemory())
- return;
-
- d->buffer->updateTexture();
-}
#endif
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h
index 77f817aba..549ea0a80 100644
--- a/src/compositor/compositor_api/qwaylandbufferref.h
+++ b/src/compositor/compositor_api/qwaylandbufferref.h
@@ -50,22 +50,24 @@ struct wl_resource;
QT_BEGIN_NAMESPACE
+class QOpenGLTexture;
+
namespace QtWayland
{
- class SurfaceBuffer;
+ class ClientBuffer;
}
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandBufferRef
{
public:
QWaylandBufferRef();
- explicit QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer);
QWaylandBufferRef(const QWaylandBufferRef &ref);
~QWaylandBufferRef();
QWaylandBufferRef &operator=(const QWaylandBufferRef &ref);
bool isNull() const;
bool hasBuffer() const;
+ bool hasContent() const;
bool isDestroyed() const;
bool operator==(const QWaylandBufferRef &ref);
bool operator!=(const QWaylandBufferRef &ref);
@@ -98,14 +100,15 @@ public:
QImage image() const;
#ifdef QT_WAYLAND_COMPOSITOR_GL
- GLuint textureForPlane(int plane) const;
- void bindToTexture() const;
- void updateTexture() const;
+ QOpenGLTexture *toOpenGLTexture(int plane = 0) const;
#endif
private:
+ explicit QWaylandBufferRef(QtWayland::ClientBuffer *buffer);
+ QtWayland::ClientBuffer *buffer() const;
class QWaylandBufferRefPrivate *const d;
friend class QWaylandBufferRefPrivate;
+ friend class QWaylandSurfacePrivate;
};
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 0d4e30df7..79a62a1f2 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -53,6 +53,7 @@
#include "wayland_wrapper/qwldatadevice_p.h"
#include "wayland_wrapper/qwldatadevicemanager_p.h"
+#include "wayland_wrapper/qwlbuffermanager_p.h"
#include "hardware_integration/qwlclientbufferintegration_p.h"
#include "hardware_integration/qwlclientbufferintegrationfactory_p.h"
@@ -81,6 +82,7 @@
#ifdef QT_WAYLAND_COMPOSITOR_GL
# include <QOpenGLTextureBlitter>
+# include <QOpenGLTexture>
# include <QOpenGLContext>
# include <QOpenGLFramebufferObject>
# include <QMatrix4x4>
@@ -174,6 +176,7 @@ void QWaylandCompositorPrivate::init()
wl_subcompositor::init(display, 1);
data_device_manager = new QtWayland::DataDeviceManager(q);
+ buffer_manager = new QtWayland::BufferManager(q);
wl_display_init_shm(display);
QVector<wl_shm_format> formats = QWaylandSharedMemoryFormatHelper::supportedWaylandFormats();
@@ -895,7 +898,7 @@ void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWay
fbo.bind();
QOpenGLTextureBlitter blitter;
blitter.create();
- blitter.bind();
+
glViewport(0, 0, buffer.size().width(), buffer.size().height());
@@ -904,15 +907,10 @@ void QWaylandCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const QWay
? QOpenGLTextureBlitter::OriginTopLeft
: QOpenGLTextureBlitter::OriginBottomLeft;
- GLuint texture;
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- buffer.bindToTexture();
- blitter.blit(texture, QMatrix4x4(), surfaceOrigin);
-
+ auto texture = buffer.toOpenGLTexture();
+ blitter.bind(texture->target());
+ blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
blitter.release();
- glDeleteTextures(1, &texture);
emit grabber->success(fbo.toImage());
} else
diff --git a/src/compositor/compositor_api/qwaylandcompositor_p.h b/src/compositor/compositor_api/qwaylandcompositor_p.h
index 9942331e4..5255f3d58 100644
--- a/src/compositor/compositor_api/qwaylandcompositor_p.h
+++ b/src/compositor/compositor_api/qwaylandcompositor_p.h
@@ -64,6 +64,7 @@ namespace QtWayland {
class ClientBufferIntegration;
class ServerBufferIntegration;
class DataDeviceManager;
+ class BufferManager;
}
class QWindowSystemEventHandler;
@@ -89,6 +90,7 @@ public:
inline QtWayland::ServerBufferIntegration *serverBufferIntegration() const;
QtWayland::DataDeviceManager *dataDeviceManager() const { return data_device_manager; }
+ QtWayland::BufferManager *bufferManager() const { return buffer_manager; }
void feedRetainedSelectionData(QMimeData *data);
QWaylandPointer *callCreatePointerDevice(QWaylandSeat *seat)
@@ -129,6 +131,7 @@ protected:
QList<QWaylandSurface *> all_surfaces;
QtWayland::DataDeviceManager *data_device_manager;
+ QtWayland::BufferManager *buffer_manager;
QElapsedTimer timer;
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
index 21e32573e..b69e20791 100644
--- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
@@ -38,6 +38,7 @@
#include <QtQml/QQmlEngine>
#include <QQuickWindow>
#include <QOpenGLTextureBlitter>
+#include <QOpenGLTexture>
#include <QOpenGLFramebufferObject>
#include <QMatrix4x4>
#include <QRunnable>
@@ -140,7 +141,6 @@ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const
fbo.bind();
QOpenGLTextureBlitter blitter;
blitter.create();
- blitter.bind();
glViewport(0, 0, buffer.size().width(), buffer.size().height());
@@ -149,15 +149,10 @@ void QWaylandQuickCompositor::grabSurface(QWaylandSurfaceGrabber *grabber, const
? QOpenGLTextureBlitter::OriginTopLeft
: QOpenGLTextureBlitter::OriginBottomLeft;
- GLuint texture;
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- buffer.bindToTexture();
- blitter.blit(texture, QMatrix4x4(), surfaceOrigin);
-
+ auto texture = buffer.toOpenGLTexture();
+ blitter.bind(texture->target());
+ blitter.blit(texture->textureId(), QMatrix4x4(), surfaceOrigin);
blitter.release();
- glDeleteTextures(1, &texture);
emit grabber->success(fbo.toImage());
}
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index a3234cba6..f41a4c3ee 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -50,6 +50,7 @@
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
#include <QtGui/QOpenGLFunctions>
+#include <QtGui/QOpenGLTexture>
#include <QtQuick/QSGSimpleTextureNode>
#include <QtQuick/QQuickWindow>
@@ -188,52 +189,40 @@ QWaylandBufferMaterial::QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEg
QWaylandBufferMaterial::~QWaylandBufferMaterial()
{
- QOpenGLFunctions *gl = QOpenGLContext::currentContext()->functions();
-
- for (GLuint texture : m_textures)
- gl->glDeleteTextures(1, &texture);
}
-void QWaylandBufferMaterial::setTextureForPlane(int plane, uint texture)
+void QWaylandBufferMaterial::setTextureForPlane(int plane, QOpenGLTexture *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);
+ texture->bind();
+ setTextureParameters(texture->target());
ensureTextures(plane - 1);
- if (m_textures.size() <= plane) {
+ if (m_textures.size() <= plane)
m_textures << texture;
- } else {
- std::swap(m_textures[plane], texture);
- gl->glDeleteTextures(1, &texture);
- }
+ else
+ m_textures[plane] = 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);
- gl->glBindTexture(target, m_textures[2]);
+ if (m_textures[2])
+ m_textures[2]->bind(GL_TEXTURE2);
case 2:
- gl->glActiveTexture(GL_TEXTURE1);
- gl->glBindTexture(target, m_textures[1]);
+ if (m_textures[1])
+ m_textures[1]->bind(GL_TEXTURE1);
case 1:
- gl->glActiveTexture(GL_TEXTURE0);
- gl->glBindTexture(target, m_textures[0]);
+ if (m_textures[0])
+ m_textures[0]->bind(GL_TEXTURE0);
}
}
@@ -260,15 +249,8 @@ void QWaylandBufferMaterial::setTextureParameters(GLenum target)
//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;
+ m_textures << nullptr;
}
}
@@ -308,11 +290,8 @@ public:
opt |= QQuickWindow::TextureHasAlphaChannel;
}
- GLuint texture;
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- buffer.bindToTexture();
- m_sgTex = surfaceItem->window()->createTextureFromId(texture , QSize(surfaceItem->width(), surfaceItem->height()), opt);
+ auto texture = buffer.toOpenGLTexture();
+ m_sgTex = surfaceItem->window()->createTextureFromId(texture->textureId() , QSize(surfaceItem->width(), surfaceItem->height()), opt);
}
}
emit textureChanged();
@@ -1151,6 +1130,7 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
: QRectF(0, 0, width(), height());
if (ref.isSharedMemory() || bufferTypes[ref.bufferFormatEgl()].canProvideTexture) {
+ // This case could covered by the more general path below, but this is more efficient (especially when using ShaderEffect items).
QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
if (!node) {
@@ -1193,13 +1173,11 @@ 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))
+ if (auto texture = ref.toOpenGLTexture(plane))
material->setTextureForPlane(plane, texture);
material->bind();
- ref.bindToTexture();
}
- ref.updateTexture();
QSGGeometry::updateTexturedRectGeometry(geometry, rect, QRectF(0, 0, 1, 1));
node->setGeometry(geometry);
diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h
index 30f1e93c7..c30829926 100644
--- a/src/compositor/compositor_api/qwaylandquickitem_p.h
+++ b/src/compositor/compositor_api/qwaylandquickitem_p.h
@@ -59,6 +59,7 @@ QT_BEGIN_NAMESPACE
class QWaylandSurfaceTextureProvider;
class QMutex;
+class QOpenGLTexture;
class QWaylandBufferMaterialShader : public QSGMaterialShader
{
@@ -84,7 +85,7 @@ public:
QWaylandBufferMaterial(QWaylandBufferRef::BufferFormatEgl format);
~QWaylandBufferMaterial();
- void setTextureForPlane(int plane, uint texture);
+ void setTextureForPlane(int plane, QOpenGLTexture *texture);
void bind();
@@ -96,7 +97,7 @@ private:
void ensureTextures(int count);
const QWaylandBufferRef::BufferFormatEgl m_format;
- QVarLengthArray<GLuint, 3> m_textures;
+ QVarLengthArray<QOpenGLTexture*, 3> m_textures;
};
class QWaylandQuickItemPrivate : public QQuickItemPrivate
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index c00d765c5..2f4de5cfc 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -40,6 +40,7 @@
#include "wayland_wrapper/qwldatadevice_p.h"
#include "wayland_wrapper/qwldatadevicemanager_p.h"
+#include "wayland_wrapper/qwlbuffermanager_p.h"
#include "wayland_wrapper/qwlregion_p.h"
#include "extensions/qwlextendedsurface_p.h"
@@ -123,7 +124,6 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate()
, compositor(Q_NULLPTR)
, refCount(1)
, client(Q_NULLPTR)
- , buffer(0)
, role(0)
, inputRegion(infiniteRegion())
, bufferScale(1)
@@ -135,7 +135,7 @@ QWaylandSurfacePrivate::QWaylandSurfacePrivate()
, inputMethodControl(Q_NULLPTR)
, subsurface(0)
{
- pending.buffer = 0;
+ pending.buffer = QWaylandBufferRef();
pending.newlyAttached = false;
pending.inputRegion = infiniteRegion();
pending.bufferScale = 1;
@@ -153,9 +153,6 @@ QWaylandSurfacePrivate::~QWaylandSurfacePrivate()
bufferRef = QWaylandBufferRef();
- for (int i = 0; i < bufferPool.size(); i++)
- bufferPool[i]->setDestroyIfUnused(true);
-
foreach (QtWayland::FrameCallback *c, pendingFrameCallbacks)
c->destroy();
foreach (QtWayland::FrameCallback *c, frameCallbacks)
@@ -237,9 +234,7 @@ void QWaylandSurfacePrivate::surface_destroy(Resource *resource)
void QWaylandSurfacePrivate::surface_attach(Resource *, struct wl_resource *buffer, int x, int y)
{
- if (pending.buffer)
- pending.buffer->disown();
- pending.buffer = createSurfaceBuffer(buffer);
+ pending.buffer = QWaylandBufferRef(getBuffer(buffer));
pending.offset = QPoint(x, y);
pending.newlyAttached = true;
}
@@ -274,19 +269,37 @@ void QWaylandSurfacePrivate::surface_commit(Resource *)
{
Q_Q(QWaylandSurface);
- if (pending.buffer || pending.newlyAttached) {
- setBackBuffer(pending.buffer, pending.damage);
+ if (pending.buffer.hasBuffer())
+ bufferRef = pending.buffer;
+
+ auto buffer = bufferRef.buffer();
+ if (buffer)
+ buffer->setCommitted(pending.damage);
+
+ setSize(bufferRef.size());
+ damage = pending.damage.intersected(QRect(QPoint(), size));
+
+ for (int i = 0; i < views.size(); i++) {
+ views.at(i)->bufferCommitted(bufferRef, damage);
}
- pending.buffer = 0;
- pending.offset = QPoint();
- pending.newlyAttached = false;
- pending.damage = QRegion();
+ emit q->damaged(damage);
+
+ bool oldHasContent = hasContent;
+ hasContent = bufferRef.hasContent();
+ if (oldHasContent != hasContent)
+ emit q->hasContentChanged();
+
+ if (!pending.offset.isNull())
+ emit q->offsetForNextFrame(pending.offset);
setBufferScale(pending.bufferScale);
- if (buffer)
- buffer->setCommitted();
+
+ pending.buffer = QWaylandBufferRef();
+ pending.offset = QPoint();
+ pending.newlyAttached = false;
+ pending.damage = QRegion();
frameCallbacks << pendingFrameCallbacks;
pendingFrameCallbacks.clear();
@@ -326,52 +339,10 @@ void QWaylandSurfacePrivate::surface_set_buffer_scale(QtWaylandServer::wl_surfac
pending.bufferScale = scale;
}
-void QWaylandSurfacePrivate::setBackBuffer(QtWayland::SurfaceBuffer *b, const QRegion &d)
+QtWayland::ClientBuffer *QWaylandSurfacePrivate::getBuffer(struct ::wl_resource *buffer)
{
- Q_Q(QWaylandSurface);
- buffer = b;
-
- bufferRef = QWaylandBufferRef(buffer);
-
- setSize(bufferRef.size());
- damage = d.intersected(QRect(QPoint(), size));
-
- for (int i = 0; i < views.size(); i++) {
- views.at(i)->bufferCommitted(bufferRef, damage);
- }
-
- emit q->damaged(damage);
-
- bool oldHasContent = hasContent;
- hasContent = QtWayland::SurfaceBuffer::hasContent(buffer);
- if (oldHasContent != hasContent)
- emit q->hasContentChanged();
-
- if (!pending.offset.isNull())
- emit q->offsetForNextFrame(pending.offset);
-}
-
-QtWayland::SurfaceBuffer *QWaylandSurfacePrivate::createSurfaceBuffer(struct ::wl_resource *buffer)
-{
- Q_Q(QWaylandSurface);
- QtWayland::SurfaceBuffer *newBuffer = 0;
- for (int i = 0; i < bufferPool.size(); i++) {
- if (!bufferPool[i]->isRegisteredWithBuffer()) {
- newBuffer = bufferPool[i];
- newBuffer->initialize(buffer);
- break;
- }
- }
-
- if (!newBuffer) {
- newBuffer = new QtWayland::SurfaceBuffer(q);
- newBuffer->initialize(buffer);
- bufferPool.append(newBuffer);
- if (bufferPool.size() > 3)
- qWarning() << "Increased buffer pool size to" << bufferPool.size() << "for surface" << q;
- }
-
- return newBuffer;
+ QtWayland::BufferManager *bufMan = QWaylandCompositorPrivate::get(compositor)->bufferManager();
+ return bufMan->getBuffer(buffer);
}
/*!
@@ -590,7 +561,7 @@ Qt::ScreenOrientation QWaylandSurface::contentOrientation() const
QWaylandSurface::Origin QWaylandSurface::origin() const
{
Q_D(const QWaylandSurface);
- return d->buffer ? d->buffer->origin() : QWaylandSurface::OriginTopLeft;
+ return d->bufferRef.origin();
}
/*!
@@ -835,8 +806,7 @@ void QWaylandSurfacePrivate::refView(QWaylandView *view)
views.append(view);
ref();
- QWaylandBufferRef ref(buffer);
- view->bufferCommitted(ref, QRect(QPoint(0,0), ref.size()));
+ view->bufferCommitted(bufferRef, QRect(QPoint(0,0), bufferRef.size()));
}
void QWaylandSurfacePrivate::derefView(QWaylandView *view)
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
index 0596b61ba..94ec287bd 100644
--- a/src/compositor/compositor_api/qwaylandsurface_p.h
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -52,7 +52,7 @@
#include <QtWaylandCompositor/qwaylandexport.h>
#include <private/qobject_p.h>
-#include <private/qwlsurfacebuffer_p.h>
+#include <private/qwlclientbuffer_p.h>
#include <QtWaylandCompositor/qwaylandsurface.h>
#include <QtWaylandCompositor/qwaylandbufferref.h>
@@ -134,8 +134,7 @@ protected:
void surface_set_buffer_transform(Resource *resource, int32_t transform) Q_DECL_OVERRIDE;
void surface_set_buffer_scale(Resource *resource, int32_t bufferScale) Q_DECL_OVERRIDE;
- void setBackBuffer(QtWayland::SurfaceBuffer *buffer, const QRegion &damage);
- QtWayland::SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer);
+ QtWayland::ClientBuffer *getBuffer(struct ::wl_resource *buffer);
public: //member variables
QWaylandCompositor *compositor;
@@ -143,12 +142,11 @@ public: //member variables
QWaylandClient *client;
QList<QWaylandView *> views;
QRegion damage;
- QtWayland::SurfaceBuffer *buffer;
QWaylandBufferRef bufferRef;
QWaylandSurfaceRole *role;
struct {
- QtWayland::SurfaceBuffer *buffer;
+ QWaylandBufferRef buffer;
QRegion damage;
QPoint offset;
bool newlyAttached;
@@ -165,8 +163,6 @@ public: //member variables
QRegion inputRegion;
QRegion opaqueRegion;
- QVector<QtWayland::SurfaceBuffer *> bufferPool;
-
QSize size;
int bufferScale;
bool isCursorSurface;
diff --git a/src/compositor/compositor_api/qwaylandview.cpp b/src/compositor/compositor_api/qwaylandview.cpp
index 5b87eae21..850503847 100644
--- a/src/compositor/compositor_api/qwaylandview.cpp
+++ b/src/compositor/compositor_api/qwaylandview.cpp
@@ -151,6 +151,7 @@ void QWaylandView::setSurface(QWaylandSurface *newSurface)
}
d->nextBuffer = QWaylandBufferRef();
+ d->nextBufferCommitted = false;
d->nextDamage = QRegion();
if (d->surface) {
@@ -211,6 +212,7 @@ void QWaylandView::bufferCommitted(const QWaylandBufferRef &buffer, const QRegio
QMutexLocker locker(&d->bufferMutex);
d->nextBuffer = buffer;
d->nextDamage = damage;
+ d->nextBufferCommitted = true;
}
/*!
@@ -232,7 +234,8 @@ void QWaylandView::bufferCommitted(const QWaylandBufferRef &buffer, const QRegio
bool QWaylandView::advance()
{
Q_D(QWaylandView);
- if (d->currentBuffer == d->nextBuffer && !d->forceAdvanceSucceed)
+
+ if (!d->nextBufferCommitted && !d->forceAdvanceSucceed)
return false;
if (d->bufferLocked)
@@ -247,6 +250,7 @@ bool QWaylandView::advance()
QMutexLocker locker(&d->bufferMutex);
d->forceAdvanceSucceed = false;
+ d->nextBufferCommitted = false;
d->currentBuffer = d->nextBuffer;
d->currentDamage = d->nextDamage;
return true;
diff --git a/src/compositor/compositor_api/qwaylandview_p.h b/src/compositor/compositor_api/qwaylandview_p.h
index d9fd352ed..8c55eca36 100644
--- a/src/compositor/compositor_api/qwaylandview_p.h
+++ b/src/compositor/compositor_api/qwaylandview_p.h
@@ -69,6 +69,7 @@ public:
: renderObject(Q_NULLPTR)
, surface(Q_NULLPTR)
, output(Q_NULLPTR)
+ , nextBufferCommitted(false)
, bufferLocked(false)
, broadcastRequestedPositionChanged(false)
, forceAdvanceSucceed(false)
@@ -86,6 +87,7 @@ public:
QRegion currentDamage;
QWaylandBufferRef nextBuffer;
QRegion nextDamage;
+ bool nextBufferCommitted;
bool bufferLocked;
bool broadcastRequestedPositionChanged;
bool forceAdvanceSucceed;
diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
index 90762437b..a7de2c0e3 100644
--- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
+++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h
@@ -57,6 +57,7 @@
QT_BEGIN_NAMESPACE
class QWaylandCompositor;
+class QOpenGLTexture;
namespace QtWayland {
class Display;
@@ -68,22 +69,11 @@ public:
virtual ~ClientBufferIntegration() { }
void setCompositor(QWaylandCompositor *compositor) { m_compositor = compositor; }
+ QWaylandCompositor *compositor() const { return m_compositor; }
virtual void initializeHardware(struct ::wl_display *display) = 0;
- 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); }
-
- virtual QWaylandSurface::Origin origin(struct ::wl_resource *) const { return QWaylandSurface::OriginBottomLeft; }
-
- virtual void *lockNativeBuffer(struct ::wl_resource *) const { return 0; }
- virtual void unlockNativeBuffer(void *) const { return; }
-
- virtual QSize bufferSize(struct ::wl_resource *) const { return QSize(); }
+ virtual ClientBuffer *createBufferFor(struct ::wl_resource *buffer) = 0;
protected:
QWaylandCompositor *m_compositor;
diff --git a/src/compositor/wayland_wrapper/qwlbuffermanager.cpp b/src/compositor/wayland_wrapper/qwlbuffermanager.cpp
new file mode 100644
index 000000000..765c9a03a
--- /dev/null
+++ b/src/compositor/wayland_wrapper/qwlbuffermanager.cpp
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwlbuffermanager_p.h"
+#include <QWaylandCompositor>
+#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
+#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h>
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWayland {
+
+BufferManager::BufferManager(QWaylandCompositor *compositor)
+ : QObject(compositor)
+ , m_compositor(compositor)
+{
+
+}
+
+struct buffer_manager_destroy_listener : wl_listener
+{
+ buffer_manager_destroy_listener()
+ : d(0)
+ {
+ notify = BufferManager::destroy_listener_callback;
+ wl_list_init(&this->link);
+ }
+
+ BufferManager *d;
+};
+
+ClientBuffer *BufferManager::getBuffer(wl_resource *buffer_resource)
+{
+ if (!buffer_resource)
+ return nullptr;
+
+ auto it = m_buffers.find(buffer_resource);
+ if (it != m_buffers.end())
+ return it.value();
+
+ auto bufferIntegration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration();
+ ClientBuffer *newBuffer = nullptr;
+ if (bufferIntegration)
+ newBuffer = bufferIntegration->createBufferFor(buffer_resource);
+ if (!newBuffer)
+ newBuffer = new SharedMemoryBuffer(buffer_resource);
+ m_buffers[buffer_resource] = newBuffer;
+
+ auto *destroy_listener = new buffer_manager_destroy_listener;
+ destroy_listener->d = this;
+ wl_signal_add(&buffer_resource->destroy_signal, destroy_listener);
+ return newBuffer;
+}
+
+
+void BufferManager::destroy_listener_callback(wl_listener *listener, void *data)
+{
+ buffer_manager_destroy_listener *destroy_listener = static_cast<buffer_manager_destroy_listener *>(listener);
+ BufferManager *self = destroy_listener->d;
+ struct ::wl_resource *buffer = static_cast<struct ::wl_resource *>(data);
+
+ wl_list_remove(&destroy_listener->link);
+ delete destroy_listener;
+
+ Q_ASSERT(self);
+ Q_ASSERT(buffer);
+
+ ClientBuffer *clientBuffer = self->m_buffers.take(buffer);
+
+ if (!clientBuffer)
+ return;
+
+ clientBuffer->setDestroyed();
+}
+
+}
+QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlbuffermanager_p.h b/src/compositor/wayland_wrapper/qwlbuffermanager_p.h
new file mode 100644
index 000000000..e1325ef89
--- /dev/null
+++ b/src/compositor/wayland_wrapper/qwlbuffermanager_p.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWLBUFFERMANAGER_H
+#define QWLBUFFERMANAGER_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QObject>
+#include "qwlclientbuffer_p.h"
+QT_BEGIN_NAMESPACE
+
+class QWaylandCompositor;
+
+namespace QtWayland {
+
+class ClientBuffer;
+
+class Q_WAYLAND_COMPOSITOR_EXPORT BufferManager : public QObject
+{
+public:
+ BufferManager(QWaylandCompositor *compositor);
+ ClientBuffer *getBuffer(struct ::wl_resource *buffer_resource);
+private:
+ friend struct buffer_manager_destroy_listener;
+ static void destroy_listener_callback(wl_listener *listener, void *data);
+
+ QHash<struct ::wl_resource *, ClientBuffer*> m_buffers;
+ QWaylandCompositor *m_compositor;
+};
+
+}
+QT_END_NAMESPACE
+
+#endif // QWLBUFFERMANAGER_H
diff --git a/src/compositor/wayland_wrapper/qwlclientbuffer.cpp b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
new file mode 100644
index 000000000..589ab825b
--- /dev/null
+++ b/src/compositor/wayland_wrapper/qwlclientbuffer.cpp
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwlclientbuffer_p.h"
+
+#ifdef QT_WAYLAND_COMPOSITOR_GL
+#include "hardware_integration/qwlclientbufferintegration_p.h"
+#include <qpa/qplatformopenglcontext.h>
+#include <QOpenGLTexture>
+#endif
+
+#include <QtCore/QDebug>
+
+#include <wayland-server-protocol.h>
+#include "qwaylandsharedmemoryformathelper_p.h"
+
+#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWayland {
+
+ClientBuffer::ClientBuffer(struct ::wl_resource *buffer)
+ : m_buffer(buffer)
+ , m_textureDirty(false)
+ , m_committed(false)
+ , m_destroyed(false)
+{
+}
+
+
+ClientBuffer::~ClientBuffer()
+{
+ if (m_buffer && m_committed && !m_destroyed)
+ sendRelease();
+}
+
+void ClientBuffer::sendRelease()
+{
+ Q_ASSERT(m_buffer);
+ wl_buffer_send_release(m_buffer);
+ m_committed = false;
+}
+
+void ClientBuffer::setDestroyed()
+{
+ m_destroyed = true;
+ m_committed = false;
+ m_buffer = nullptr;
+
+ if (!m_refCount)
+ delete this;
+}
+
+void ClientBuffer::ref()
+{
+ m_refCount.ref();
+}
+
+void ClientBuffer::deref()
+{
+ if (!m_refCount.deref()) {
+ if (isCommitted() && m_buffer && !m_destroyed)
+ sendRelease();
+ if (m_destroyed)
+ delete this;
+ }
+}
+
+void ClientBuffer::setCommitted(QRegion &damage)
+{
+ m_damage = damage;
+ m_committed = true;
+ m_textureDirty = true;
+}
+
+QWaylandBufferRef::BufferFormatEgl ClientBuffer::bufferFormatEgl() const
+{
+ return QWaylandBufferRef::BufferFormatEgl_Null;
+}
+
+SharedMemoryBuffer::SharedMemoryBuffer(wl_resource *bufferResource)
+ : ClientBuffer(bufferResource)
+ , m_shmTexture(nullptr)
+{
+
+}
+
+QSize SharedMemoryBuffer::size() const
+{
+ if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) {
+ int width = wl_shm_buffer_get_width(shmBuffer);
+ int height = wl_shm_buffer_get_height(shmBuffer);
+ return QSize(width, height);
+ }
+ return QSize();
+}
+
+QWaylandSurface::Origin SharedMemoryBuffer::origin() const
+{
+ return QWaylandSurface::OriginTopLeft;
+}
+
+
+// TODO: support different color formats, and try to avoid QImage::convertToFormat()
+
+QImage SharedMemoryBuffer::image() const
+{
+ if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) {
+ int width = wl_shm_buffer_get_width(shmBuffer);
+ int height = wl_shm_buffer_get_height(shmBuffer);
+ int bytesPerLine = wl_shm_buffer_get_stride(shmBuffer);
+ uchar *data = static_cast<uchar *>(wl_shm_buffer_get_data(shmBuffer));
+ return QImage(data, width, height, bytesPerLine, QImage::Format_ARGB32_Premultiplied);
+ }
+
+ return QImage();
+}
+
+#ifdef QT_WAYLAND_COMPOSITOR_GL
+QOpenGLTexture *SharedMemoryBuffer::toOpenGlTexture(int plane)
+{
+ Q_UNUSED(plane);
+ if (isSharedMemory()) {
+ if (!m_shmTexture) {
+ m_shmTexture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_shmTexture->create();
+ }
+ if (m_textureDirty) {
+ m_textureDirty = false;
+ m_shmTexture->bind();
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ // TODO: partial texture upload
+ QImage image = this->image();
+ if (image.hasAlphaChannel()) {
+ if (image.format() != QImage::Format_RGBA8888)
+ image = image.convertToFormat(QImage::Format_RGBA8888);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
+ } else {
+ if (image.format() != QImage::Format_RGBX8888)
+ image = image.convertToFormat(QImage::Format_RGBX8888);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits());
+ }
+ //we can release the buffer after uploading, since we have a copy
+ if (isCommitted())
+ sendRelease();
+ }
+ return m_shmTexture;
+ }
+ return nullptr;
+}
+#endif
+
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlclientbuffer_p.h
index e0a7d021f..72c5a56e3 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
+++ b/src/compositor/wayland_wrapper/qwlclientbuffer_p.h
@@ -34,8 +34,8 @@
**
****************************************************************************/
-#ifndef SURFACEBUFFER_H
-#define SURFACEBUFFER_H
+#ifndef QWLCLIENTBUFFER_P_H
+#define QWLCLIENTBUFFER_P_H
//
// W A R N I N G
@@ -63,83 +63,85 @@ QT_BEGIN_NAMESPACE
class QWaylandClientBufferIntegration;
class QWaylandBufferRef;
class QWaylandCompositor;
+class QOpenGLTexture;
namespace QtWayland {
struct surface_buffer_destroy_listener
{
struct wl_listener listener;
- class SurfaceBuffer *surfaceBuffer;
+ class ClientBuffer *surfaceBuffer;
};
-class SurfaceBuffer
+class Q_WAYLAND_COMPOSITOR_EXPORT ClientBuffer
{
public:
- SurfaceBuffer(QWaylandSurface *surface);
+ ClientBuffer(struct ::wl_resource *bufferResource);
- ~SurfaceBuffer();
+ virtual ~ClientBuffer();
- void initialize(struct ::wl_resource *bufferResource);
- void destructBufferState();
+ virtual QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const;
+ virtual QSize size() const = 0;
+ virtual QWaylandSurface::Origin origin() const = 0;
- inline bool isRegisteredWithBuffer() const { return m_is_registered_for_buffer; }
+ virtual void *lockNativeBuffer() { return nullptr; }
+ virtual void unlockNativeBuffer(void *native_buffer) const { Q_UNUSED(native_buffer); }
- void sendRelease();
- void disown();
-
- void setDisplayed();
+ virtual QImage image() const { return QImage(); }
inline bool isCommitted() const { return m_committed; }
- inline void setCommitted() { m_committed = true; }
- inline bool isDisplayed() const { return m_is_displayed; }
-
+ virtual void setCommitted(QRegion &damage);
bool isDestroyed() { return m_destroyed; }
inline struct ::wl_resource *waylandBufferHandle() const { return m_buffer; }
- void setDestroyIfUnused(bool destroy);
-
- QSize size() const;
- QWaylandSurface::Origin origin() const;
bool isSharedMemory() const { return wl_shm_buffer_get(m_buffer); }
- QImage image() const;
- QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const;
#ifdef QT_WAYLAND_COMPOSITOR_GL
- void bindToTexture() const;
- uint textureForPlane(int plane) const;
- void updateTexture() const;
+ virtual QOpenGLTexture *toOpenGlTexture(int plane = 0) = 0;
#endif
- static bool hasContent(SurfaceBuffer *buffer) { return buffer && buffer->waylandBufferHandle(); }
-private:
+ static bool hasContent(ClientBuffer *buffer) { return buffer && buffer->waylandBufferHandle(); }
+
+protected:
void ref();
void deref();
- void destroyIfUnused();
+ void sendRelease();
+ void setDestroyed();
- QWaylandSurface *m_surface;
- QWaylandCompositor *m_compositor;
struct ::wl_resource *m_buffer;
- int m_bufferScale;
- struct surface_buffer_destroy_listener m_destroy_listener;
+ QRegion m_damage;
+ bool m_textureDirty;
+
+private:
bool m_committed;
- bool m_is_registered_for_buffer;
- bool m_surface_has_buffer;
bool m_destroyed;
- bool m_is_displayed;
-
QAtomicInt m_refCount;
- bool m_used;
- bool m_destroyIfUnused;
-
- static void destroy_listener_callback(wl_listener *listener, void *data);
friend class ::QWaylandBufferRef;
+ friend class BufferManager;
+};
+
+class Q_WAYLAND_COMPOSITOR_EXPORT SharedMemoryBuffer : public ClientBuffer
+{
+public:
+ SharedMemoryBuffer(struct ::wl_resource *bufferResource);
+
+ QSize size() const Q_DECL_OVERRIDE;
+ QWaylandSurface::Origin origin() const Q_DECL_OVERRIDE;
+ QImage image() const;
+
+#ifdef QT_WAYLAND_COMPOSITOR_GL
+ QOpenGLTexture *toOpenGlTexture(int plane = 0) Q_DECL_OVERRIDE;
+
+private:
+ QOpenGLTexture *m_shmTexture;
+#endif
};
}
QT_END_NAMESPACE
-#endif // SURFACEBUFFER_H
+#endif // QWLCLIENTBUFFER_P_H
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
deleted file mode 100644
index df2dded2f..000000000
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL3$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see http://www.qt.io/terms-conditions. For further
-** information use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPLv3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or later as published by the Free
-** Software Foundation and appearing in the file LICENSE.GPL included in
-** the packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 2.0 requirements will be
-** met: http://www.gnu.org/licenses/gpl-2.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qwlsurfacebuffer_p.h"
-
-#ifdef QT_WAYLAND_COMPOSITOR_GL
-#include "hardware_integration/qwlclientbufferintegration_p.h"
-#include <qpa/qplatformopenglcontext.h>
-#endif
-
-#include <QtCore/QDebug>
-
-#include <wayland-server-protocol.h>
-#include "qwaylandsharedmemoryformathelper_p.h"
-
-#include <QtWaylandCompositor/private/qwaylandcompositor_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace QtWayland {
-
-SurfaceBuffer::SurfaceBuffer(QWaylandSurface *surface)
- : m_surface(surface)
- , m_compositor(surface->compositor())
- , m_buffer(0)
- , m_committed(false)
- , m_is_registered_for_buffer(false)
- , m_surface_has_buffer(false)
- , m_destroyed(false)
- , m_is_displayed(false)
- , m_used(false)
- , m_destroyIfUnused(false)
-{
-}
-
-SurfaceBuffer::~SurfaceBuffer()
-{
- if (m_is_registered_for_buffer)
- destructBufferState();
-}
-
-void SurfaceBuffer::initialize(struct ::wl_resource *buffer)
-{
- m_buffer = buffer;
- m_committed = false;
- m_is_registered_for_buffer = true;
- m_surface_has_buffer = true;
- m_is_displayed = false;
- m_destroyed = false;
- m_destroy_listener.surfaceBuffer = this;
- m_destroy_listener.listener.notify = destroy_listener_callback;
- if (buffer) {
-#ifdef QT_WAYLAND_COMPOSITOR_GL
- if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration())
- integration->initializeBuffer(buffer);
-#endif
- wl_signal_add(&buffer->destroy_signal, &m_destroy_listener.listener);
- }
-}
-
-void SurfaceBuffer::destructBufferState()
-{
- if (m_buffer) {
- if (m_committed)
- sendRelease();
- wl_list_remove(&m_destroy_listener.listener.link);
- }
- m_buffer = 0;
- m_committed = false;
- m_is_registered_for_buffer = false;
- m_is_displayed = false;
-}
-
-void SurfaceBuffer::sendRelease()
-{
- Q_ASSERT(m_buffer);
- wl_buffer_send_release(m_buffer);
-}
-
-void SurfaceBuffer::disown()
-{
- m_surface_has_buffer = false;
- destructBufferState();
- destroyIfUnused();
-}
-
-void SurfaceBuffer::setDisplayed()
-{
- m_is_displayed = true;
-}
-
-void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data)
-{
- Q_UNUSED(data);
- struct surface_buffer_destroy_listener *destroy_listener =
- reinterpret_cast<struct surface_buffer_destroy_listener *>(listener);
- SurfaceBuffer *d = destroy_listener->surfaceBuffer;
-
- // Mark the buffer as destroyed and clear m_buffer right away to avoid
- // touching it before it is properly cleaned up.
- d->m_destroyed = true;
- d->m_buffer = 0;
-}
-
-void SurfaceBuffer::ref()
-{
- m_used = m_refCount.ref();
-}
-
-void SurfaceBuffer::deref()
-{
- m_used = m_refCount.deref();
- if (!m_used)
- disown();
-}
-
-void SurfaceBuffer::setDestroyIfUnused(bool destroy)
-{
- m_destroyIfUnused = destroy;
- destroyIfUnused();
-}
-
-void SurfaceBuffer::destroyIfUnused()
-{
- if (!m_used && m_destroyIfUnused)
- delete this;
-}
-
-QSize SurfaceBuffer::size() const
-{
- if (!m_buffer)
- return QSize();
-
- if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) {
- int width = wl_shm_buffer_get_width(shmBuffer);
- int height = wl_shm_buffer_get_height(shmBuffer);
- return QSize(width, height);
- }
-#ifdef QT_WAYLAND_COMPOSITOR_GL
- if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) {
- return integration->bufferSize(m_buffer);
- }
-#endif
-
- return QSize();
-}
-
-QWaylandSurface::Origin SurfaceBuffer::origin() const
-{
- if (isSharedMemory()) {
- return QWaylandSurface::OriginTopLeft;
- }
-
-#ifdef QT_WAYLAND_COMPOSITOR_GL
- if (ClientBufferIntegration *integration = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) {
- return integration->origin(m_buffer);
- }
-#endif
- return QWaylandSurface::OriginTopLeft;
-}
-
-QImage SurfaceBuffer::image() const
-{
- if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) {
- int width = wl_shm_buffer_get_width(shmBuffer);
- int height = wl_shm_buffer_get_height(shmBuffer);
- int bytesPerLine = wl_shm_buffer_get_stride(shmBuffer);
- uchar *data = static_cast<uchar *>(wl_shm_buffer_get_data(shmBuffer));
- return QImage(data, width, height, bytesPerLine, QImage::Format_ARGB32_Premultiplied);
- }
-
- return QImage();
-}
-
-QWaylandBufferRef::BufferFormatEgl SurfaceBuffer::bufferFormatEgl() const
-{
- Q_ASSERT(isSharedMemory() == false);
-
-#ifdef QT_WAYLAND_COMPOSITOR_GL
- if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration())
- return clientInt->bufferFormat(m_buffer);
-#endif
-
- return QWaylandBufferRef::BufferFormatEgl_Null;
-}
-
-#ifdef QT_WAYLAND_COMPOSITOR_GL
-void SurfaceBuffer::bindToTexture() const
-{
- Q_ASSERT(m_compositor);
- if (isSharedMemory()) {
- QImage image = this->image();
- if (image.hasAlphaChannel()) {
- if (image.format() != QImage::Format_RGBA8888) {
- image = image.convertToFormat(QImage::Format_RGBA8888);
- }
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits());
- } else {
- if (image.format() != QImage::Format_RGBX8888) {
- image = image.convertToFormat(QImage::Format_RGBX8888);
- }
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits());
- }
- } else {
- if (QtWayland::ClientBufferIntegration *clientInt = QWaylandCompositorPrivate::get(m_compositor)->clientBufferIntegration()) {
- clientInt->bindTextureToBuffer(m_buffer);
- }
- }
-}
-
-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())
- clientInt->updateTextureForBuffer(m_buffer);
-}
-#endif
-
-}
-
-QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri
index f338ddc05..fa5d76291 100644
--- a/src/compositor/wayland_wrapper/wayland_wrapper.pri
+++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri
@@ -3,21 +3,23 @@ WAYLANDSERVERSOURCES += \
../3rdparty/protocol/wayland.xml \
HEADERS += \
+ wayland_wrapper/qwlbuffermanager_p.h \
+ wayland_wrapper/qwlclientbuffer_p.h \
wayland_wrapper/qwldatadevice_p.h \
wayland_wrapper/qwldatadevicemanager_p.h \
wayland_wrapper/qwldataoffer_p.h \
wayland_wrapper/qwldatasource_p.h \
wayland_wrapper/qwlregion_p.h \
- wayland_wrapper/qwlsurfacebuffer_p.h \
../shared/qwaylandxkb_p.h \
SOURCES += \
+ wayland_wrapper/qwlbuffermanager.cpp \
+ wayland_wrapper/qwlclientbuffer.cpp \
wayland_wrapper/qwldatadevice.cpp \
wayland_wrapper/qwldatadevicemanager.cpp \
wayland_wrapper/qwldataoffer.cpp \
wayland_wrapper/qwldatasource.cpp \
wayland_wrapper/qwlregion.cpp \
- wayland_wrapper/qwlsurfacebuffer.cpp \
../shared/qwaylandxkb.cpp \
INCLUDEPATH += wayland_wrapper
diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp
index 508e88257..940ce82f5 100644
--- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp
+++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.cpp
@@ -40,6 +40,7 @@
#include <qpa/qplatformnativeinterface.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLContext>
+#include <QOpenGLTexture>
#include <qpa/qplatformscreen.h>
#include <QtGui/QWindow>
@@ -60,6 +61,9 @@ public:
: egl_display(EGL_NO_DISPLAY)
, valid(false)
{ }
+
+ static BrcmEglIntegrationPrivate *get(BrcmEglIntegration *integration);
+
EGLDisplay egl_display;
bool valid;
PFNEGLQUERYGLOBALIMAGEBRCMPROC eglQueryGlobalImageBRCM;
@@ -117,25 +121,46 @@ void BrcmEglIntegration::initializeHardware(struct ::wl_display *display)
}
}
-void BrcmEglIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
+QtWayland::ClientBuffer *BrcmEglIntegration::createBufferFor(wl_resource *buffer)
{
- Q_D(BrcmEglIntegration);
+ if (wl_shm_buffer_get(buffer))
+ return nullptr;
+ return new BrcmEglClientBuffer(this, buffer);
+}
+
+BrcmEglIntegrationPrivate *BrcmEglIntegrationPrivate::get(BrcmEglIntegration *integration)
+{
+ return integration->d_ptr.data();
+}
+
+QOpenGLTexture *BrcmEglClientBuffer::toOpenGlTexture(int plane)
+{
+ Q_UNUSED(plane);
+
+ auto d = BrcmEglIntegrationPrivate::get(m_integration);
if (!d->valid) {
qWarning("bindTextureToBuffer failed!");
- return;
+ return nullptr;
}
- BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(buffer);
+ BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(m_buffer);
if (!d->eglQueryGlobalImageBRCM(brcmBuffer->handle(), brcmBuffer->handle() + 2)) {
qWarning("eglQueryGlobalImageBRCM failed!");
- return;
+ return nullptr;
}
EGLImageKHR image = d->eglCreateImageKHR(d->egl_display, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)brcmBuffer->handle(), NULL);
if (image == EGL_NO_IMAGE_KHR)
qWarning("eglCreateImageKHR() failed: %x\n", eglGetError());
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+
+ m_texture->bind();
+
d->glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -144,6 +169,8 @@ void BrcmEglIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
d->eglDestroyImageKHR(d->egl_display, image);
+
+ return m_texture;
}
void BrcmEglIntegration::brcm_bind_resource(Resource *)
@@ -155,11 +182,29 @@ void BrcmEglIntegration::brcm_create_buffer(Resource *resource, uint32_t id, int
new BrcmBuffer(resource->client(), id, QSize(width, height), static_cast<EGLint *>(data->data), data->size / sizeof(EGLint));
}
-QSize BrcmEglIntegration::bufferSize(struct ::wl_resource *buffer) const
+BrcmEglClientBuffer::BrcmEglClientBuffer(BrcmEglIntegration *integration, wl_resource *buffer)
+ : ClientBuffer(buffer)
+ , m_integration(integration)
+ , m_texture(nullptr)
+{
+}
+
+QWaylandBufferRef::BufferFormatEgl BrcmEglClientBuffer::bufferFormatEgl() const
{
- BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(buffer);
+ return QWaylandBufferRef::BufferFormatEgl_RGBA;
+}
+QSize BrcmEglClientBuffer::size() const
+{
+ BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(m_buffer);
return brcmBuffer->size();
}
+QWaylandSurface::Origin BrcmEglClientBuffer::origin() const
+{
+ BrcmBuffer *brcmBuffer = BrcmBuffer::fromResource(m_buffer);
+ return brcmBuffer->isYInverted() ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft;
+}
+
+
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h
index 48dd9c42e..a1d39e4fe 100644
--- a/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h
+++ b/src/hardwareintegration/compositor/brcm-egl/brcmeglintegration.h
@@ -42,6 +42,8 @@
#include <QtCore/QScopedPointer>
+#include <private/qwlclientbuffer_p.h>
+
QT_BEGIN_NAMESPACE
class BrcmEglIntegrationPrivate;
@@ -53,10 +55,7 @@ public:
BrcmEglIntegration();
void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE;
-
- void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
-
- QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
+ QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) Q_DECL_OVERRIDE;
protected:
void brcm_bind_resource(Resource *resource) Q_DECL_OVERRIDE;
@@ -67,6 +66,21 @@ private:
QScopedPointer<BrcmEglIntegrationPrivate> d_ptr;
};
+class BrcmEglClientBuffer : public QtWayland::ClientBuffer
+{
+public:
+ BrcmEglClientBuffer(BrcmEglIntegration *integration, wl_resource *buffer);
+
+ QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE;
+ QSize size() const Q_DECL_OVERRIDE;
+ QWaylandSurface::Origin origin() const Q_DECL_OVERRIDE;
+ QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE;
+private:
+ BrcmEglIntegration *m_integration;
+ QOpenGLTexture *m_texture;
+};
+
+
QT_END_NAMESPACE
#endif // BRCMEGLINTEGRATION_H
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
index 4416d103c..d71fce6ae 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp
@@ -40,6 +40,7 @@
#include <qpa/qplatformnativeinterface.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
#include <qpa/qplatformscreen.h>
#include <QtGui/QWindow>
#include <QtCore/QPointer>
@@ -90,6 +91,10 @@
#define EGL_TEXTURE_Y_XUXV_WL 0x31D9
#endif
+#ifndef EGL_PLATFORM_X11_KHR
+#define EGL_PLATFORM_X11_KHR 0x31D5
+#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);
@@ -110,17 +115,50 @@ typedef void (GL_APIENTRYP PFNGLEGLIMAGETARGETRENDERBUFFERSTORAGEOESPROC) (GLenu
QT_BEGIN_NAMESPACE
+static const char *
+egl_error_string(EGLint code)
+{
+#define MYERRCODE(x) case x: return #x;
+ switch (code) {
+ MYERRCODE(EGL_SUCCESS)
+ MYERRCODE(EGL_NOT_INITIALIZED)
+ MYERRCODE(EGL_BAD_ACCESS)
+ MYERRCODE(EGL_BAD_ALLOC)
+ MYERRCODE(EGL_BAD_ATTRIBUTE)
+ MYERRCODE(EGL_BAD_CONTEXT)
+ MYERRCODE(EGL_BAD_CONFIG)
+ MYERRCODE(EGL_BAD_CURRENT_SURFACE)
+ MYERRCODE(EGL_BAD_DISPLAY)
+ MYERRCODE(EGL_BAD_SURFACE)
+ MYERRCODE(EGL_BAD_MATCH)
+ MYERRCODE(EGL_BAD_PARAMETER)
+ MYERRCODE(EGL_BAD_NATIVE_PIXMAP)
+ MYERRCODE(EGL_BAD_NATIVE_WINDOW)
+ MYERRCODE(EGL_CONTEXT_LOST)
+ default:
+ return "unknown";
+ }
+#undef MYERRCODE
+}
+
struct BufferState
{
BufferState();
+ enum EglMode {
+ ModeNone,
+ ModeEGLImage,
+ ModeEGLStream
+ };
+
EGLint egl_format;
QVarLengthArray<EGLImageKHR, 3> egl_images;
+ QOpenGLTexture *textures[3];
EGLStreamKHR egl_stream;
- GLuint eglstream_texture;
bool isYInverted;
QSize size;
+ EglMode eglMode;
};
class WaylandEglClientBufferIntegrationPrivate
@@ -128,18 +166,14 @@ class WaylandEglClientBufferIntegrationPrivate
public:
WaylandEglClientBufferIntegrationPrivate();
- void attach(struct ::wl_resource *buffer);
- void attach_egl_texture(struct ::wl_resource *buffer, EGLint format);
- void attach_egl_fd_texture(struct ::wl_resource *buffer, EGLNativeFileDescriptorKHR streamFd);
+ void initBuffer(WaylandEglClientBuffer *buffer);
+ void init_egl_texture(WaylandEglClientBuffer *buffer, EGLint format);
+ void init_egl_fd_texture(WaylandEglClientBuffer *buffer, EGLNativeFileDescriptorKHR streamFd);
void register_buffer(struct ::wl_resource *buffer, BufferState state);
- void bindBuffer(struct ::wl_resource *buffer);
-
- static void handle_buffer_destroy(wl_listener *listener, void *data);
EGLDisplay egl_display;
bool valid;
bool display_bound;
- QHash<struct ::wl_resource *, BufferState> buffers;
PFNEGLBINDWAYLANDDISPLAYWL egl_bind_wayland_display;
PFNEGLUNBINDWAYLANDDISPLAYWL egl_unbind_wayland_display;
@@ -151,25 +185,16 @@ public:
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC gl_egl_image_target_texture_2d;
QEGLStreamConvenience *funcs;
-};
-
-struct buffer_destroy_listener : wl_listener
-{
- buffer_destroy_listener()
- : d(0)
- {
- notify = WaylandEglClientBufferIntegrationPrivate::handle_buffer_destroy;
- wl_list_init(&this->link);
+ static WaylandEglClientBufferIntegrationPrivate *get(WaylandEglClientBufferIntegration *integration) {
+ return integration->d_ptr.data();
}
-
- WaylandEglClientBufferIntegrationPrivate *d;
};
BufferState::BufferState()
: egl_format(EGL_TEXTURE_RGBA)
, egl_stream(EGL_NO_STREAM_KHR)
- , eglstream_texture(0)
, isYInverted(true)
+ , eglMode(ModeNone)
{}
WaylandEglClientBufferIntegrationPrivate::WaylandEglClientBufferIntegrationPrivate()
@@ -183,21 +208,21 @@ WaylandEglClientBufferIntegrationPrivate::WaylandEglClientBufferIntegrationPriva
, egl_destroy_image(0)
, gl_egl_image_target_texture_2d(0)
, funcs(Q_NULLPTR)
-{}
+{
+}
-void WaylandEglClientBufferIntegrationPrivate::attach(struct ::wl_resource *buffer)
+void WaylandEglClientBufferIntegrationPrivate::initBuffer(WaylandEglClientBuffer *buffer)
{
EGLint format;
- EGLNativeFileDescriptorKHR streamFd = EGL_NO_FILE_DESCRIPTOR_KHR;
- if (egl_query_wayland_buffer(egl_display, buffer, EGL_TEXTURE_FORMAT, &format))
- attach_egl_texture(buffer, format);
- else if (egl_query_wayland_buffer(egl_display, buffer, EGL_WAYLAND_BUFFER_WL, &streamFd))
- attach_egl_fd_texture(buffer, streamFd);
+ if (egl_query_wayland_buffer(egl_display, buffer->waylandBufferHandle(), EGL_TEXTURE_FORMAT, &format))
+ init_egl_texture(buffer, format);
}
-void WaylandEglClientBufferIntegrationPrivate::attach_egl_texture(struct ::wl_resource *buffer, EGLint format)
+void WaylandEglClientBufferIntegrationPrivate::init_egl_texture(WaylandEglClientBuffer *buffer, EGLint format)
{
+// Non-streaming case
+
// Resolving GL functions may need a context current, so do it only here.
if (!gl_egl_image_target_texture_2d)
gl_egl_image_target_texture_2d = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
@@ -207,12 +232,13 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_texture(struct ::wl_re
return;
}
- BufferState state;
+ BufferState &state = *buffer->d;
state.egl_format = format;
+ state.eglMode = BufferState::ModeEGLImage;
#if defined(EGL_WAYLAND_Y_INVERTED_WL)
EGLint isYInverted;
- EGLBoolean ret = egl_query_wayland_buffer(egl_display, buffer, EGL_WAYLAND_Y_INVERTED_WL, &isYInverted);
+ EGLBoolean ret = egl_query_wayland_buffer(egl_display, buffer->waylandBufferHandle(), 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.
@@ -244,21 +270,21 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_texture(struct ::wl_re
EGLImageKHR image = egl_create_image(egl_display,
EGL_NO_CONTEXT,
EGL_WAYLAND_BUFFER_WL,
- buffer,
+ buffer->waylandBufferHandle(),
attribs);
if (image == EGL_NO_IMAGE_KHR)
qWarning("failed to create EGL image for plane %d", i);
state.egl_images << image;
+ state.textures[i] = nullptr;
}
-
- register_buffer(buffer, state);
}
-void WaylandEglClientBufferIntegrationPrivate::attach_egl_fd_texture(struct ::wl_resource *buffer, EGLNativeFileDescriptorKHR streamFd)
+void WaylandEglClientBufferIntegrationPrivate::init_egl_fd_texture(WaylandEglClientBuffer *buffer, EGLNativeFileDescriptorKHR streamFd)
{
- BufferState state;
+//EglStreams case
+ BufferState &state = *buffer->d;
state.egl_format = EGL_TEXTURE_EXTERNAL_WL;
state.isYInverted = false;
@@ -270,106 +296,37 @@ void WaylandEglClientBufferIntegrationPrivate::attach_egl_fd_texture(struct ::wl
qWarning("%s:%d: eglCreateStreamFromFileDescriptorKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
return;
}
+ state.eglMode = BufferState::ModeEGLStream;
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);
+
+ auto texture = new QOpenGLTexture(static_cast<QOpenGLTexture::Target>(GL_TEXTURE_EXTERNAL_OES));
+ texture->create();
+ state.textures[0] = texture; // TODO: support multiple planes for the streaming case
+
glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, state.eglstream_texture);
+ texture->create();
+ texture->bind();
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture->textureId());
+
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)
-{
- Q_ASSERT(!buffers.contains(buffer));
-
- EGLint width, height;
- egl_query_wayland_buffer(egl_display, buffer, EGL_WIDTH, &width);
- egl_query_wayland_buffer(egl_display, buffer, EGL_HEIGHT, &height);
- state.size = QSize(width, height);
-
- buffers[buffer] = state;
-
- buffer_destroy_listener *destroy_listener = new buffer_destroy_listener;
- destroy_listener->d = this;
- wl_signal_add(&buffer->destroy_signal, destroy_listener);
-}
-
-void WaylandEglClientBufferIntegrationPrivate::bindBuffer(struct ::wl_resource *buffer)
-{
- if (!valid) {
- qWarning("QtCompositor: bindTextureToBuffer() failed");
- return;
- }
+ auto newStream = funcs->stream_consumer_gltexture(egl_display, state.egl_stream);
- if (!buffer || !buffers.contains(buffer))
- return;
-
- const BufferState state = buffers.value(buffer);
-
- if (state.egl_stream != EGL_NO_STREAM_KHR) {
- 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);
-
- const GLenum target = (state.egl_format == EGL_TEXTURE_EXTERNAL_WL) ? GL_TEXTURE_EXTERNAL_OES
- : GL_TEXTURE_2D;
-
- for (int i = 0; i < state.egl_images.size(); i++) {
- glActiveTexture(GL_TEXTURE0 + i);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl_egl_image_target_texture_2d(target, state.egl_images[i]);
- }
-
- glActiveTexture(previousTexture);
+ if (!newStream) {
+ EGLint code = eglGetError();
+ qWarning() << "Could not initialize EGLStream:" << egl_error_string(code) << hex << (long)code;
+ funcs->destroy_stream(egl_display, state.egl_stream);
+ state.egl_stream = EGL_NO_STREAM_KHR;
}
}
-void WaylandEglClientBufferIntegrationPrivate::handle_buffer_destroy(wl_listener *listener, void *data)
-{
- buffer_destroy_listener *destroy_listener = static_cast<buffer_destroy_listener *>(listener);
- WaylandEglClientBufferIntegrationPrivate *self = destroy_listener->d;
- struct ::wl_resource *buffer = static_cast<struct ::wl_resource *>(data);
-
- wl_list_remove(&destroy_listener->link);
- delete destroy_listener;
-
- if (!self->buffers.contains(buffer))
- return;
-
- Q_ASSERT(self);
- Q_ASSERT(buffer);
-
- BufferState state = self->buffers.take(buffer);
-
- // We would need to delete the texture of the egl_stream here, but we can't as this breaks the
- // texture of the new stream when the window is resized. It seems wayland takes care to delete the texture for us.
-
- for (int i = 0; i < state.egl_images.size(); i++)
- self->egl_destroy_image(self->egl_display, state.egl_images[i]);
-
- if (state.egl_stream != EGL_NO_STREAM_KHR)
- self->funcs->destroy_stream(self->egl_display, state.egl_stream);
-}
-
WaylandEglClientBufferIntegration::WaylandEglClientBufferIntegration()
: QtWayland::ClientBufferIntegration()
, d_ptr(new WaylandEglClientBufferIntegrationPrivate)
@@ -438,17 +395,27 @@ void WaylandEglClientBufferIntegration::initializeHardware(struct wl_display *di
d->valid = true;
}
-void WaylandEglClientBufferIntegration::initializeBuffer(struct ::wl_resource *buffer)
+QtWayland::ClientBuffer *WaylandEglClientBufferIntegration::createBufferFor(wl_resource *buffer)
{
- Q_D(WaylandEglClientBufferIntegration);
-
if (wl_shm_buffer_get(buffer))
- return;
-
- if (!buffer || d->buffers.contains(buffer))
- return;
+ return nullptr;
+ return new WaylandEglClientBuffer(this, buffer);
+}
- d->attach(buffer);
+WaylandEglClientBuffer::WaylandEglClientBuffer(WaylandEglClientBufferIntegration *integration, wl_resource *buffer)
+ : ClientBuffer(buffer)
+ , m_integration(integration)
+{
+ auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
+ d = new BufferState;
+ if (buffer && !wl_shm_buffer_get(buffer)) {
+ EGLint width, height;
+ p->egl_query_wayland_buffer(p->egl_display, buffer, EGL_WIDTH, &width);
+ p->egl_query_wayland_buffer(p->egl_display, buffer, EGL_HEIGHT, &height);
+ d->size = QSize(width, height);
+
+ p->initBuffer(this);
+ }
}
static QWaylandBufferRef::BufferFormatEgl formatFromEglFormat(EGLint format) {
@@ -470,117 +437,92 @@ static QWaylandBufferRef::BufferFormatEgl formatFromEglFormat(EGLint format) {
return QWaylandBufferRef::BufferFormatEgl_RGBA;
}
-QWaylandBufferRef::BufferFormatEgl WaylandEglClientBufferIntegration::bufferFormat(wl_resource *buffer)
-{
- Q_D(const WaylandEglClientBufferIntegration);
- return formatFromEglFormat(d->buffers.value(buffer).egl_format);
-}
-
-uint WaylandEglClientBufferIntegration::textureForBuffer(wl_resource *buffer, int plane)
+QWaylandBufferRef::BufferFormatEgl WaylandEglClientBuffer::bufferFormatEgl() const
{
- Q_UNUSED(plane)
- Q_D(WaylandEglClientBufferIntegration);
- if (!buffer)
- return 0;
-
- const BufferState state = d->buffers.value(buffer);
- return state.eglstream_texture;
+ return formatFromEglFormat(d->egl_format);
}
-void WaylandEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
+QOpenGLTexture *WaylandEglClientBuffer::toOpenGlTexture(int plane)
{
- Q_D(WaylandEglClientBufferIntegration);
- d->bindBuffer(buffer);
-}
-
-// 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;
+ if (!m_buffer)
+ return nullptr;
+
+ auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
+ auto texture = d->textures[plane];
+ const auto target = static_cast<QOpenGLTexture::Target>((d->eglMode == BufferState::ModeEGLStream || d->egl_format == EGL_TEXTURE_EXTERNAL_WL) ? GL_TEXTURE_EXTERNAL_OES
+ : GL_TEXTURE_2D);
+ if (!texture) {
+ texture = new QOpenGLTexture(target);
+ texture->create();
+ d->textures[plane] = texture;
}
- if (!buffer)
- return;
- const BufferState state = d->buffers.value(buffer);
+ if (d->eglMode == BufferState::ModeEGLStream) {
+ // EGLStream requires calling acquire on every frame.
+ if (d->egl_stream != EGL_NO_STREAM_KHR) {
+
+ texture->bind();
- 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);
+ EGLint stream_state;
+ p->funcs->query_stream(p->egl_display, d->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());
+ if (stream_state == EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR) {
+ if (p->funcs->stream_consumer_acquire(p->egl_display, d->egl_stream) != EGL_TRUE)
+ qWarning("%s:%d: eglStreamConsumerAcquireKHR failed: 0x%x", Q_FUNC_INFO, __LINE__, eglGetError());
+ }
}
+ } else if (m_textureDirty) {
+ texture->bind();
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ p->gl_egl_image_target_texture_2d(target, d->egl_images[plane]);
}
+ return texture;
}
-QWaylandSurface::Origin WaylandEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const
+void WaylandEglClientBuffer::setCommitted(QRegion &damage)
{
- Q_D(const WaylandEglClientBufferIntegration);
-
- if (d->buffers.contains(buffer))
- return d->buffers[buffer].isYInverted ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft;
-
-#if defined(EGL_WAYLAND_Y_INVERTED_WL)
- EGLint isYInverted;
- EGLBoolean ret = EGL_FALSE;
- if (buffer)
- 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.
- if (ret == EGL_FALSE || isYInverted == EGL_TRUE)
- return QWaylandSurface::OriginTopLeft;
- return QWaylandSurface::OriginBottomLeft;
-#endif
-
- return QtWayland::ClientBufferIntegration::origin(buffer);
+ ClientBuffer::setCommitted(damage);
+ if (d->eglMode == BufferState::ModeNone) {
+ EGLNativeFileDescriptorKHR streamFd = EGL_NO_FILE_DESCRIPTOR_KHR;
+ auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
+ if (p->egl_query_wayland_buffer(p->egl_display, waylandBufferHandle(), EGL_WAYLAND_BUFFER_WL, &streamFd))
+ p->init_egl_fd_texture(this, streamFd);
+ }
}
+QWaylandSurface::Origin WaylandEglClientBuffer::origin() const
+{
+ return d->isYInverted ? QWaylandSurface::OriginTopLeft : QWaylandSurface::OriginBottomLeft;
+}
-void *WaylandEglClientBufferIntegration::lockNativeBuffer(struct ::wl_resource *buffer) const
+void *WaylandEglClientBuffer::lockNativeBuffer()
{
- Q_D(const WaylandEglClientBufferIntegration);
+ auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
- if (d->buffers.contains(buffer) && d->buffers[buffer].egl_stream != EGL_NO_STREAM_KHR)
- return 0;
+ if (d->egl_stream != EGL_NO_STREAM_KHR)
+ return nullptr;
- EGLImageKHR image = d->egl_create_image(d->egl_display, EGL_NO_CONTEXT,
+ EGLImageKHR image = p->egl_create_image(p->egl_display, EGL_NO_CONTEXT,
EGL_WAYLAND_BUFFER_WL,
- buffer, NULL);
+ m_buffer, NULL);
return image;
}
-void WaylandEglClientBufferIntegration::unlockNativeBuffer(void *native_buffer) const
+void WaylandEglClientBuffer::unlockNativeBuffer(void *native_buffer) const
{
- Q_D(const WaylandEglClientBufferIntegration);
-
if (!native_buffer)
return;
+ auto *p = WaylandEglClientBufferIntegrationPrivate::get(m_integration);
+
EGLImageKHR image = static_cast<EGLImageKHR>(native_buffer);
- d->egl_destroy_image(d->egl_display, image);
+ p->egl_destroy_image(p->egl_display, image);
}
-QSize WaylandEglClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const
+QSize WaylandEglClientBuffer::size() const
{
- Q_D(const WaylandEglClientBufferIntegration);
-
- 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 d->size;
}
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
index 74cad708d..5385ac25f 100644
--- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
+++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h
@@ -39,6 +39,7 @@
#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h>
#include <QtCore/QScopedPointer>
+#include <QtWaylandCompositor/private/qwlclientbuffer_p.h>
QT_BEGIN_NAMESPACE
@@ -52,22 +53,34 @@ public:
void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE;
- 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;
+ QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer);
- QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE;
+private:
+ Q_DISABLE_COPY(WaylandEglClientBufferIntegration)
+ QScopedPointer<WaylandEglClientBufferIntegrationPrivate> d_ptr;
+};
- void *lockNativeBuffer(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
- void unlockNativeBuffer(void *native_buffer) const Q_DECL_OVERRIDE;
+struct BufferState;
- QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
+class WaylandEglClientBuffer : public QtWayland::ClientBuffer
+{
+public:
+ QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE;
+ QSize size() const Q_DECL_OVERRIDE;
+ QWaylandSurface::Origin origin() const Q_DECL_OVERRIDE;
+ void *lockNativeBuffer() Q_DECL_OVERRIDE;
+ void unlockNativeBuffer(void *native_buffer) const Q_DECL_OVERRIDE;
+ QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE;
+ void setCommitted(QRegion &damage) Q_DECL_OVERRIDE;
private:
- Q_DISABLE_COPY(WaylandEglClientBufferIntegration)
- QScopedPointer<WaylandEglClientBufferIntegrationPrivate> d_ptr;
+ friend class WaylandEglClientBufferIntegration;
+ friend class WaylandEglClientBufferIntegrationPrivate;
+
+ WaylandEglClientBuffer(WaylandEglClientBufferIntegration* integration, wl_resource *bufferResource);
+
+ BufferState *d;
+ WaylandEglClientBufferIntegration *m_integration;
};
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp
index e858a8e78..1a478052b 100644
--- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp
+++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp
@@ -40,6 +40,7 @@
#include <QtWaylandCompositor/QWaylandCompositor>
#include <QtGui/QGuiApplication>
+#include <QtGui/QOpenGLTexture>
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformopenglcontext.h>
@@ -83,23 +84,38 @@ void XCompositeEglClientBufferIntegration::initializeHardware(struct ::wl_displa
} else {
qFatal("Platform integration doesn't have native interface");
}
- mScreen = XDefaultScreen(mDisplay);
new XCompositeHandler(m_compositor, mDisplay);
}
-void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
+QtWayland::ClientBuffer *XCompositeEglClientBufferIntegration::createBufferFor(wl_resource *buffer)
{
- XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer);
- Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window());
+ if (wl_shm_buffer_get(buffer))
+ return nullptr;
+ return new XCompositeEglClientBuffer(this, buffer);
+}
+
+
+XCompositeEglClientBuffer::XCompositeEglClientBuffer(XCompositeEglClientBufferIntegration *integration, wl_resource *bufferResource)
+ : QtWayland::ClientBuffer(bufferResource)
+ , m_texture(nullptr)
+ , m_integration(integration)
+{
+}
+
+QOpenGLTexture *XCompositeEglClientBuffer::toOpenGlTexture(int plane)
+{
+ Q_UNUSED(plane);
+ XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer);
+ Pixmap pixmap = XCompositeNameWindowPixmap(m_integration->xDisplay(), compositorBuffer->window());
QVector<EGLint> eglConfigSpec = eglbuildSpec();
EGLint matching = 0;
EGLConfig config;
- bool matched = eglChooseConfig(mEglDisplay,eglConfigSpec.constData(),&config,1,&matching);
+ bool matched = eglChooseConfig(m_integration->eglDisplay(),eglConfigSpec.constData(),&config,1,&matching);
if (!matched || !matching) {
qWarning("Could not retrieve a suitable EGL config");
- return;
+ return nullptr;
}
QVector<EGLint> attribList;
@@ -110,29 +126,37 @@ void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resou
attribList.append(EGL_TEXTURE_2D);
attribList.append(EGL_NONE);
- EGLSurface surface = eglCreatePixmapSurface(mEglDisplay,config,pixmap,attribList.constData());
+ EGLSurface surface = eglCreatePixmapSurface(m_integration->eglDisplay(),config,pixmap,attribList.constData());
if (surface == EGL_NO_SURFACE) {
qDebug() << "Failed to create eglsurface" << pixmap << compositorBuffer->window();
}
compositorBuffer->setOrigin(QWaylandSurface::OriginTopLeft);
- if (!eglBindTexImage(mEglDisplay,surface,EGL_BACK_BUFFER)) {
- qDebug() << "Failed to bind";
+ if (!m_texture) {
+ m_texture = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ m_texture->create();
+ }
+ m_texture->bind();
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ if (!eglBindTexImage(m_integration->eglDisplay(),surface,EGL_BACK_BUFFER)) {
+ qWarning() << "Failed to bind";
}
// eglDestroySurface(mEglDisplay,surface);
+ return m_texture;
}
-QWaylandSurface::Origin XCompositeEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const
+
+QWaylandSurface::Origin XCompositeEglClientBuffer::origin() const
{
- XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer);
+ XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer);
return compositorBuffer->origin();
}
-QSize XCompositeEglClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const
+QSize XCompositeEglClientBuffer::size() const
{
- XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer);
+ XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer);
return compositorBuffer->size();
}
diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h
index c14e582ed..ec4ea284b 100644
--- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h
+++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h
@@ -40,7 +40,7 @@
#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h>
#include <QtWaylandCompositor/QWaylandCompositor>
-
+#include <QtWaylandCompositor/private/qwlclientbuffer_p.h>
#include "xlibinclude.h"
#include <EGL/egl.h>
@@ -53,16 +53,30 @@ public:
XCompositeEglClientBufferIntegration();
void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE;
-
- void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
- QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE;
-
- QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
+ QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) Q_DECL_OVERRIDE;
+ inline Display *xDisplay() const { return mDisplay; }
+ inline EGLDisplay eglDisplay() const { return mEglDisplay; }
private:
Display *mDisplay;
EGLDisplay mEglDisplay;
- int mScreen;
+};
+
+class XCompositeEglClientBuffer : public QtWayland::ClientBuffer
+{
+public:
+ XCompositeEglClientBuffer(XCompositeEglClientBufferIntegration *integration, wl_resource *bufferResource);
+
+ QSize size() const;
+ QWaylandSurface::Origin origin() const;
+ QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE;
+ QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE {
+ return QWaylandBufferRef::BufferFormatEgl_RGBA;
+ }
+
+private:
+ QOpenGLTexture *m_texture;
+ XCompositeEglClientBufferIntegration *m_integration;
};
QT_END_NAMESPACE
diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp
index 6f70d2bbf..0b11c2630 100644
--- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp
+++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.cpp
@@ -41,6 +41,7 @@
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatformintegration.h>
#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLTexture>
#include "xcompositebuffer.h"
#include "xcompositehandler.h"
@@ -109,14 +110,31 @@ void XCompositeGLXClientBufferIntegration::initializeHardware(struct ::wl_displa
delete glContext;
}
-void XCompositeGLXClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource *buffer)
+QtWayland::ClientBuffer *XCompositeGLXClientBufferIntegration::createBufferFor(wl_resource *buffer)
{
- XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer);
- Pixmap pixmap = XCompositeNameWindowPixmap(mDisplay, compositorBuffer->window());
+ if (wl_shm_buffer_get(buffer))
+ return nullptr;
+ return new XCompositeGLXClientBuffer(this, buffer);
+}
+
+XCompositeGLXClientBuffer::XCompositeGLXClientBuffer(XCompositeGLXClientBufferIntegration *integration, wl_resource *bufferResource)
+ : QtWayland::ClientBuffer(bufferResource)
+ , m_texture(nullptr)
+ , m_integration(integration)
+ , m_glxPixmap(0)
+{
+}
+
+
+QOpenGLTexture *XCompositeGLXClientBuffer::toOpenGlTexture(int plane)
+{
+ Q_UNUSED(plane);
+ XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer);
+ Pixmap pixmap = XCompositeNameWindowPixmap(m_integration->xDisplay(), compositorBuffer->window());
QVector<int> glxConfigSpec = qglx_buildSpec();
int numberOfConfigs;
- GLXFBConfig *configs = glXChooseFBConfig(mDisplay,mScreen,glxConfigSpec.constData(),&numberOfConfigs);
+ GLXFBConfig *configs = glXChooseFBConfig(m_integration->xDisplay(),m_integration->xScreen(),glxConfigSpec.constData(),&numberOfConfigs);
QVector<int> attribList;
attribList.append(GLX_TEXTURE_FORMAT_EXT);
@@ -124,28 +142,40 @@ void XCompositeGLXClientBufferIntegration::bindTextureToBuffer(struct ::wl_resou
attribList.append(GLX_TEXTURE_TARGET_EXT);
attribList.append(GLX_TEXTURE_2D_EXT);
attribList.append(0);
- GLXPixmap glxPixmap = glXCreatePixmap(mDisplay,*configs,pixmap,attribList.constData());
+
+ if (!m_glxPixmap)
+ m_glxPixmap = glXCreatePixmap(m_integration->xDisplay(), *configs, pixmap, attribList.constData());
uint inverted = 0;
- glXQueryDrawable(mDisplay, glxPixmap, GLX_Y_INVERTED_EXT,&inverted);
+ glXQueryDrawable(m_integration->xDisplay(), m_glxPixmap, GLX_Y_INVERTED_EXT,&inverted);
compositorBuffer->setOrigin(inverted ? QWaylandSurface::OriginBottomLeft : QWaylandSurface::OriginTopLeft);
XFree(configs);
+ auto tex = m_texture;
+ if (!m_texture) {
+ tex = new QOpenGLTexture(QOpenGLTexture::Target2D);
+ tex->create();
+ m_texture = tex;
+ }
+ tex->bind();
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ m_integration->m_glxBindTexImageEXT(m_integration->xDisplay(),m_glxPixmap,GLX_FRONT_EXT, 0);
- m_glxBindTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT, 0);
- //Do we need to change the api so that we do bind and release in the painevent?
- //The specification states that when deleting the texture the color buffer is deleted
-// m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT);
+ // TODO: release in the destructor?
+ // m_glxReleaseTexImageEXT(mDisplay,glxPixmap,GLX_FRONT_EXT);
+ return tex;
}
-QWaylandSurface::Origin XCompositeGLXClientBufferIntegration::origin(struct ::wl_resource *buffer) const
+
+QWaylandSurface::Origin XCompositeGLXClientBuffer::origin() const
{
- return XCompositeBuffer::fromResource(buffer)->origin();
+ XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer);
+ return compositorBuffer->origin();
}
-QSize XCompositeGLXClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const
+QSize XCompositeGLXClientBuffer::size() const
{
- XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer);
+ XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(m_buffer);
return compositorBuffer->size();
}
diff --git a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h
index 9caeb4645..7b63f976e 100644
--- a/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h
+++ b/src/hardwareintegration/compositor/xcomposite-glx/xcompositeglxintegration.h
@@ -38,7 +38,7 @@
#define XCOMPOSITEGLXINTEGRATION_H
#include <QtWaylandCompositor/private/qwlclientbufferintegration_p.h>
-
+#include <QtWaylandCompositor/private/qwlclientbuffer_p.h>
#include "xlibinclude.h"
#define GLX_GLXEXT_PROTOTYPES
@@ -56,21 +56,38 @@ public:
~XCompositeGLXClientBufferIntegration();
void initializeHardware(struct ::wl_display *display) Q_DECL_OVERRIDE;
+ QtWayland::ClientBuffer *createBufferFor(wl_resource *buffer) Q_DECL_OVERRIDE;
- void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE;
- QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE;
-
- QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE;
+ inline Display *xDisplay() const { return mDisplay; }
+ inline int xScreen() const { return mScreen; }
-private:
PFNGLXBINDTEXIMAGEEXTPROC m_glxBindTexImageEXT;
PFNGLXRELEASETEXIMAGEEXTPROC m_glxReleaseTexImageEXT;
+private:
Display *mDisplay;
int mScreen;
XCompositeHandler *mHandler;
};
+class XCompositeGLXClientBuffer : public QtWayland::ClientBuffer
+{
+public:
+ XCompositeGLXClientBuffer(XCompositeGLXClientBufferIntegration *integration, wl_resource *bufferResource);
+
+ QSize size() const;
+ QWaylandSurface::Origin origin() const;
+ QOpenGLTexture *toOpenGlTexture(int plane) Q_DECL_OVERRIDE;
+ QWaylandBufferRef::BufferFormatEgl bufferFormatEgl() const Q_DECL_OVERRIDE {
+ return QWaylandBufferRef::BufferFormatEgl_RGBA;
+ }
+
+private:
+ QOpenGLTexture *m_texture;
+ XCompositeGLXClientBufferIntegration *m_integration;
+ GLXPixmap m_glxPixmap;
+};
+
QT_END_NAMESPACE
#endif // XCOMPOSITEGLXINTEGRATION_H