summaryrefslogtreecommitdiffstats
path: root/src/compositor
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 /src/compositor
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>
Diffstat (limited to 'src/compositor')
-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
18 files changed, 551 insertions, 485 deletions
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