summaryrefslogtreecommitdiffstats
path: root/src/compositor
diff options
context:
space:
mode:
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