summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGiulio Camuffo <giulio.camuffo@jollamobile.com>2014-03-25 14:19:55 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-04-29 10:09:31 +0200
commitfc439e40e37f9c0b3108225f951fb19bb3abee80 (patch)
tree851bf52ee2004b3b201b5e86df7a4d4db7f79a2c
parentc551e6df6c77f65a0db62b3ad4db539e86b75a30 (diff)
Rework the way buffers are used and rendered
The current way buffers are handled is sub-optimal. They are hidden inside QtWayland::Surface and the actual renderer, be it QtQuick or anything else, cannot get a direct hold of them, nor it can directly control when the underlying textures are created or deleted. The main additions in this commit are the splitting of the QtQuick code path and the new QWaylandBufferRef and QWaylandBufferAttacher classes. QWaylandBufferRef allows a renderer to retain a reference to a wl_buffer even after the underlying Surface discarded it. That allows the renderer to directly decide when to destroy the texture of the buffer. QWaylandBufferAttacher is a pure virtual class which must be implemented by the renderer. Instances of it will be assigned to the QWaylandSurfaces, created. Its attach() virtual method will then be called when a new buffer is committed to the surface. The renderer can then choose to immediately create a texture or wait for some later time. It is its responsibility to create and destroy the GL texture, it will not happen automatically. This functionality is implemented for QtQuick in the new QWaylandQuickCompositor and QWaylandQuickSurface classes. Change-Id: I674b4e5fb8c65c3b1c582e33ff3a0b0e45f2acc9 Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
-rw-r--r--examples/qml-compositor/WindowContainer.qml27
-rw-r--r--examples/qml-compositor/main.cpp48
-rw-r--r--examples/qml-compositor/main.qml30
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.cpp108
-rw-r--r--examples/qwindow-compositor/qwindowcompositor.h4
-rw-r--r--examples/server-buffer/compositor/main.cpp34
-rw-r--r--examples/server-buffer/compositor/qml/main.qml17
-rw-r--r--src/compositor/compositor_api/compositor_api.pri15
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.cpp131
-rw-r--r--src/compositor/compositor_api/qwaylandbufferref.h87
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.cpp37
-rw-r--r--src/compositor/compositor_api/qwaylandcompositor.h5
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.cpp102
-rw-r--r--src/compositor/compositor_api/qwaylandquickcompositor.h64
-rw-r--r--src/compositor/compositor_api/qwaylandquicksurface.cpp241
-rw-r--r--src/compositor/compositor_api/qwaylandquicksurface.h91
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp220
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.h57
-rw-r--r--src/compositor/compositor_api/qwaylandsurface_p.h68
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.cpp173
-rw-r--r--src/compositor/compositor_api/qwaylandsurfaceitem.h41
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor.cpp55
-rw-r--r--src/compositor/wayland_wrapper/qwlcompositor_p.h12
-rw-r--r--src/compositor/wayland_wrapper/qwlinputdevice.cpp5
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard.cpp12
-rw-r--r--src/compositor/wayland_wrapper/qwlkeyboard_p.h4
-rw-r--r--src/compositor/wayland_wrapper/qwllistener.cpp70
-rw-r--r--src/compositor/wayland_wrapper/qwllistener_p.h75
-rw-r--r--src/compositor/wayland_wrapper/qwlpointer.cpp14
-rw-r--r--src/compositor/wayland_wrapper/qwlpointer_p.h9
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface.cpp124
-rw-r--r--src/compositor/wayland_wrapper/qwlsurface_p.h60
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp33
-rw-r--r--src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h6
-rw-r--r--src/compositor/wayland_wrapper/qwltouch.cpp14
-rw-r--r--src/compositor/wayland_wrapper/qwltouch_p.h8
-rw-r--r--src/compositor/wayland_wrapper/wayland_wrapper.pri2
-rw-r--r--tests/auto/compositor/tst_compositor.cpp26
38 files changed, 1474 insertions, 655 deletions
diff --git a/examples/qml-compositor/WindowContainer.qml b/examples/qml-compositor/WindowContainer.qml
index 701b46d24..77dd1d4dc 100644
--- a/examples/qml-compositor/WindowContainer.qml
+++ b/examples/qml-compositor/WindowContainer.qml
@@ -40,6 +40,7 @@
import QtQuick 2.0
import QtQuick.Window 2.0
+import QtCompositor 1.0
Item {
id: container
@@ -52,10 +53,20 @@ Item {
visible: isFullscreen || !root.hasFullscreenWindow
onVisibleChanged: {
- child.clientRenderingEnabled = visible
+ child.surface.clientRenderingEnabled = visible
console.log("visibility changed: " + visible);
}
+ WaylandSurfaceItem {
+ id: surfaceItem
+ anchors.fill: parent
+ touchEventsEnabled: true
+
+ onSurfaceDestroyed: {
+ destroyAnimation.start();
+ }
+ }
+
opacity: 0
property real targetX
@@ -64,7 +75,7 @@ Item {
property real targetHeight
property real targetScale
- property variant child: null
+ property variant child: surfaceItem
property variant chrome: null
property bool animationsEnabled: false
property bool isFullscreen: state === "fullscreen"
@@ -168,11 +179,17 @@ Item {
NumberAnimation { target: scaleTransform; property: "yScale"; easing.type: Easing.Linear; to: 0.01; duration: 200; }
NumberAnimation { target: scaleTransform; property: "xScale"; easing.type: Easing.Linear; to: 0.01; duration: 150; }
NumberAnimation { target: container; property: "opacity"; easing.type: Easing.Linear; to: 0.0; duration: 150; }
- ScriptAction { script: container.parent.removeWindow(child); }
+ ScriptAction { script: container.parent.removeWindow(container) }
+ }
+ SequentialAnimation {
+ id: unmapAnimation
+ NumberAnimation { target: container; property: "opacity"; easing.type: Easing.Linear; to: 0.0; duration: 150; }
+ ScriptAction { script: container.parent.removeWindow(container) }
}
- function runDestroyAnimation() {
- destroyAnimation.start();
+ Connections {
+ target: container.child.surface
+ onUnmapped: unmapAnimation.start()
}
Image {
diff --git a/examples/qml-compositor/main.cpp b/examples/qml-compositor/main.cpp
index 93b23c0e3..7ebcb6c29 100644
--- a/examples/qml-compositor/main.cpp
+++ b/examples/qml-compositor/main.cpp
@@ -38,9 +38,8 @@
**
****************************************************************************/
-#include "qwaylandcompositor.h"
-#include "qwaylandsurface.h"
-#include "qwaylandsurfaceitem.h"
+#include "qwaylandquickcompositor.h"
+#include "qwaylandquicksurface.h"
#include <QGuiApplication>
#include <QTimer>
@@ -52,14 +51,14 @@
#include <QQuickItem>
#include <QQuickView>
-class QmlCompositor : public QQuickView, public QWaylandCompositor
+class QmlCompositor : public QQuickView, public QWaylandQuickCompositor
{
Q_OBJECT
- Q_PROPERTY(QWaylandSurface* fullscreenSurface READ fullscreenSurface WRITE setFullscreenSurface NOTIFY fullscreenSurfaceChanged)
+ Q_PROPERTY(QWaylandQuickSurface* fullscreenSurface READ fullscreenSurface WRITE setFullscreenSurface NOTIFY fullscreenSurfaceChanged)
public:
QmlCompositor()
- : QWaylandCompositor(this, 0, DefaultExtensions | SubSurfaceExtension)
+ : QWaylandQuickCompositor(this, 0, DefaultExtensions | SubSurfaceExtension)
, m_fullscreenSurface(0)
{
setSource(QUrl("main.qml"));
@@ -67,11 +66,10 @@ public:
setColor(Qt::black);
winId();
- connect(this, SIGNAL(beforeSynchronizing()), this, SLOT(startFrame()), Qt::DirectConnection);
connect(this, SIGNAL(afterRendering()), this, SLOT(sendCallbacks()));
}
- QWaylandSurface *fullscreenSurface() const
+ QWaylandQuickSurface *fullscreenSurface() const
{
return m_fullscreenSurface;
}
@@ -87,12 +85,7 @@ public slots:
qvariant_cast<QObject *>(window)->deleteLater();
}
- void destroyClientForWindow(QVariant window) {
- QWaylandSurface *surface = qobject_cast<QWaylandSurfaceItem *>(qvariant_cast<QObject *>(window))->surface();
- destroyClientForSurface(surface);
- }
-
- void setFullscreenSurface(QWaylandSurface *surface) {
+ void setFullscreenSurface(QWaylandQuickSurface *surface) {
if (surface == m_fullscreenSurface)
return;
m_fullscreenSurface = surface;
@@ -101,34 +94,25 @@ public slots:
private slots:
void surfaceMapped() {
- QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
+ QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(sender());
//Ignore surface if it's not a window surface
if (!surface->hasShellSurface())
return;
- QWaylandSurfaceItem *item = surface->surfaceItem();
- //Create a WaylandSurfaceItem if we have not yet
- if (!item)
- item = new QWaylandSurfaceItem(surface, rootObject());
-
- item->setTouchEventsEnabled(true);
- //item->takeFocus();
- emit windowAdded(QVariant::fromValue(static_cast<QQuickItem *>(item)));
+ emit windowAdded(QVariant::fromValue(surface));
}
void surfaceUnmapped() {
- QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
+ QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(sender());
if (surface == m_fullscreenSurface)
m_fullscreenSurface = 0;
- QQuickItem *item = surface->surfaceItem();
- emit windowDestroyed(QVariant::fromValue(item));
+ emit windowDestroyed(QVariant::fromValue(surface));
}
void surfaceDestroyed(QObject *object) {
- QWaylandSurface *surface = static_cast<QWaylandSurface *>(object);
+ QWaylandQuickSurface *surface = static_cast<QWaylandQuickSurface *>(object);
if (surface == m_fullscreenSurface)
m_fullscreenSurface = 0;
- QQuickItem *item = surface->surfaceItem();
- emit windowDestroyed(QVariant::fromValue(item));
+ emit windowDestroyed(QVariant::fromValue(surface));
}
void sendCallbacks() {
@@ -137,9 +121,6 @@ private slots:
else
sendFrameCallbacks(surfaces());
}
- void startFrame() {
- frameStarted();
- }
protected:
void resizeEvent(QResizeEvent *event)
@@ -155,7 +136,7 @@ protected:
}
private:
- QWaylandSurface *m_fullscreenSurface;
+ QWaylandQuickSurface *m_fullscreenSurface;
};
int main(int argc, char *argv[])
@@ -170,7 +151,6 @@ int main(int argc, char *argv[])
compositor.rootContext()->setContextProperty("compositor", &compositor);
QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant)));
- QObject::connect(&compositor, SIGNAL(windowDestroyed(QVariant)), compositor.rootObject(), SLOT(windowDestroyed(QVariant)));
QObject::connect(&compositor, SIGNAL(windowResized(QVariant)), compositor.rootObject(), SLOT(windowResized(QVariant)));
return app.exec();
diff --git a/examples/qml-compositor/main.qml b/examples/qml-compositor/main.qml
index 7b152280e..120c92bdb 100644
--- a/examples/qml-compositor/main.qml
+++ b/examples/qml-compositor/main.qml
@@ -39,6 +39,7 @@
****************************************************************************/
import QtQuick 2.0
+import QtCompositor 1.0
import "compositor.js" as CompositorLogic
Item {
@@ -84,15 +85,15 @@ Item {
function windowAdded(window) {
var windowContainerComponent = Qt.createComponent("WindowContainer.qml");
var windowContainer = windowContainerComponent.createObject(root);
+ console.log(windowContainerComponent.errorString());
- window.parent = windowContainer;
+ windowContainer.child.surface = window;
- windowContainer.targetWidth = window.width;
- windowContainer.targetHeight = window.height;
- windowContainer.child = window;
+ windowContainer.targetWidth = window.size.width;
+ windowContainer.targetHeight = window.size.height;
var windowChromeComponent = Qt.createComponent("WindowChrome.qml");
- var windowChrome = windowChromeComponent.createObject(window);
+ var windowChrome = windowChromeComponent.createObject(windowContainer.child);
CompositorLogic.addWindow(windowContainer);
@@ -102,25 +103,16 @@ Item {
}
function windowResized(window) {
- var windowContainer = window.parent;
- windowContainer.width = window.width;
- windowContainer.height = window.height;
+ window.width = window.surface.size.width;
+ window.height = window.surface.size.height;
CompositorLogic.relayout();
}
- function windowDestroyed(window) {
- var windowContainer = window.parent;
- if (windowContainer.runDestroyAnimation)
- windowContainer.runDestroyAnimation();
- }
-
function removeWindow(window) {
- var windowContainer = window.parent;
- CompositorLogic.removeWindow(windowContainer);
- windowContainer.chrome.destroy();
- windowContainer.destroy();
- compositor.destroyWindow(window);
+ CompositorLogic.removeWindow(window);
+ window.chrome.destroy();
+ window.destroy();
}
onHeightChanged: CompositorLogic.relayout();
diff --git a/examples/qwindow-compositor/qwindowcompositor.cpp b/examples/qwindow-compositor/qwindowcompositor.cpp
index e0f213aa4..aa6afd7aa 100644
--- a/examples/qwindow-compositor/qwindowcompositor.cpp
+++ b/examples/qwindow-compositor/qwindowcompositor.cpp
@@ -52,6 +52,55 @@
#include <QPainter>
#include <QtCompositor/qwaylandinput.h>
+#include <QtCompositor/qwaylandbufferref.h>
+
+static GLuint textureFromImage(const QImage &image)
+{
+ GLuint texture = 0;
+ glGenTextures(1, &texture);
+ glBindTexture(GL_TEXTURE_2D, texture);
+ QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tx.constBits());
+ glBindTexture(GL_TEXTURE_2D, 0);
+ return texture;
+}
+
+class BufferAttacher : public QWaylandBufferAttacher
+{
+public:
+ void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE
+ {
+ if (bufferRef) {
+ if (ownTexture)
+ glDeleteTextures(1, &texture);
+ else
+ bufferRef.destroyTexture();
+ }
+
+ bufferRef = ref;
+
+ if (bufferRef) {
+ if (bufferRef.isShm()) {
+ texture = textureFromImage(bufferRef.image());
+ ownTexture = true;
+ } else {
+ texture = bufferRef.createTexture();
+ ownTexture = false;
+ }
+ }
+ }
+
+ QImage image() const
+ {
+ if (!bufferRef || !bufferRef.isShm())
+ return QImage();
+ return bufferRef.image();
+ }
+
+ QWaylandBufferRef bufferRef;
+ GLuint texture;
+ bool ownTexture;
+};
QWindowCompositor::QWindowCompositor(QOpenGLWindow *window)
: QWaylandCompositor(window, 0, DefaultExtensions | SubSurfaceExtension)
@@ -118,9 +167,9 @@ void QWindowCompositor::ensureKeyboardFocusSurface(QWaylandSurface *oldSurface)
defaultInputDevice()->setKeyboardFocus(m_surfaces.isEmpty() ? 0 : m_surfaces.last());
}
-void QWindowCompositor::surfaceDestroyed(QObject *object)
+void QWindowCompositor::surfaceDestroyed()
{
- QWaylandSurface *surface = static_cast<QWaylandSurface *>(object);
+ QWaylandSurface *surface = static_cast<QWaylandSurface *>(sender());
m_surfaces.removeOne(surface);
ensureKeyboardFocusSurface(surface);
m_renderScheduler.start(0);
@@ -157,6 +206,7 @@ void QWindowCompositor::surfaceUnmapped()
m_surfaces.insert(0, surface);
ensureKeyboardFocusSurface(surface);
+ m_renderScheduler.start(0);
}
void QWindowCompositor::surfaceCommitted()
@@ -178,13 +228,15 @@ void QWindowCompositor::surfaceCommitted(QWaylandSurface *surface)
void QWindowCompositor::surfaceCreated(QWaylandSurface *surface)
{
- connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
+ connect(surface, SIGNAL(surfaceDestroyed()), this, SLOT(surfaceDestroyed()));
connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
connect(surface, SIGNAL(unmapped()), this, SLOT(surfaceUnmapped()));
- connect(surface, SIGNAL(committed()), this, SLOT(surfaceCommitted()));
+ connect(surface, SIGNAL(redraw()), this, SLOT(surfaceCommitted()));
connect(surface, SIGNAL(extendedSurfaceReady()), this, SLOT(sendExpose()));
connect(surface, SIGNAL(posChanged()), this, SLOT(surfacePosChanged()));
m_renderScheduler.start(0);
+
+ surface->setBufferAttacher(new BufferAttacher);
}
void QWindowCompositor::sendExpose()
@@ -197,7 +249,10 @@ void QWindowCompositor::updateCursor()
{
if (!m_cursorSurface)
return;
- QCursor cursor(QPixmap::fromImage(m_cursorSurface->image()), m_cursorHotspotX, m_cursorHotspotY);
+
+ QImage image = static_cast<BufferAttacher *>(m_cursorSurface->bufferAttacher())->image();
+
+ QCursor cursor(QPixmap::fromImage(image), m_cursorHotspotX, m_cursorHotspotY);
static bool cursorIsSet = false;
if (cursorIsSet) {
QGuiApplication::changeOverrideCursor(cursor);
@@ -215,11 +270,13 @@ QPointF QWindowCompositor::toSurface(QWaylandSurface *surface, const QPointF &po
void QWindowCompositor::setCursorSurface(QWaylandSurface *surface, int hotspotX, int hotspotY)
{
if ((m_cursorSurface != surface) && surface)
- connect(surface, SIGNAL(damaged(QRect)), this, SLOT(updateCursor()));
+ connect(surface, SIGNAL(configure()), this, SLOT(updateCursor()));
m_cursorSurface = surface;
m_cursorHotspotX = hotspotX;
m_cursorHotspotY = hotspotY;
+ if (!m_cursorSurface->bufferAttacher())
+ m_cursorSurface->setBufferAttacher(new BufferAttacher);
}
QWaylandSurface *QWindowCompositor::surfaceAt(const QPointF &point, QPointF *local)
@@ -236,34 +293,14 @@ QWaylandSurface *QWindowCompositor::surfaceAt(const QPointF &point, QPointF *loc
return 0;
}
-static GLuint textureFromImage(const QImage &image)
-{
- GLuint texture = 0;
- glGenTextures(1, &texture);
- glBindTexture(GL_TEXTURE_2D, texture);
- QImage tx = image.convertToFormat(QImage::Format_RGBA8888_Premultiplied);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tx.width(), tx.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, tx.constBits());
- glBindTexture(GL_TEXTURE_2D, 0);
- return texture;
-}
-
-GLuint QWindowCompositor::composeSurface(QWaylandSurface *surface, bool *textureOwned)
+GLuint QWindowCompositor::composeSurface(QWaylandSurface *surface)
{
- GLuint texture = 0;
-
QSize windowSize = surface->size();
- surface->swapBuffers();
QOpenGLFunctions *functions = QOpenGLContext::currentContext()->functions();
functions->glBindFramebuffer(GL_FRAMEBUFFER, m_surface_fbo);
- if (surface->type() == QWaylandSurface::Shm) {
- texture = textureFromImage(surface->image());
- *textureOwned = true;
- } else if (surface->type() == QWaylandSurface::Texture) {
- texture = surface->texture();
- *textureOwned = false;
- }
+ GLuint texture = static_cast<BufferAttacher *>(surface->bufferAttacher())->texture;
functions->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_TEXTURE_2D, texture, 0);
@@ -287,19 +324,11 @@ void QWindowCompositor::paintChildren(QWaylandSurface *surface, QWaylandSurface
QWaylandSurface *subSurface = i.next();
QPointF p = subSurface->mapTo(window,QPointF(0,0));
QSize subSize = subSurface->size();
- subSurface->swapBuffers();
if (subSize.isValid()) {
- GLuint texture = 0;
- if (subSurface->type() == QWaylandSurface::Texture) {
- texture = subSurface->texture();
- } else if (surface->type() == QWaylandSurface::Shm) {
- texture = textureFromImage(subSurface->image());
- }
+ GLuint texture = static_cast<BufferAttacher *>(subSurface->bufferAttacher())->texture;
QRect geo(p.toPoint(),subSize);
if (texture > 0)
m_textureBlitter->drawTexture(texture,geo,windowSize,0,window->isYInverted(),subSurface->isYInverted());
- if (surface->type() == QWaylandSurface::Shm)
- glDeleteTextures(1, &texture);
}
paintChildren(subSurface,window,windowSize);
}
@@ -326,12 +355,9 @@ void QWindowCompositor::render()
foreach (QWaylandSurface *surface, m_surfaces) {
if (!surface->visible())
continue;
- bool ownsTexture;
- GLuint texture = composeSurface(surface, &ownsTexture);
+ GLuint texture = composeSurface(surface);
QRect geo(surface->pos().toPoint(),surface->size());
m_textureBlitter->drawTexture(texture,geo,m_window->size(),0,false,surface->isYInverted());
- if (ownsTexture)
- glDeleteTextures(1, &texture);
}
m_textureBlitter->release();
diff --git a/examples/qwindow-compositor/qwindowcompositor.h b/examples/qwindow-compositor/qwindowcompositor.h
index e26a09ebc..3ecbdbc1a 100644
--- a/examples/qwindow-compositor/qwindowcompositor.h
+++ b/examples/qwindow-compositor/qwindowcompositor.h
@@ -58,7 +58,7 @@ public:
~QWindowCompositor();
private slots:
- void surfaceDestroyed(QObject *object);
+ void surfaceDestroyed();
void surfaceMapped();
void surfaceUnmapped();
void surfaceCommitted();
@@ -71,7 +71,7 @@ protected:
QWaylandSurface* surfaceAt(const QPointF &point, QPointF *local = 0);
- GLuint composeSurface(QWaylandSurface *surface, bool *textureOwned);
+ GLuint composeSurface(QWaylandSurface *surface);
void paintChildren(QWaylandSurface *surface, QWaylandSurface *window, const QSize &windowSize);
diff --git a/examples/server-buffer/compositor/main.cpp b/examples/server-buffer/compositor/main.cpp
index ff375a8c6..a30ea0895 100644
--- a/examples/server-buffer/compositor/main.cpp
+++ b/examples/server-buffer/compositor/main.cpp
@@ -38,9 +38,8 @@
**
****************************************************************************/
-#include "qwaylandcompositor.h"
+#include "qwaylandquickcompositor.h"
#include "qwaylandsurface.h"
-#include "qwaylandsurfaceitem.h"
#include <QGuiApplication>
#include <QTimer>
@@ -63,14 +62,14 @@
class QmlCompositor
: public QQuickView
- , public QWaylandCompositor
+ , public QWaylandQuickCompositor
, public QtWaylandServer::qt_share_buffer
{
Q_OBJECT
public:
QmlCompositor()
- : QWaylandCompositor(this, 0, DefaultExtensions | SubSurfaceExtension)
+ : QWaylandQuickCompositor(this, 0, DefaultExtensions | SubSurfaceExtension)
, QtWaylandServer::qt_share_buffer(QWaylandCompositor::handle()->wl_display())
, m_server_buffer_32_bit(0)
, m_server_buffer_item_32_bit(0)
@@ -83,7 +82,6 @@ public:
create();
grabWindow();
- connect(this, SIGNAL(beforeSynchronizing()), this, SLOT(startFrame()), Qt::DirectConnection);
connect(this, SIGNAL(afterRendering()), this, SLOT(sendCallbacks()));
connect(this, SIGNAL(sceneGraphInitialized()), this, SLOT(initiateServerBuffer()),Qt::DirectConnection);
@@ -98,38 +96,26 @@ signals:
void serverBuffersCreated();
public slots:
- void destroyWindow(QVariant window)
- {
- qvariant_cast<QObject *>(window)->deleteLater();
- }
-
void destroyClientForWindow(QVariant window)
{
- QWaylandSurface *surface = qobject_cast<QWaylandSurfaceItem *>(qvariant_cast<QObject *>(window))->surface();
+ QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(qvariant_cast<QObject *>(window));
destroyClientForSurface(surface);
}
private slots:
void surfaceMapped() {
QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
- QQuickItem *item = surface->surfaceItem();
- emit windowAdded(QVariant::fromValue(static_cast<QQuickItem *>(item)));
+ emit windowAdded(QVariant::fromValue(surface));
}
void surfaceUnmapped() {
QWaylandSurface *surface = qobject_cast<QWaylandSurface *>(sender());
- QQuickItem *item = surface->surfaceItem();
- emit windowDestroyed(QVariant::fromValue(item));
+ emit windowDestroyed(QVariant::fromValue(surface));
}
void surfaceDestroyed(QObject *object) {
QWaylandSurface *surface = static_cast<QWaylandSurface *>(object);
- QQuickItem *item = surface->surfaceItem();
- emit windowDestroyed(QVariant::fromValue(item));
- }
-
- void startFrame() {
- frameStarted();
+ emit windowDestroyed(QVariant::fromValue(surface));
}
void sendCallbacks() {
@@ -219,11 +205,6 @@ protected:
}
void surfaceCreated(QWaylandSurface *surface) {
- QWaylandSurfaceItem *item = new QWaylandSurfaceItem(surface, rootObject());
- item->setUseTextureAlpha(true);
- item->setTouchEventsEnabled(true);
-
- connect(surface, SIGNAL(destroyed(QObject *)), this, SLOT(surfaceDestroyed(QObject *)));
connect(surface, SIGNAL(mapped()), this, SLOT(surfaceMapped()));
connect(surface,SIGNAL(unmapped()), this,SLOT(surfaceUnmapped()));
}
@@ -270,7 +251,6 @@ int main(int argc, char *argv[])
compositor.rootContext()->setContextProperty("compositor", &compositor);
QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant)));
- QObject::connect(&compositor, SIGNAL(windowDestroyed(QVariant)), compositor.rootObject(), SLOT(windowDestroyed(QVariant)));
QObject::connect(&compositor, SIGNAL(windowResized(QVariant)), compositor.rootObject(), SLOT(windowResized(QVariant)));
QObject::connect(&compositor, SIGNAL(serverBufferItemCreated(QVariant)), compositor.rootObject(), SLOT(serverBufferItemCreated(QVariant)));
diff --git a/examples/server-buffer/compositor/qml/main.qml b/examples/server-buffer/compositor/qml/main.qml
index 231fb5169..1beddbf1d 100644
--- a/examples/server-buffer/compositor/qml/main.qml
+++ b/examples/server-buffer/compositor/qml/main.qml
@@ -39,6 +39,7 @@
****************************************************************************/
import QtQuick 2.0
+import QtCompositor 1.0
Item {
id: root
@@ -58,15 +59,21 @@ Item {
anchors.fill: parent
}
- function windowAdded(window) {
- window.parent = root;
+ Component {
+ id: windowItem
+ WaylandSurfaceItem {
+ onSurfaceDestroyed: {
+ destroy();
+ }
+ }
}
- function windowResized(window) {
+ function windowAdded(window) {
+ var item = windowItem.createObject(root);
+ item.surface = window;
}
- function windowDestroyed(window) {
- compositor.destroyWindow(window);
+ function windowResized(window) {
}
function removeWindow(window) {
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 87d28003c..8e7fd3ace 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -2,29 +2,34 @@ INCLUDEPATH += compositor_api
HEADERS += \
compositor_api/qwaylandcompositor.h \
+ compositor_api/qwaylandcompositor_p.h \
compositor_api/qwaylandsurface.h \
+ compositor_api/qwaylandsurface_p.h \
compositor_api/qwaylandinput.h \
compositor_api/qwaylandinputpanel.h \
- compositor_api/qwaylanddrag.h
+ compositor_api/qwaylanddrag.h \
+ compositor_api/qwaylandbufferref.h
SOURCES += \
compositor_api/qwaylandcompositor.cpp \
compositor_api/qwaylandsurface.cpp \
compositor_api/qwaylandinput.cpp \
compositor_api/qwaylandinputpanel.cpp \
- compositor_api/qwaylanddrag.cpp
+ compositor_api/qwaylanddrag.cpp \
+ compositor_api/qwaylandbufferref.cpp
QT += core-private
qtHaveModule(quick) {
SOURCES += \
+ compositor_api/qwaylandquickcompositor.cpp \
+ compositor_api/qwaylandquicksurface.cpp \
compositor_api/qwaylandsurfaceitem.cpp
HEADERS += \
+ compositor_api/qwaylandquickcompositor.h \
+ compositor_api/qwaylandquicksurface.h \
compositor_api/qwaylandsurfaceitem.h
- DEFINES += QT_COMPOSITOR_QUICK
-
QT += qml quick
- QT += quick-private gui-private
}
diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp
new file mode 100644
index 000000000..67554c7cb
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandbufferref.cpp
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QDebug>
+#include <QAtomicInt>
+
+#include "qwaylandbufferref.h"
+#include "wayland_wrapper/qwlsurfacebuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandBufferRefPrivate
+{
+public:
+ QtWayland::SurfaceBuffer *buffer;
+};
+
+QWaylandBufferRef::QWaylandBufferRef()
+ : d(new QWaylandBufferRefPrivate)
+{
+ d->buffer = 0;
+}
+
+QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer)
+ : d(new QWaylandBufferRefPrivate)
+{
+ d->buffer = buffer;
+ if (buffer)
+ buffer->m_refCount.ref();
+}
+
+QWaylandBufferRef::QWaylandBufferRef(const QWaylandBufferRef &ref)
+ : d(new QWaylandBufferRefPrivate)
+{
+ d->buffer = 0;
+ *this = ref;
+}
+
+QWaylandBufferRef::~QWaylandBufferRef()
+{
+ if (d->buffer && !d->buffer->m_refCount.deref())
+ d->buffer->disown();
+ delete d;
+}
+
+QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref)
+{
+ if (d->buffer && !d->buffer->m_refCount.deref())
+ d->buffer->disown();
+
+ d->buffer = ref.d->buffer;
+ if (d->buffer)
+ d->buffer->m_refCount.ref();
+
+ return *this;
+}
+
+QWaylandBufferRef::operator bool() const
+{
+ return d->buffer && d->buffer->waylandBufferHandle();
+}
+
+bool QWaylandBufferRef::isShm() const
+{
+ return d->buffer->isShmBuffer();
+}
+
+QImage QWaylandBufferRef::image() const
+{
+ if (d->buffer->isShmBuffer())
+ return d->buffer->image();
+ return QImage();
+}
+
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+
+GLuint QWaylandBufferRef::createTexture()
+{
+ if (!d->buffer->isShmBuffer() && !d->buffer->textureCreated()) {
+ d->buffer->createTexture();
+ }
+ return d->buffer->texture();
+}
+
+void QWaylandBufferRef::destroyTexture()
+{
+ if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) {
+ d->buffer->destroyTexture();
+ }
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h
new file mode 100644
index 000000000..0d1573bbb
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandbufferref.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDBUFFERREF_H
+#define QWAYLANDBUFFERREF_H
+
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+#include <QtGui/qopengl.h>
+#endif
+
+#include <QtCompositor/qwaylandexport.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtWayland
+{
+ class SurfaceBuffer;
+}
+
+class Q_COMPOSITOR_EXPORT QWaylandBufferRef
+{
+public:
+ QWaylandBufferRef();
+ explicit QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer);
+ QWaylandBufferRef(const QWaylandBufferRef &ref);
+ ~QWaylandBufferRef();
+
+ QWaylandBufferRef &operator=(const QWaylandBufferRef &ref);
+ operator bool() const;
+ bool isShm() const;
+
+ QImage image() const;
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ /**
+ * There must be a GL context bound when calling this function.
+ * It is responsibility of the caller to call destroyTexture() later.
+ */
+ GLuint createTexture();
+ void destroyTexture();
+#endif
+
+private:
+ class QWaylandBufferRefPrivate *const d;
+ friend class QWaylandBufferRefPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/compositor/compositor_api/qwaylandcompositor.cpp b/src/compositor/compositor_api/qwaylandcompositor.cpp
index 342dce510..2135a0e94 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.cpp
+++ b/src/compositor/compositor_api/qwaylandcompositor.cpp
@@ -55,33 +55,26 @@
#include <QDebug>
-#ifdef QT_COMPOSITOR_QUICK
-#include "qwaylandsurfaceitem.h"
-#endif
-
QT_BEGIN_NAMESPACE
QWaylandCompositor::QWaylandCompositor(QWindow *window, const char *socketName, ExtensionFlags extensions)
- : m_compositor(0)
+ : m_compositor(new QtWayland::Compositor(this, extensions))
, m_toplevel_window(window)
- , m_socket_name(socketName)
{
- QStringList arguments = QCoreApplication::instance()->arguments();
+ m_compositor->m_socket_name = socketName;
+ m_compositor->init();
- int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name"));
- if (socketArg != -1 && socketArg + 1 < arguments.size())
- m_socket_name = arguments.at(socketArg + 1).toLocal8Bit();
-
- m_compositor = new QtWayland::Compositor(this, extensions);
-#ifdef QT_COMPOSITOR_QUICK
- qmlRegisterType<QWaylandSurfaceItem>("WaylandCompositor", 1, 0, "WaylandSurfaceItem");
- qmlRegisterType<QWaylandSurface>("WaylandCompositor", 1, 0, "WaylandSurface");
-#else
- qRegisterMetaType<QWaylandSurface*>("WaylandSurface*");
+#if !defined(QT_NO_DEBUG) && !defined(QT_WAYLAND_NO_CLEANUP_WARNING)
+ qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually");
#endif
- m_compositor->initializeHardwareIntegration();
- m_compositor->initializeExtensions();
- m_compositor->initializeDefaultInputDevice();
+}
+
+QWaylandCompositor::QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr)
+ : m_compositor(dptr)
+ , m_toplevel_window(window)
+{
+ m_compositor->m_socket_name = socketName;
+ m_compositor->init();
}
QWaylandCompositor::~QWaylandCompositor()
@@ -213,9 +206,9 @@ void QWaylandCompositor::setClientFullScreenHint(bool value)
const char *QWaylandCompositor::socketName() const
{
- if (m_socket_name.isEmpty())
+ if (m_compositor->m_socket_name.isEmpty())
return 0;
- return m_socket_name.constData();
+ return m_compositor->m_socket_name.constData();
}
/*!
diff --git a/src/compositor/compositor_api/qwaylandcompositor.h b/src/compositor/compositor_api/qwaylandcompositor.h
index 9009f4caa..85f10b281 100644
--- a/src/compositor/compositor_api/qwaylandcompositor.h
+++ b/src/compositor/compositor_api/qwaylandcompositor.h
@@ -141,13 +141,14 @@ public:
void configureTouchExtension(TouchExtensionFlags flags);
protected:
+ QWaylandCompositor(QWindow *window, const char *socketName, QtWayland::Compositor *dptr);
virtual void retainedSelectionReceived(QMimeData *mimeData);
-private:
friend class QtWayland::Compositor;
QtWayland::Compositor *m_compositor;
+
+private:
QWindow *m_toplevel_window;
- QByteArray m_socket_name;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QWaylandCompositor::ExtensionFlags)
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
new file mode 100644
index 000000000..bc475f1c5
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp
@@ -0,0 +1,102 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QQuickWindow>
+
+#include <QtCompositor/private/qwlcompositor_p.h>
+
+#include "qwaylandquickcompositor.h"
+#include "qwaylandquicksurface.h"
+#include "qwaylandsurfaceitem.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandQuickCompositorPrivate : public QtWayland::Compositor
+{
+public:
+ QWaylandQuickCompositorPrivate(QWaylandQuickCompositor *compositor, QWaylandCompositor::ExtensionFlags extensions)
+ : QtWayland::Compositor(compositor, extensions)
+ , updateScheduled(false)
+ {
+ }
+
+ void compositor_create_surface(Resource *resource, uint32_t id) Q_DECL_OVERRIDE
+ {
+ QWaylandQuickSurface *surface = new QWaylandQuickSurface(resource->client(), id, static_cast<QWaylandQuickCompositor *>(m_qt_compositor));
+ m_surfaces << surface->handle();
+ //BUG: This may not be an on-screen window surface though
+ m_qt_compositor->surfaceCreated(surface);
+ }
+
+ void updateStarted()
+ {
+ updateScheduled = false;
+ m_qt_compositor->frameStarted();
+ m_qt_compositor->cleanupGraphicsResources();
+ }
+
+ bool updateScheduled;
+};
+
+
+QWaylandQuickCompositor::QWaylandQuickCompositor(QQuickWindow *window, const char *socketName, ExtensionFlags extensions)
+ : QWaylandCompositor(window, socketName, new QWaylandQuickCompositorPrivate(this, extensions))
+{
+ window->connect(window, &QQuickWindow::beforeSynchronizing, d_ptr(), &QWaylandQuickCompositorPrivate::updateStarted, Qt::DirectConnection);
+
+ qmlRegisterType<QWaylandSurfaceItem>("QtCompositor", 1, 0, "WaylandSurfaceItem");
+ qmlRegisterUncreatableType<QWaylandQuickSurface>("QtCompositor", 1, 0, "WaylandQuickSurface", QObject::tr("Cannot create instance of WaylandQuickSurface"));
+}
+
+QWaylandQuickCompositorPrivate *QWaylandQuickCompositor::d_ptr()
+{
+ return static_cast<QWaylandQuickCompositorPrivate *>(m_compositor);
+}
+
+void QWaylandQuickCompositor::update()
+{
+ if (!d_ptr()->updateScheduled) {
+ static_cast<QQuickWindow *>(window())->update();
+ d_ptr()->updateScheduled = true;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.h b/src/compositor/compositor_api/qwaylandquickcompositor.h
new file mode 100644
index 000000000..c87585221
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandquickcompositor.h
@@ -0,0 +1,64 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDQUICKCOMPOSITOR_H
+#define QWAYLANDQUICKCOMPOSITOR_H
+
+#include <QtCompositor/qwaylandcompositor.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQuickWindow;
+class QWaylandQuickCompositorPrivate;
+
+class Q_COMPOSITOR_EXPORT QWaylandQuickCompositor : public QWaylandCompositor
+{
+public:
+ QWaylandQuickCompositor(QQuickWindow *window = 0, const char *socketName = 0, QWaylandCompositor::ExtensionFlags extensions = DefaultExtensions);
+
+ void update();
+
+private:
+ friend class QWaylandQuickCompositorPrivate;
+ QWaylandQuickCompositorPrivate *d_ptr();
+};
+
+#endif
diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp
new file mode 100644
index 000000000..e4a5f7732
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QSGTexture>
+#include <QOpenGLTexture>
+#include <QQuickWindow>
+#include <QDebug>
+#include <QQmlPropertyMap>
+
+#include "qwaylandquicksurface.h"
+#include "qwaylandquickcompositor.h"
+#include "qwaylandsurfaceitem.h"
+#include <QtCompositor/qwaylandbufferref.h>
+#include <QtCompositor/private/qwaylandsurface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class BufferAttacher : public QWaylandBufferAttacher
+{
+public:
+ BufferAttacher()
+ : surface(0)
+ , texture(0)
+ , update(false)
+ {
+
+ }
+
+ ~BufferAttacher()
+ {
+ if (texture)
+ texture->deleteLater();
+ bufferRef = QWaylandBufferRef();
+ nextBuffer = QWaylandBufferRef();
+ }
+
+ void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE
+ {
+ nextBuffer = ref;
+ update = true;
+ }
+
+ void createTexture()
+ {
+ if (bufferRef)
+ bufferRef.destroyTexture();
+ bufferRef = nextBuffer;
+
+ QQuickWindow *window = static_cast<QQuickWindow *>(surface->compositor()->window());
+ // If the next buffer is NULL do not delete the current texture. If the client called
+ // attach(0) the surface is going to be unmapped anyway, if instead the client attached
+ // a valid buffer but died before we got here we want to keep the old buffer around
+ // in case some destroy animation is run.
+ if (bufferRef) {
+ delete texture;
+
+ if (bufferRef.isShm()) {
+ texture = window->createTextureFromImage(bufferRef.image());
+ } else {
+ QQuickWindow::CreateTextureOptions opt = 0;
+ if (surface->useTextureAlpha()) {
+ opt |= QQuickWindow::TextureHasAlphaChannel;
+ }
+ texture = window->createTextureFromId(bufferRef.createTexture(), surface->size(), opt);
+ }
+ texture->bind();
+ }
+
+ update = false;
+ }
+
+ void invalidateTexture()
+ {
+ delete texture;
+ texture = 0;
+ }
+
+ QWaylandQuickSurface *surface;
+ QWaylandBufferRef bufferRef;
+ QWaylandBufferRef nextBuffer;
+ QSGTexture *texture;
+ bool update;
+};
+
+
+class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate
+{
+public:
+ QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf)
+ : QWaylandSurfacePrivate(client, id, c, surf)
+ , buffer(new BufferAttacher)
+ , compositor(c)
+ , useTextureAlpha(true)
+ , windowPropertyMap(new QQmlPropertyMap)
+ , clientRenderingEnabled(true)
+ {
+
+ }
+
+ ~QWaylandQuickSurfacePrivate()
+ {
+ windowPropertyMap->deleteLater();
+ // buffer is deleted automatically by ~Surface(), since it is the assigned attacher
+ }
+
+ void surface_commit(Resource *resource) Q_DECL_OVERRIDE
+ {
+ if (m_pending.newlyAttached) {
+ buffer->update = true;
+ }
+ QWaylandSurfacePrivate::surface_commit(resource);
+
+ compositor->update();
+ }
+
+ BufferAttacher *buffer;
+ QWaylandQuickCompositor *compositor;
+ bool useTextureAlpha;
+ QQmlPropertyMap *windowPropertyMap;
+ bool clientRenderingEnabled;
+};
+
+QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor)
+ : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, compositor, this))
+{
+ Q_D(QWaylandQuickSurface);
+ d->buffer->surface = this;
+ setBufferAttacher(d->buffer);
+
+ QQuickWindow *window = static_cast<QQuickWindow *>(compositor->window());
+ connect(window, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickSurface::updateTexture, Qt::DirectConnection);
+ connect(window, &QQuickWindow::sceneGraphInvalidated, this, &QWaylandQuickSurface::invalidateTexture, Qt::DirectConnection);
+ connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert);
+ connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty);
+
+}
+
+QWaylandQuickSurface::~QWaylandQuickSurface()
+{
+
+}
+
+QSGTexture *QWaylandQuickSurface::texture() const
+{
+ Q_D(const QWaylandQuickSurface);
+ return d->buffer->texture;
+}
+
+bool QWaylandQuickSurface::useTextureAlpha() const
+{
+ Q_D(const QWaylandQuickSurface);
+ return d->useTextureAlpha;
+}
+
+void QWaylandQuickSurface::setUseTextureAlpha(bool useTextureAlpha)
+{
+ Q_D(QWaylandQuickSurface);
+ if (d->useTextureAlpha != useTextureAlpha) {
+ d->useTextureAlpha = useTextureAlpha;
+ emit useTextureAlphaChanged();
+ emit configure();
+ }
+}
+
+QObject *QWaylandQuickSurface::windowPropertyMap() const
+{
+ Q_D(const QWaylandQuickSurface);
+ return d->windowPropertyMap;
+}
+
+
+void QWaylandQuickSurface::updateTexture()
+{
+ Q_D(QWaylandQuickSurface);
+ if (d->buffer->update)
+ d->buffer->createTexture();
+}
+
+void QWaylandQuickSurface::invalidateTexture()
+{
+ Q_D(QWaylandQuickSurface);
+ d->buffer->invalidateTexture();
+}
+
+bool QWaylandQuickSurface::clientRenderingEnabled() const
+{
+ Q_D(const QWaylandQuickSurface);
+ return d->clientRenderingEnabled;
+}
+
+void QWaylandQuickSurface::setClientRenderingEnabled(bool enabled)
+{
+ Q_D(QWaylandQuickSurface);
+ if (d->clientRenderingEnabled != enabled) {
+ d->clientRenderingEnabled = enabled;
+
+ sendOnScreenVisibilityChange(enabled);
+
+ emit clientRenderingEnabledChanged();
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h
new file mode 100644
index 000000000..6c464ecd7
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandquicksurface.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUICKWAYLANDSURFACE_H
+#define QQUICKWAYLANDSURFACE_H
+
+#include <QSGTexture>
+#include <QSGTextureProvider>
+
+#include "qwaylandsurface.h"
+
+struct wl_client;
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandSurfaceItem;
+class QWaylandQuickSurfacePrivate;
+class QWaylandQuickCompositor;
+
+class Q_COMPOSITOR_EXPORT QWaylandQuickSurface : public QWaylandSurface
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWaylandQuickSurface)
+ Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged)
+ Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged)
+ Q_PROPERTY(QObject *windowProperties READ windowPropertyMap CONSTANT)
+public:
+ QWaylandQuickSurface(wl_client *client, quint32 id, QWaylandQuickCompositor *compositor);
+ ~QWaylandQuickSurface();
+
+ QSGTexture *texture() const;
+
+ bool useTextureAlpha() const;
+ void setUseTextureAlpha(bool useTextureAlpha);
+
+ bool clientRenderingEnabled() const;
+ void setClientRenderingEnabled(bool enabled);
+
+ QObject *windowPropertyMap() const;
+
+signals:
+ void useTextureAlphaChanged();
+ void clientRenderingEnabledChanged();
+
+private:
+ void updateTexture();
+ void invalidateTexture();
+
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index 2b7d713c8..5fd7fabe9 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -53,74 +53,51 @@
#include "qwaylandcompositor.h"
#include "waylandwindowmanagerintegration.h"
+#include "qwaylandsurface_p.h"
+#include "qwaylandbufferref.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
-#ifdef QT_COMPOSITOR_QUICK
-#include "qwaylandsurfaceitem.h"
-#include <QtQml/QQmlPropertyMap>
-#endif
-
QT_BEGIN_NAMESPACE
-class QWaylandSurfacePrivate : public QObjectPrivate
-{
-public:
- QWaylandSurfacePrivate(QtWayland::Surface *srfc)
- : surface(srfc)
-#ifdef QT_COMPOSITOR_QUICK
- , surface_item(0)
- , windowPropertyMap(new QQmlPropertyMap)
-#endif
- {}
-
- ~QWaylandSurfacePrivate()
- {
-#ifdef QT_COMPOSITOR_QUICK
- if (surface_item)
- surface_item->setSurface(0);
- if (windowPropertyMap)
- windowPropertyMap->deleteLater();
-#endif
- }
+QWaylandSurfacePrivate::QWaylandSurfacePrivate(wl_client *client, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface)
+ : QtWayland::Surface(client, id, compositor, surface)
+ , closing(false)
+ , refCount(1)
+{}
- QtWayland::Surface *surface;
-#ifdef QT_COMPOSITOR_QUICK
- QWaylandSurfaceItem *surface_item;
- QQmlPropertyMap *windowPropertyMap;
-#endif
-};
-QWaylandSurface::QWaylandSurface(QtWayland::Surface *surface)
- : QObject(*new QWaylandSurfacePrivate(surface))
+
+QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor)
+ : QObject(*new QWaylandSurfacePrivate(client, id, compositor, this))
{
-#ifdef QT_COMPOSITOR_QUICK
- Q_D(QWaylandSurface);
- connect(this, &QWaylandSurface::windowPropertyChanged,
- d->windowPropertyMap, &QQmlPropertyMap::insert);
- connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged,
- this, &QWaylandSurface::setWindowProperty);
-#endif
+
}
-void QWaylandSurface::swapBuffers()
+QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate *dptr)
+ : QObject(*dptr)
{
- Q_D(const QWaylandSurface);
- d->surface->swapBuffers();
+
+}
+
+QWaylandSurface::~QWaylandSurface()
+{
+ Q_D(QWaylandSurface);
+ delete d->m_attacher;
}
WaylandClient *QWaylandSurface::client() const
{
Q_D(const QWaylandSurface);
- return d->surface->resource()->client();
+ return d->resource()->client();
}
QWaylandSurface *QWaylandSurface::parentSurface() const
{
Q_D(const QWaylandSurface);
- if (d->surface->subSurface() && d->surface->subSurface()->parent()) {
- return d->surface->subSurface()->parent()->waylandSurface();
+ if (d->subSurface() && d->subSurface()->parent()) {
+ return d->subSurface()->parent()->waylandSurface();
}
return 0;
}
@@ -128,8 +105,8 @@ QWaylandSurface *QWaylandSurface::parentSurface() const
QLinkedList<QWaylandSurface *> QWaylandSurface::subSurfaces() const
{
Q_D(const QWaylandSurface);
- if (d->surface->subSurface()) {
- return d->surface->subSurface()->subSurfaces();
+ if (d->subSurface()) {
+ return d->subSurface()->subSurfaces();
}
return QLinkedList<QWaylandSurface *>();
}
@@ -137,13 +114,13 @@ QLinkedList<QWaylandSurface *> QWaylandSurface::subSurfaces() const
QWaylandSurface::Type QWaylandSurface::type() const
{
Q_D(const QWaylandSurface);
- return d->surface->type();
+ return d->type();
}
bool QWaylandSurface::isYInverted() const
{
Q_D(const QWaylandSurface);
- return d->surface->isYInverted();
+ return d->isYInverted();
}
bool QWaylandSurface::visible() const
@@ -154,110 +131,70 @@ bool QWaylandSurface::visible() const
bool QWaylandSurface::isMapped() const
{
Q_D(const QWaylandSurface);
- return d->surface->mapped();
+ return d->mapped();
}
QPointF QWaylandSurface::pos() const
{
Q_D(const QWaylandSurface);
- return d->surface->pos();
+ return d->pos();
}
void QWaylandSurface::setPos(const QPointF &pos)
{
Q_D(QWaylandSurface);
- d->surface->setPos(pos);
+ d->setPos(pos);
}
QSize QWaylandSurface::size() const
{
Q_D(const QWaylandSurface);
- return d->surface->size();
+ return d->size();
}
void QWaylandSurface::requestSize(const QSize &size)
{
Q_D(QWaylandSurface);
- if (d->surface->shellSurface())
- d->surface->shellSurface()->sendConfigure(WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, size.width(), size.height());
+ if (d->shellSurface())
+ d->shellSurface()->sendConfigure(WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT, size.width(), size.height());
}
Qt::ScreenOrientations QWaylandSurface::orientationUpdateMask() const
{
Q_D(const QWaylandSurface);
- return d->surface->compositor()->orientationUpdateMaskForClient(static_cast<wl_client *>(client()));
+ return d->compositor()->orientationUpdateMaskForClient(static_cast<wl_client *>(client()));
}
Qt::ScreenOrientation QWaylandSurface::contentOrientation() const
{
Q_D(const QWaylandSurface);
- if (!d->surface->extendedSurface())
+ if (!d->extendedSurface())
return Qt::PrimaryOrientation;
- return d->surface->extendedSurface()->contentOrientation();
+ return d->extendedSurface()->contentOrientation();
}
QWaylandSurface::WindowFlags QWaylandSurface::windowFlags() const
{
Q_D(const QWaylandSurface);
- if (!d->surface->extendedSurface())
+ if (!d->extendedSurface())
return QWaylandSurface::WindowFlags(0);
- return d->surface->extendedSurface()->windowFlags();
+ return d->extendedSurface()->windowFlags();
}
QWaylandSurface::WindowType QWaylandSurface::windowType() const
{
Q_D(const QWaylandSurface);
- if (d->surface->shellSurface())
- return d->surface->shellSurface()->windowType();
+ if (d->shellSurface())
+ return d->shellSurface()->windowType();
return QWaylandSurface::None;
}
-QImage QWaylandSurface::image() const
-{
- Q_D(const QWaylandSurface);
- return d->surface->image();
-}
-
-#ifdef QT_COMPOSITOR_WAYLAND_GL
-GLuint QWaylandSurface::texture() const
-{
- Q_D(const QWaylandSurface);
- return d->surface->textureId();
-}
-#else //QT_COMPOSITOR_WAYLAND_GL
-uint QWaylandSurface::texture() const
-{
- return 0;
-}
-#endif
-
-QtWayland::Surface * QWaylandSurface::handle() const
-{
- Q_D(const QWaylandSurface);
- return d->surface;
-}
-
-#ifdef QT_COMPOSITOR_QUICK
-QWaylandSurfaceItem *QWaylandSurface::surfaceItem() const
-{
- Q_D(const QWaylandSurface);
- return d->surface_item;
-}
-
-void QWaylandSurface::setSurfaceItem(QWaylandSurfaceItem *surfaceItem)
+QtWayland::Surface * QWaylandSurface::handle()
{
Q_D(QWaylandSurface);
- d->surface_item = surfaceItem;
+ return d;
}
-QObject *QWaylandSurface::windowPropertyMap() const
-{
- Q_D(const QWaylandSurface);
- return d->windowPropertyMap;
-}
-
-#endif //QT_COMPOSITOR_QUICK
-
qint64 QWaylandSurface::processId() const
{
struct wl_client *client = static_cast<struct wl_client *>(this->client());
@@ -269,19 +206,19 @@ qint64 QWaylandSurface::processId() const
QVariantMap QWaylandSurface::windowProperties() const
{
Q_D(const QWaylandSurface);
- if (!d->surface->extendedSurface())
+ if (!d->extendedSurface())
return QVariantMap();
- return d->surface->extendedSurface()->windowProperties();
+ return d->extendedSurface()->windowProperties();
}
void QWaylandSurface::setWindowProperty(const QString &name, const QVariant &value)
{
Q_D(QWaylandSurface);
- if (!d->surface->extendedSurface())
+ if (!d->extendedSurface())
return;
- d->surface->extendedSurface()->setWindowProperty(name, value);
+ d->extendedSurface()->setWindowProperty(name, value);
}
QPointF QWaylandSurface::mapToParent(const QPointF &pos) const
@@ -307,22 +244,22 @@ QPointF QWaylandSurface::mapTo(QWaylandSurface *parent, const QPointF &pos) cons
QWaylandCompositor *QWaylandSurface::compositor() const
{
Q_D(const QWaylandSurface);
- return d->surface->compositor()->waylandCompositor();
+ return d->compositor()->waylandCompositor();
}
QWaylandSurface *QWaylandSurface::transientParent() const
{
Q_D(const QWaylandSurface);
- if (d->surface->shellSurface() && d->surface->shellSurface()->transientParent())
- return d->surface->shellSurface()->transientParent()->surface()->waylandSurface();
+ if (d->shellSurface() && d->shellSurface()->transientParent())
+ return d->shellSurface()->transientParent()->surface()->waylandSurface();
return 0;
}
QWindow::Visibility QWaylandSurface::visibility() const
{
Q_D(const QWaylandSurface);
- if (d->surface->extendedSurface())
- return d->surface->extendedSurface()->visibility();
+ if (d->extendedSurface())
+ return d->extendedSurface()->visibility();
return QWindow::AutomaticVisibility;
}
@@ -330,8 +267,8 @@ QWindow::Visibility QWaylandSurface::visibility() const
void QWaylandSurface::setVisibility(QWindow::Visibility visibility)
{
Q_D(QWaylandSurface);
- if (d->surface->extendedSurface())
- d->surface->extendedSurface()->setVisibility(visibility);
+ if (d->extendedSurface())
+ d->extendedSurface()->setVisibility(visibility);
}
void QWaylandSurface::sendOnScreenVisibilityChange(bool visible)
@@ -342,19 +279,19 @@ void QWaylandSurface::sendOnScreenVisibilityChange(bool visible)
QString QWaylandSurface::className() const
{
Q_D(const QWaylandSurface);
- return d->surface->className();
+ return d->className();
}
QString QWaylandSurface::title() const
{
Q_D(const QWaylandSurface);
- return d->surface->title();
+ return d->title();
}
bool QWaylandSurface::hasShellSurface() const
{
Q_D(const QWaylandSurface);
- if (d->surface->shellSurface())
+ if (d->shellSurface())
return true;
return false;
@@ -364,7 +301,7 @@ bool QWaylandSurface::hasInputPanelSurface() const
{
Q_D(const QWaylandSurface);
- return d->surface->inputPanelSurface() != 0;
+ return d->inputPanelSurface() != 0;
}
/*!
@@ -373,14 +310,21 @@ bool QWaylandSurface::hasInputPanelSurface() const
bool QWaylandSurface::transientInactive() const
{
Q_D(const QWaylandSurface);
- return d->surface->transientInactive();
+ return d->transientInactive();
+}
+
+void QWaylandSurface::destroy()
+{
+ Q_D(QWaylandSurface);
+ if (--d->refCount == 0)
+ compositor()->handle()->destroySurface(d);
}
void QWaylandSurface::destroySurface()
{
Q_D(QWaylandSurface);
- if (d->surface->extendedSurface()) {
- d->surface->extendedSurface()->send_close();
+ if (d->extendedSurface()) {
+ d->extendedSurface()->send_close();
} else {
destroySurfaceByForce();
}
@@ -389,15 +333,15 @@ void QWaylandSurface::destroySurface()
void QWaylandSurface::destroySurfaceByForce()
{
Q_D(QWaylandSurface);
- wl_resource *surface_resource = d->surface->resource()->handle;
+ wl_resource *surface_resource = d->resource()->handle;
wl_resource_destroy(surface_resource);
}
void QWaylandSurface::ping()
{
Q_D(QWaylandSurface);
- if (d->surface->shellSurface())
- d->surface->shellSurface()->ping();
+ if (d->shellSurface())
+ d->shellSurface()->ping();
}
/*!
@@ -408,14 +352,32 @@ void QWaylandSurface::ping()
void QWaylandSurface::updateSelection()
{
Q_D(QWaylandSurface);
- const QtWayland::InputDevice *inputDevice = d->surface->compositor()->defaultInputDevice();
+ const QtWayland::InputDevice *inputDevice = d->compositor()->defaultInputDevice();
if (inputDevice) {
const QtWayland::DataDevice *dataDevice = inputDevice->dataDevice();
if (dataDevice) {
- d->surface->compositor()->dataDeviceManager()->offerRetainedSelection(
- dataDevice->resourceMap().value(d->surface->resource()->client())->handle);
+ d->compositor()->dataDeviceManager()->offerRetainedSelection(
+ dataDevice->resourceMap().value(d->resource()->client())->handle);
}
}
}
+void QWaylandSurface::ref()
+{
+ Q_D(QWaylandSurface);
+ ++d->refCount;
+}
+
+void QWaylandSurface::setBufferAttacher(QWaylandBufferAttacher *attacher)
+{
+ Q_D(QWaylandSurface);
+ d->m_attacher = attacher;
+}
+
+QWaylandBufferAttacher *QWaylandSurface::bufferAttacher() const
+{
+ Q_D(const QWaylandSurface);
+ return d->m_attacher;
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h
index 2f7b70ce8..22deee5ae 100644
--- a/src/compositor/compositor_api/qwaylandsurface.h
+++ b/src/compositor/compositor_api/qwaylandsurface.h
@@ -48,19 +48,14 @@
#include <QtGui/QWindow>
#include <QtCore/QVariantMap>
-#ifdef QT_COMPOSITOR_WAYLAND_GL
-#include <QtGui/qopengl.h>
-#endif
+struct wl_client;
QT_BEGIN_NAMESPACE
class QTouchEvent;
class QWaylandSurfacePrivate;
class QWaylandCompositor;
-
-#ifdef QT_COMPOSITOR_QUICK
-class QWaylandSurfaceItem;
-#endif
+class QWaylandBufferRef;
namespace QtWayland {
class Surface;
@@ -68,6 +63,17 @@ class SurfacePrivate;
class ExtendedSurface;
}
+class Q_COMPOSITOR_EXPORT QWaylandBufferAttacher
+{
+public:
+ virtual ~QWaylandBufferAttacher() {}
+
+protected:
+ virtual void attach(const QWaylandBufferRef &ref) = 0;
+
+ friend class QtWayland::Surface;
+};
+
class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject
{
Q_OBJECT
@@ -81,9 +87,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
Q_PROPERTY(Qt::ScreenOrientations orientationUpdateMask READ orientationUpdateMask NOTIFY orientationUpdateMaskChanged)
Q_PROPERTY(QWindow::Visibility visibility READ visibility WRITE setVisibility NOTIFY visibilityChanged)
-#ifdef QT_COMPOSITOR_QUICK
- Q_PROPERTY(QObject * windowProperties READ windowPropertyMap CONSTANT)
-#endif
+ Q_PROPERTY(QSize size READ size NOTIFY sizeChanged)
Q_ENUMS(WindowFlag WindowType)
Q_FLAGS(WindowFlag WindowFlags)
@@ -109,7 +113,8 @@ public:
Texture
};
- QWaylandSurface(QtWayland::Surface *surface = 0);
+ QWaylandSurface(wl_client *client, quint32 id, QWaylandCompositor *compositor);
+ virtual ~QWaylandSurface();
WaylandClient *client() const;
@@ -134,27 +139,13 @@ public:
WindowType windowType() const;
- QImage image() const;
-#ifdef QT_COMPOSITOR_WAYLAND_GL
- GLuint texture() const;
-#else
- uint texture() const;
-#endif
-
QWindow::Visibility visibility() const;
void setVisibility(QWindow::Visibility visibility);
Q_INVOKABLE void sendOnScreenVisibilityChange(bool visible); // Compat
QWaylandSurface *transientParent() const;
- QtWayland::Surface *handle() const;
-
-#ifdef QT_COMPOSITOR_QUICK
- QWaylandSurfaceItem *surfaceItem() const;
- void setSurfaceItem(QWaylandSurfaceItem *surfaceItem);
-
- QObject *windowPropertyMap() const;
-#endif
+ QtWayland::Surface *handle();
qint64 processId() const;
QByteArray authenticationToken() const;
@@ -175,20 +166,26 @@ public:
bool transientInactive() const;
+ Q_INVOKABLE void destroy();
Q_INVOKABLE void destroySurface();
Q_INVOKABLE void destroySurfaceByForce();
Q_INVOKABLE void ping();
- void swapBuffers();
+ void ref();
+
+ void setBufferAttacher(QWaylandBufferAttacher *attacher);
+ QWaylandBufferAttacher *bufferAttacher() const;
public slots:
void updateSelection();
+protected:
+ QWaylandSurface(QWaylandSurfacePrivate *dptr);
+
signals:
void mapped();
void unmapped();
void damaged(const QRegion &rect);
- void committed();
void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent);
void sizeChanged();
void posChanged();
@@ -204,6 +201,10 @@ signals:
void lowerRequested();
void visibilityChanged();
void pong();
+ void surfaceDestroyed();
+
+ void configure();
+ void redraw();
};
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandsurface_p.h b/src/compositor/compositor_api/qwaylandsurface_p.h
new file mode 100644
index 000000000..aff0a8758
--- /dev/null
+++ b/src/compositor/compositor_api/qwaylandsurface_p.h
@@ -0,0 +1,68 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWAYLANDSURFACE_P_H
+#define QWAYLANDSURFACE_P_H
+
+#include <QtCompositor/qwaylandexport.h>
+#include <private/qobject_p.h>
+
+#include <QtCompositor/private/qwlsurface_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWaylandCompositor;
+class QWaylandSurface;
+
+class Q_COMPOSITOR_EXPORT QWaylandSurfacePrivate : public QObjectPrivate, public QtWayland::Surface
+{
+public:
+ QWaylandSurfacePrivate(wl_client *client, quint32 id, QWaylandCompositor *compositor, QWaylandSurface *surface);
+
+ bool closing;
+ int refCount;
+
+ friend class QWaylandSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
index 57e5c2906..1a1dc7cdb 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
+++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp
@@ -39,12 +39,9 @@
****************************************************************************/
#include "qwaylandsurfaceitem.h"
-#include "qwaylandsurface.h"
-#include "qwaylandcompositor.h"
-#include "qwaylandinput.h"
-
-#include "qwlsurface_p.h"
-#include "qwlextendedsurface_p.h"
+#include "qwaylandquicksurface.h"
+#include <QtCompositor/qwaylandcompositor.h>
+#include <QtCompositor/qwaylandinput.h>
#include <QtGui/QKeyEvent>
#include <QtGui/QGuiApplication>
@@ -58,15 +55,15 @@
QT_BEGIN_NAMESPACE
+QMutex *QWaylandSurfaceItem::mutex = 0;
+
class QWaylandSurfaceTextureProvider : public QSGTextureProvider
{
- Q_OBJECT
-
public:
QWaylandSurfaceTextureProvider() : t(0) { }
- ~QWaylandSurfaceTextureProvider() { delete t; }
- QSGTexture *texture() const {
+ QSGTexture *texture() const Q_DECL_OVERRIDE
+ {
if (t)
t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest);
return t;
@@ -74,55 +71,45 @@ public:
bool smooth;
QSGTexture *t;
-
-public slots:
- void invalidate()
- {
- delete t;
- t = 0;
- }
};
-QMutex *QWaylandSurfaceItem::mutex = 0;
-
QWaylandSurfaceItem::QWaylandSurfaceItem(QQuickItem *parent)
: QQuickItem(parent)
, m_surface(0)
, m_provider(0)
, m_paintEnabled(true)
- , m_useTextureAlpha(false)
- , m_clientRenderingEnabled(true)
, m_touchEventsEnabled(false)
, m_resizeSurfaceToItem(false)
+ , m_newTexture(false)
{
if (!mutex)
mutex = new QMutex;
+
+ setFlag(ItemHasContents);
}
-QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *parent)
+QWaylandSurfaceItem::QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent)
: QQuickItem(parent)
, m_surface(0)
, m_provider(0)
, m_paintEnabled(true)
- , m_useTextureAlpha(false)
- , m_clientRenderingEnabled(true)
, m_touchEventsEnabled(false)
, m_resizeSurfaceToItem(false)
{
init(surface);
}
-void QWaylandSurfaceItem::init(QWaylandSurface *surface)
+void QWaylandSurfaceItem::init(QWaylandQuickSurface *surface)
{
+ if (m_surface)
+ m_surface->destroy();
+
if (!surface)
return;
- if (m_surface) {
- m_surface->setSurfaceItem(0);
- }
-
m_surface = surface;
- m_surface->setSurfaceItem(this);
+ surface->ref();
+ update();
if (m_resizeSurfaceToItem) {
updateSurfaceSize();
@@ -134,7 +121,7 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface)
updatePosition();
setSmooth(true);
- setFlag(ItemHasContents);
+
setAcceptedMouseButtons(Qt::LeftButton | Qt::MiddleButton | Qt::RightButton |
Qt::ExtraButton1 | Qt::ExtraButton2 | Qt::ExtraButton3 | Qt::ExtraButton4 |
Qt::ExtraButton5 | Qt::ExtraButton6 | Qt::ExtraButton7 | Qt::ExtraButton8 |
@@ -143,29 +130,29 @@ void QWaylandSurfaceItem::init(QWaylandSurface *surface)
setAcceptHoverEvents(true);
connect(surface, &QWaylandSurface::mapped, this, &QWaylandSurfaceItem::surfaceMapped);
connect(surface, &QWaylandSurface::unmapped, this, &QWaylandSurfaceItem::surfaceUnmapped);
- connect(surface, &QWaylandSurface::destroyed, this, &QWaylandSurfaceItem::surfaceDestroyed);
- connect(surface, &QWaylandSurface::damaged, this, &QWaylandSurfaceItem::surfaceDamaged);
- connect(surface, &QWaylandSurface::committed, this, &QQuickItem::update);
+ connect(surface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::surfaceDestroyed);
connect(surface, &QWaylandSurface::parentChanged, this, &QWaylandSurfaceItem::parentChanged);
connect(surface, &QWaylandSurface::sizeChanged, this, &QWaylandSurfaceItem::updateSize);
connect(surface, &QWaylandSurface::posChanged, this, &QWaylandSurfaceItem::updatePosition);
+ connect(surface, &QWaylandSurface::configure, this, &QWaylandSurfaceItem::updateBuffer);
+ connect(surface, &QWaylandSurface::redraw, this, &QQuickItem::update);
connect(this, &QWaylandSurfaceItem::widthChanged, this, &QWaylandSurfaceItem::updateSurfaceSize);
connect(this, &QWaylandSurfaceItem::heightChanged, this, &QWaylandSurfaceItem::updateSurfaceSize);
- m_damaged = false;
m_yInverted = surface ? surface->isYInverted() : true;
+ emit yInvertedChanged();
}
QWaylandSurfaceItem::~QWaylandSurfaceItem()
{
QMutexLocker locker(mutex);
if (m_surface)
- m_surface->setSurfaceItem(0);
+ m_surface->destroy();
if (m_provider)
m_provider->deleteLater();
}
-void QWaylandSurfaceItem::setSurface(QWaylandSurface *surface)
+void QWaylandSurfaceItem::setSurface(QWaylandQuickSurface *surface)
{
if (surface == m_surface)
return;
@@ -181,16 +168,9 @@ bool QWaylandSurfaceItem::isYInverted() const
QSGTextureProvider *QWaylandSurfaceItem::textureProvider() const
{
- const_cast<QWaylandSurfaceItem *>(this)->ensureProvider();
- return m_provider;
-}
-
-void QWaylandSurfaceItem::ensureProvider()
-{
- if (!m_provider) {
+ if (!m_provider)
m_provider = new QWaylandSurfaceTextureProvider();
- connect(window(), &QQuickWindow::sceneGraphInvalidated, m_provider, &QWaylandSurfaceTextureProvider::invalidate, Qt::DirectConnection);
- }
+ return m_provider;
}
void QWaylandSurfaceItem::mousePressEvent(QMouseEvent *event)
@@ -281,40 +261,10 @@ void QWaylandSurfaceItem::surfaceUnmapped()
update();
}
-void QWaylandSurfaceItem::surfaceDestroyed(QObject *)
-{
- if (m_surface)
- m_surface->setSurfaceItem(0);
-
- m_surface = 0;
-}
-
-void QWaylandSurfaceItem::setDamagedFlag(bool on)
-{
- m_damaged = on;
-}
-
-
-void QWaylandSurfaceItem::surfaceDamaged(const QRegion &)
-{
- m_damaged = true;
- if (m_surface) {
- bool inverted = m_surface->isYInverted();
- if (inverted != m_yInverted) {
- m_yInverted = inverted;
- emit yInvertedChanged();
- }
- }
- emit textureChanged();
-}
-
void QWaylandSurfaceItem::parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent)
{
Q_UNUSED(oldParent);
- QWaylandSurfaceItem *item = newParent? newParent->surfaceItem():0;
- setParentItem(item);
-
if (newParent) {
setPaintEnabled(true);
setVisible(true);
@@ -340,6 +290,14 @@ void QWaylandSurfaceItem::updatePosition()
setPosition(m_surface->pos());
}
+/*!
+ \qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled
+
+ If this property is true, the \l item is hidden, though the texture
+ will still be updated. As opposed to hiding the \l item by
+ setting \l{Item::visible}{visible} to false, setting this property to true
+ will not prevent mouse or keyboard input from reaching \l item.
+*/
bool QWaylandSurfaceItem::paintEnabled() const
{
return m_paintEnabled;
@@ -351,29 +309,14 @@ void QWaylandSurfaceItem::setPaintEnabled(bool enabled)
update();
}
-void QWaylandSurfaceItem::updateTexture()
+void QWaylandSurfaceItem::updateBuffer()
{
- ensureProvider();
- QSGTexture *texture = m_provider->t;
- if (m_damaged) {
- m_damaged = false;
- QSGTexture *oldTexture = texture;
- if (m_surface->type() == QWaylandSurface::Texture) {
- QQuickWindow::CreateTextureOptions opt = 0;
- if (useTextureAlpha()) {
- opt |= QQuickWindow::TextureHasAlphaChannel;
- }
- texture = window()->createTextureFromId(m_surface->texture(), m_surface->size(), opt);
- } else {
- texture = window()->createTextureFromImage(m_surface->image());
- }
- texture->bind();
- delete oldTexture;
- }
+ bool inv = m_yInverted;
+ m_yInverted = surface()->isYInverted();
+ if (inv != m_yInverted)
+ emit yInvertedChanged();
- m_provider->t = texture;
- emit m_provider->textureChanged();
- m_provider->smooth = smooth();
+ m_newTexture = true;
}
QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
@@ -383,14 +326,20 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD
return 0;
}
+ if (!m_provider)
+ m_provider = new QWaylandSurfaceTextureProvider();
+
// Order here is important, as the state of visible is that of the pending
// buffer but will be replaced after we advance the buffer queue.
bool mapped = m_surface->isMapped();
- surface()->swapBuffers();
if (mapped)
- updateTexture();
+ m_provider->t = surface()->texture();
+ m_provider->smooth = smooth();
+ if (m_newTexture)
+ emit m_provider->textureChanged();
+ m_newTexture = false;
- if (!mapped|| !m_provider || !m_provider->t || !m_paintEnabled) {
+ if (!mapped || !m_provider->t || !m_paintEnabled) {
delete oldNode;
return 0;
}
@@ -409,28 +358,6 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD
return node;
}
-void QWaylandSurfaceItem::setUseTextureAlpha(bool useTextureAlpha)
-{
- m_useTextureAlpha = useTextureAlpha;
-
- if ((flags() & ItemHasContents) != 0) {
- update();
- }
-}
-
-void QWaylandSurfaceItem::setClientRenderingEnabled(bool enabled)
-{
- if (m_clientRenderingEnabled != enabled) {
- m_clientRenderingEnabled = enabled;
-
- if (m_surface) {
- m_surface->sendOnScreenVisibilityChange(enabled);
- }
-
- emit clientRenderingEnabledChanged();
- }
-}
-
void QWaylandSurfaceItem::setTouchEventsEnabled(bool enabled)
{
if (m_touchEventsEnabled != enabled) {
@@ -448,5 +375,3 @@ void QWaylandSurfaceItem::setResizeSurfaceToItem(bool enabled)
}
QT_END_NAMESPACE
-
-#include "qwaylandsurfaceitem.moc"
diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h
index 8abd4bf2d..f1da27995 100644
--- a/src/compositor/compositor_api/qwaylandsurfaceitem.h
+++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h
@@ -42,38 +42,37 @@
#define QWAYLANDSURFACEITEM_H
#include <QtCompositor/qwaylandexport.h>
-#include <QtCompositor/qwaylandsurface.h>
#include <QtQuick/QQuickItem>
#include <QtQuick/qsgtexture.h>
#include <QtQuick/qsgtextureprovider.h>
+#include "qwaylandquicksurface.h"
+
QT_BEGIN_NAMESPACE
class QWaylandSurfaceTextureProvider;
class QMutex;
-Q_DECLARE_METATYPE(QWaylandSurface*)
+Q_DECLARE_METATYPE(QWaylandQuickSurface*)
-class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem
+class QWaylandSurfaceItem : public QQuickItem
{
Q_OBJECT
- Q_PROPERTY(QWaylandSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged)
+ Q_PROPERTY(QWaylandQuickSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged)
Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled)
- Q_PROPERTY(bool useTextureAlpha READ useTextureAlpha WRITE setUseTextureAlpha NOTIFY useTextureAlphaChanged)
- Q_PROPERTY(bool clientRenderingEnabled READ clientRenderingEnabled WRITE setClientRenderingEnabled NOTIFY clientRenderingEnabledChanged)
Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged)
Q_PROPERTY(bool isYInverted READ isYInverted NOTIFY yInvertedChanged)
Q_PROPERTY(bool resizeSurfaceToItem READ resizeSurfaceToItem WRITE setResizeSurfaceToItem NOTIFY resizeSurfaceToItemChanged)
public:
QWaylandSurfaceItem(QQuickItem *parent = 0);
- QWaylandSurfaceItem(QWaylandSurface *surface, QQuickItem *parent = 0);
+ QWaylandSurfaceItem(QWaylandQuickSurface *surface, QQuickItem *parent = 0);
~QWaylandSurfaceItem();
- void setSurface(QWaylandSurface *surface);
- QWaylandSurface *surface() const {return m_surface; }
+ void setSurface(QWaylandQuickSurface *surface);
+ QWaylandQuickSurface *surface() const {return m_surface; }
Q_INVOKABLE bool isYInverted() const;
@@ -81,18 +80,12 @@ public:
QSGTextureProvider *textureProvider() const;
bool paintEnabled() const;
- bool useTextureAlpha() const { return m_useTextureAlpha; }
- bool clientRenderingEnabled() const { return m_clientRenderingEnabled; }
bool touchEventsEnabled() const { return m_touchEventsEnabled; }
bool resizeSurfaceToItem() const { return m_resizeSurfaceToItem; }
- void setUseTextureAlpha(bool useTextureAlpha);
- void setClientRenderingEnabled(bool enabled);
void setTouchEventsEnabled(bool enabled);
void setResizeSurfaceToItem(bool enabled);
- void setDamagedFlag(bool on);
-
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
@@ -111,21 +104,18 @@ public slots:
private slots:
void surfaceMapped();
void surfaceUnmapped();
- void surfaceDestroyed(QObject *object);
- void surfaceDamaged(const QRegion &);
void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent);
void updateSize();
void updateSurfaceSize();
void updatePosition();
+ void updateBuffer();
signals:
- void textureChanged();
- void useTextureAlphaChanged();
- void clientRenderingEnabledChanged();
void touchEventsEnabledChanged();
void yInvertedChanged();
void surfaceChanged();
void resizeSurfaceToItemChanged();
+ void surfaceDestroyed();
protected:
QSGNode *updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *);
@@ -133,20 +123,17 @@ protected:
private:
friend class QWaylandSurfaceNode;
void updateTexture();
- void init(QWaylandSurface *);
- void ensureProvider();
+ void init(QWaylandQuickSurface *);
static QMutex *mutex;
- QWaylandSurface *m_surface;
- QWaylandSurfaceTextureProvider *m_provider;
+ QWaylandQuickSurface *m_surface;
+ mutable QWaylandSurfaceTextureProvider *m_provider;
bool m_paintEnabled;
- bool m_useTextureAlpha;
- bool m_clientRenderingEnabled;
bool m_touchEventsEnabled;
- bool m_damaged;
bool m_yInverted;
bool m_resizeSurfaceToItem;
+ bool m_newTexture;
};
QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlcompositor.cpp b/src/compositor/wayland_wrapper/qwlcompositor.cpp
index da67c3cd2..a6ec62caa 100644
--- a/src/compositor/wayland_wrapper/qwlcompositor.cpp
+++ b/src/compositor/wayland_wrapper/qwlcompositor.cpp
@@ -69,10 +69,6 @@
#include <QtCore/QAbstractEventDispatcher>
#include <QtGui/private/qguiapplication_p.h>
-#ifdef QT_COMPOSITOR_QUICK
-#include <QtQuick/QQuickWindow>
-#endif
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -131,6 +127,15 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex
{
m_timer.start();
compositor = this;
+}
+
+void Compositor::init()
+{
+ QStringList arguments = QCoreApplication::instance()->arguments();
+
+ int socketArg = arguments.indexOf(QLatin1String("--wayland-socket-name"));
+ if (socketArg != -1 && socketArg + 1 < arguments.size())
+ m_socket_name = arguments.at(socketArg + 1).toLocal8Bit();
wl_compositor::init(m_display->handle());
@@ -147,7 +152,7 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex
m_shell,
Shell::bind_func);
- if (wl_display_add_socket(m_display->handle(), qt_compositor->socketName())) {
+ if (wl_display_add_socket(m_display->handle(), m_qt_compositor->socketName())) {
fprintf(stderr, "Fatal: Failed to open server socket\n");
exit(EXIT_FAILURE);
}
@@ -163,18 +168,12 @@ Compositor::Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::Ex
connect(dispatcher, SIGNAL(aboutToBlock()), this, SLOT(processWaylandEvents()));
qRegisterMetaType<SurfaceBuffer*>("SurfaceBuffer*");
+ qRegisterMetaType<QWaylandSurface*>("WaylandSurface*");
//initialize distancefieldglyphcache here
-#ifdef QT_COMPOSITOR_QUICK
- if (QQuickWindow *w = qobject_cast<QQuickWindow *>(qt_compositor->window())) {
- connect(w, SIGNAL(beforeSynchronizing()), this, SLOT(cleanupGraphicsResources()), Qt::DirectConnection);
- } else
-#endif
- {
-#if !defined(QT_NO_DEBUG) && !defined(QT_WAYLAND_NO_CLEANUP_WARNING)
- qWarning("QWaylandCompositor::cleanupGraphicsResources() must be called manually");
-#endif
- }
+ initializeHardwareIntegration();
+ initializeExtensions();
+ initializeDefaultInputDevice();
}
Compositor::~Compositor()
@@ -216,44 +215,26 @@ void Compositor::processWaylandEvents()
void Compositor::destroySurface(Surface *surface)
{
- InputDevice *dev = defaultInputDevice();
- if (dev->mouseFocus() == surface) {
- dev->setMouseFocus(0, QPointF(), QPointF());
- // Make sure the surface is reset regardless of what the grabber
- // interface's focus() does. (e.g. the default implementation does
- // nothing when a button is down which would be disastrous here)
- dev->pointerDevice()->setFocus(0, QPointF());
- }
- if (dev->pointerDevice()->current() == surface) {
- dev->pointerDevice()->setCurrent(0, QPointF());
- }
- if (dev->keyboardFocus() == surface)
- dev->setKeyboardFocus(0);
-
m_surfaces.removeOne(surface);
waylandCompositor()->surfaceAboutToBeDestroyed(surface->waylandSurface());
surface->releaseSurfaces();
- m_destroyed_surfaces << surface;
+ m_destroyed_surfaces << surface->waylandSurface();
}
void Compositor::cleanupGraphicsResources()
{
- foreach (SurfaceBuffer *s, m_destroyed_buffers)
- s->bufferWasDestroyed();
- m_destroyed_buffers.clear();
-
qDeleteAll(m_destroyed_surfaces);
m_destroyed_surfaces.clear();
}
void Compositor::compositor_create_surface(Resource *resource, uint32_t id)
{
- Surface *surface = new Surface(resource->client(), id, this);
- m_surfaces << surface;
+ QWaylandSurface *surface = new QWaylandSurface(resource->client(), id, m_qt_compositor);
+ m_surfaces << surface->handle();
//BUG: This may not be an on-screen window surface though
- m_qt_compositor->surfaceCreated(surface->waylandSurface());
+ m_qt_compositor->surfaceCreated(surface);
}
void Compositor::compositor_create_region(Resource *resource, uint32_t id)
diff --git a/src/compositor/wayland_wrapper/qwlcompositor_p.h b/src/compositor/wayland_wrapper/qwlcompositor_p.h
index 450ee23ed..835fa1fd8 100644
--- a/src/compositor/wayland_wrapper/qwlcompositor_p.h
+++ b/src/compositor/wayland_wrapper/qwlcompositor_p.h
@@ -90,7 +90,9 @@ public:
Compositor(QWaylandCompositor *qt_compositor, QWaylandCompositor::ExtensionFlags extensions);
~Compositor();
+ void init();
void sendFrameCallbacks(QList<QWaylandSurface *> visibleSurfaces);
+ void frameFinished(Surface *surface = 0);
InputDevice *defaultInputDevice(); //we just have 1 default device for now (since QPA doesn't give us anything else)
@@ -155,8 +157,6 @@ public:
bool retainedSelectionEnabled() const;
void overrideSelection(const QMimeData *data);
void feedRetainedSelectionData(QMimeData *data);
-
- void bufferWasDestroyed(SurfaceBuffer *buffer) { m_destroyed_buffers << buffer; }
public slots:
void cleanupGraphicsResources();
@@ -166,13 +166,14 @@ protected:
private slots:
void processWaylandEvents();
-private:
+protected:
void loadClientBufferIntegration();
void loadServerBufferIntegration();
QWaylandCompositor::ExtensionFlags m_extensions;
Display *m_display;
+ QByteArray m_socket_name;
/* Input */
QWaylandInputDevice *m_default_wayland_input_device;
@@ -186,8 +187,7 @@ private:
QElapsedTimer m_timer;
QList<Surface *> m_surfaces;
- QSet<Surface *> m_destroyed_surfaces;
- QSet<SurfaceBuffer *> m_destroyed_buffers;
+ QSet<QWaylandSurface *> m_destroyed_surfaces;
/* Render state */
uint32_t m_current_frame;
@@ -220,6 +220,8 @@ private:
uint32_t version, uint32_t id);
bool m_retainSelection;
+
+ friend class ::QWaylandCompositor;
};
}
diff --git a/src/compositor/wayland_wrapper/qwlinputdevice.cpp b/src/compositor/wayland_wrapper/qwlinputdevice.cpp
index 50ed377a6..0f3fce94f 100644
--- a/src/compositor/wayland_wrapper/qwlinputdevice.cpp
+++ b/src/compositor/wayland_wrapper/qwlinputdevice.cpp
@@ -260,7 +260,7 @@ Surface *InputDevice::keyboardFocus() const
*/
bool InputDevice::setKeyboardFocus(Surface *surface)
{
- if (surface && surface->transientInactive())
+ if (surface && (surface->transientInactive() || surface->isDestroyed()))
return false;
m_keyboard->setFocus(surface);
@@ -276,6 +276,9 @@ Surface *InputDevice::mouseFocus() const
void InputDevice::setMouseFocus(Surface *surface, const QPointF &localPos, const QPointF &globalPos)
{
+ if (surface && surface->isDestroyed())
+ return;
+
m_pointer->setMouseFocus(surface, localPos, globalPos);
// We have no separate touch focus management so make it match the pointer focus always.
diff --git a/src/compositor/wayland_wrapper/qwlkeyboard.cpp b/src/compositor/wayland_wrapper/qwlkeyboard.cpp
index 4c3aa8920..25e7155b0 100644
--- a/src/compositor/wayland_wrapper/qwlkeyboard.cpp
+++ b/src/compositor/wayland_wrapper/qwlkeyboard.cpp
@@ -75,6 +75,7 @@ Keyboard::Keyboard(Compositor *compositor, InputDevice *seat)
#ifndef QT_NO_WAYLAND_XKB
initXKB();
#endif
+ connect(&m_focusDestroyListener, &WlListener::fired, this, &Keyboard::focusDestroyed);
}
Keyboard::~Keyboard()
@@ -93,6 +94,7 @@ void Keyboard::setFocus(Surface *surface)
if (m_focusResource && m_focus != surface) {
uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
send_leave(m_focusResource->handle, serial, m_focus->resource()->handle);
+ m_focusDestroyListener.reset();
}
Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0;
@@ -101,6 +103,7 @@ void Keyboard::setFocus(Surface *surface)
uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group);
send_enter(resource->handle, serial, surface->resource()->handle, QByteArray::fromRawData((char *)m_keys.data(), m_keys.size() * sizeof(uint32_t)));
+ m_focusDestroyListener.listenForDestruction(surface->resource()->handle);
}
m_focusResource = resource;
@@ -114,6 +117,15 @@ void Keyboard::setKeymap(const QWaylandKeymap &keymap)
m_pendingKeymap = true;
}
+void Keyboard::focusDestroyed(void *data)
+{
+ Q_UNUSED(data)
+ m_focusDestroyListener.reset();
+
+ m_focus = 0;
+ m_focusResource = 0;
+}
+
void Keyboard::sendKeyModifiers(wl_keyboard::Resource *resource, uint32_t serial)
{
send_modifiers(resource->handle, serial, m_modsDepressed, m_modsLatched, m_modsLocked, m_group);
diff --git a/src/compositor/wayland_wrapper/qwlkeyboard_p.h b/src/compositor/wayland_wrapper/qwlkeyboard_p.h
index b20fa97f7..6faf6ace2 100644
--- a/src/compositor/wayland_wrapper/qwlkeyboard_p.h
+++ b/src/compositor/wayland_wrapper/qwlkeyboard_p.h
@@ -54,6 +54,8 @@
#include <xkbcommon/xkbcommon.h>
#endif
+#include "qwllistener_p.h"
+
QT_BEGIN_NAMESPACE
namespace QtWayland {
@@ -91,6 +93,7 @@ private:
void sendKeyEvent(uint code, uint32_t state);
void updateModifierState(uint code, uint32_t state);
void updateKeymap();
+ void focusDestroyed(void *data);
#ifndef QT_NO_WAYLAND_XKB
void initXKB();
@@ -102,6 +105,7 @@ private:
Surface *m_focus;
Resource *m_focusResource;
+ WlListener m_focusDestroyListener;
QVector<uint32_t> m_keys;
uint32_t m_modsDepressed;
diff --git a/src/compositor/wayland_wrapper/qwllistener.cpp b/src/compositor/wayland_wrapper/qwllistener.cpp
new file mode 100644
index 000000000..a754981bf
--- /dev/null
+++ b/src/compositor/wayland_wrapper/qwllistener.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwllistener_p.h"
+
+QT_BEGIN_NAMESPACE
+
+WlListener::WlListener()
+{
+ m_listener.parent = this;
+ m_listener.listener.notify = handler;
+ wl_list_init(&m_listener.listener.link);
+}
+
+void WlListener::listenForDestruction(::wl_resource *resource)
+{
+ wl_resource_add_destroy_listener(resource, &m_listener.listener);
+}
+
+void WlListener::reset()
+{
+ wl_list_remove(&m_listener.listener.link);
+ wl_list_init(&m_listener.listener.link);
+}
+
+void WlListener::handler(wl_listener *listener, void *data)
+{
+ WlListener *that = reinterpret_cast<Listener *>(listener)->parent;
+ emit that->fired(data);
+}
+
+QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwllistener_p.h b/src/compositor/wayland_wrapper/qwllistener_p.h
new file mode 100644
index 000000000..4c49b1433
--- /dev/null
+++ b/src/compositor/wayland_wrapper/qwllistener_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Jolla Ltd, author: <giulio.camuffo@jollamobile.com>
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 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 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTWAYLAND_QWLLISTENER_H
+#define QTWAYLAND_QWLLISTENER_H
+
+#include <QObject>
+
+#include <wayland-server.h>
+
+QT_BEGIN_NAMESPACE
+
+class WlListener : public QObject
+{
+ Q_OBJECT
+public:
+ WlListener();
+
+ void listenForDestruction(::wl_resource *resource);
+ void reset();
+
+signals:
+ void fired(void *data);
+
+private:
+ static void handler(wl_listener *listener, void *data);
+
+ struct Listener {
+ wl_listener listener;
+ WlListener *parent;
+ };
+ Listener m_listener;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/compositor/wayland_wrapper/qwlpointer.cpp b/src/compositor/wayland_wrapper/qwlpointer.cpp
index b459472a2..60082e325 100644
--- a/src/compositor/wayland_wrapper/qwlpointer.cpp
+++ b/src/compositor/wayland_wrapper/qwlpointer.cpp
@@ -96,6 +96,7 @@ Pointer::Pointer(Compositor *compositor, InputDevice *seat)
, m_currentPoint()
, m_buttonCount()
{
+ connect(&m_focusDestroyListener, &WlListener::fired, this, &Pointer::focusDestroyed);
}
void Pointer::setFocus(Surface *surface, const QPointF &position)
@@ -103,6 +104,7 @@ void Pointer::setFocus(Surface *surface, const QPointF &position)
if (m_focusResource && m_focus != surface) {
uint32_t serial = wl_display_next_serial(m_compositor->wl_display());
send_leave(m_focusResource->handle, serial, m_focus->resource()->handle);
+ m_focusDestroyListener.reset();
}
Resource *resource = surface ? resourceMap().value(surface->resource()->client()) : 0;
@@ -117,12 +119,24 @@ void Pointer::setFocus(Surface *surface, const QPointF &position)
}
send_enter(resource->handle, serial, surface->resource()->handle,
wl_fixed_from_double(position.x()), wl_fixed_from_double(position.y()));
+
+ m_focusDestroyListener.listenForDestruction(surface->resource()->handle);
}
m_focusResource = resource;
m_focus = surface;
}
+void Pointer::focusDestroyed(void *data)
+{
+ Q_UNUSED(data)
+ m_focusDestroyListener.reset();
+
+ m_focus = 0;
+ m_focusResource = 0;
+ setMouseFocus(0, QPointF(), QPointF());
+}
+
void Pointer::startGrab(PointerGrabber *grab)
{
m_grab = grab;
diff --git a/src/compositor/wayland_wrapper/qwlpointer_p.h b/src/compositor/wayland_wrapper/qwlpointer_p.h
index ed53b048c..e125ab323 100644
--- a/src/compositor/wayland_wrapper/qwlpointer_p.h
+++ b/src/compositor/wayland_wrapper/qwlpointer_p.h
@@ -46,11 +46,14 @@
#include <QtCore/QList>
#include <QtCore/QPoint>
+#include <QtCore/QObject>
#include <QtCompositor/private/qwayland-server-wayland.h>
#include <stdint.h>
+#include "qwllistener_p.h"
+
QT_BEGIN_NAMESPACE
namespace QtWayland {
@@ -71,7 +74,7 @@ public:
Pointer *m_pointer;
};
-class Q_COMPOSITOR_EXPORT Pointer : public QtWaylandServer::wl_pointer, public PointerGrabber
+class Q_COMPOSITOR_EXPORT Pointer : public QObject, public QtWaylandServer::wl_pointer, public PointerGrabber
{
public:
Pointer(Compositor *compositor, InputDevice *seat);
@@ -112,6 +115,8 @@ protected:
void pointer_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
private:
+ void focusDestroyed(void *data);
+
Compositor *m_compositor;
InputDevice *m_seat;
@@ -129,6 +134,8 @@ private:
QPointF m_currentPoint;
int m_buttonCount;
+
+ WlListener m_focusDestroyListener;
};
} // namespace QtWayland
diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp
index 5928bbb0f..98d494ac8 100644
--- a/src/compositor/wayland_wrapper/qwlsurface.cpp
+++ b/src/compositor/wayland_wrapper/qwlsurface.cpp
@@ -41,10 +41,6 @@
#include "qwlsurface_p.h"
#include "qwaylandsurface.h"
-#ifdef QT_COMPOSITOR_QUICK
-#include "qwaylandsurfaceitem.h"
-#endif
-
#include "qwlcompositor_p.h"
#include "qwlinputdevice_p.h"
#include "qwlextendedsurface_p.h"
@@ -58,11 +54,6 @@
#include <wayland-server.h>
-#ifdef QT_COMPOSITOR_WAYLAND_GL
-#include "hardware_integration/qwlclientbufferintegration_p.h"
-#include <qpa/qplatformopenglcontext.h>
-#endif
-
#ifdef QT_WAYLAND_WINDOWMANAGER_SUPPORT
#include "waylandwindowmanagerintegration.h"
#endif
@@ -117,19 +108,20 @@ public:
bool canSend;
};
-Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
+Surface::Surface(struct wl_client *client, uint32_t id, QWaylandCompositor *compositor, QWaylandSurface *surface)
: QtWaylandServer::wl_surface(client, id)
- , m_compositor(compositor)
- , m_waylandSurface(new QWaylandSurface(this))
- , m_backBuffer(0)
- , m_frontBuffer(0)
+ , m_compositor(compositor->handle())
+ , m_waylandSurface(surface)
+ , m_buffer(0)
, m_surfaceMapped(false)
+ , m_attacher(0)
, m_extendedSurface(0)
, m_subSurface(0)
, m_shellSurface(0)
, m_inputPanelSurface(0)
, m_transientInactive(false)
, m_isCursorSurface(false)
+ , m_destroyed(false)
{
m_pending.buffer = 0;
m_pending.newlyAttached = false;
@@ -137,9 +129,10 @@ Surface::Surface(struct wl_client *client, uint32_t id, Compositor *compositor)
Surface::~Surface()
{
- delete m_waylandSurface;
delete m_subSurface;
+ m_bufferRef = QWaylandBufferRef();
+
for (int i = 0; i < m_bufferPool.size(); i++)
delete m_bufferPool[i];
@@ -151,10 +144,7 @@ Surface::~Surface()
void Surface::releaseSurfaces()
{
- delete m_waylandSurface;
- m_waylandSurface = 0;
- delete m_subSurface;
- m_subSurface = 0;
+
}
Surface *Surface::fromResource(struct ::wl_resource *resource)
@@ -164,9 +154,8 @@ Surface *Surface::fromResource(struct ::wl_resource *resource)
QWaylandSurface::Type Surface::type() const
{
- SurfaceBuffer *surfaceBuffer = currentSurfaceBuffer();
- if (surfaceBuffer && surfaceBuffer->waylandBufferHandle()) {
- if (surfaceBuffer->isShmBuffer()) {
+ if (m_buffer && m_buffer->waylandBufferHandle()) {
+ if (m_buffer->isShmBuffer()) {
return QWaylandSurface::Shm;
} else {
return QWaylandSurface::Texture;
@@ -177,27 +166,14 @@ QWaylandSurface::Type Surface::type() const
bool Surface::isYInverted() const
{
- bool ret = false;
- static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt();
- ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration();
-
-#ifdef QT_COMPOSITOR_WAYLAND_GL
- SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
- if (!surfacebuffer) {
- ret = false;
- } else if (clientBufferIntegration && surfacebuffer->waylandBufferHandle() && type() != QWaylandSurface::Shm) {
- ret = clientBufferIntegration->isYInverted(surfacebuffer->waylandBufferHandle());
- } else
-#endif
- ret = true;
-
- return ret != negateReturn;
+ if (m_buffer)
+ return m_buffer->isYInverted();
+ return false;
}
bool Surface::mapped() const
{
- SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
- return surfacebuffer ? bool(surfacebuffer->waylandBufferHandle()) : false;
+ return m_buffer ? bool(m_buffer->waylandBufferHandle()) : false;
}
QPointF Surface::pos() const
@@ -246,28 +222,6 @@ QRegion Surface::opaqueRegion() const
return m_opaqueRegion;
}
-QImage Surface::image() const
-{
- SurfaceBuffer *surfacebuffer = currentSurfaceBuffer();
- if (surfacebuffer && !surfacebuffer->isDestroyed() && type() == QWaylandSurface::Shm) {
- return surfacebuffer->image();
- }
- return QImage();
-}
-
-#ifdef QT_COMPOSITOR_WAYLAND_GL
-GLuint Surface::textureId() const
-{
- const SurfaceBuffer *surfacebuffer = m_frontBuffer;
-
- if (m_compositor->clientBufferIntegration() && type() == QWaylandSurface::Texture
- && !surfacebuffer->textureCreated()) {
- const_cast<SurfaceBuffer *>(surfacebuffer)->createTexture();
- }
- return surfacebuffer->texture();
-}
-#endif // QT_COMPOSITOR_WAYLAND_GL
-
void Surface::sendFrameCallback()
{
uint time = m_compositor->currentTimeMsecs();
@@ -342,25 +296,6 @@ Compositor *Surface::compositor() const
return m_compositor;
}
-void Surface::swapBuffers()
- {
- SurfaceBuffer *front = m_frontBuffer;
-
- // Advance current back buffer to the front buffer.
- if (m_backBuffer) {
- if (m_backBuffer->isDestroyed()) {
- m_backBuffer->disown();
- m_backBuffer = 0;
- }
- m_frontBuffer = m_backBuffer;
- m_backBuffer = 0;
- }
-
- // Release the old front buffer if we changed it.
- if (front && front != m_frontBuffer)
- front->disown();
-}
-
/*!
* Sets the backbuffer for this surface. The back buffer is not yet on
* screen and will become live during the next swapBuffers().
@@ -370,11 +305,11 @@ void Surface::swapBuffers()
*/
void Surface::setBackBuffer(SurfaceBuffer *buffer)
{
- m_backBuffer = buffer;
+ m_buffer = buffer;
- if (m_backBuffer) {
- bool valid = m_backBuffer->waylandBufferHandle() != 0;
- setSize(valid ? m_backBuffer->size() : QSize());
+ if (m_buffer) {
+ bool valid = m_buffer->waylandBufferHandle() != 0;
+ setSize(valid ? m_buffer->size() : QSize());
if ((!m_subSurface || !m_subSurface->parent()) && !m_surfaceMapped) {
m_surfaceMapped = true;
@@ -426,7 +361,9 @@ void Surface::surface_destroy_resource(Resource *)
m_extendedSurface = 0;
}
- compositor()->destroySurface(this);
+ m_destroyed = true;
+ m_waylandSurface->destroy();
+ emit m_waylandSurface->surfaceDestroyed();
}
void Surface::surface_destroy(Resource *resource)
@@ -469,14 +406,17 @@ void Surface::surface_commit(Resource *)
m_damage = m_pending.damage;
if (m_pending.buffer || m_pending.newlyAttached) {
- if (m_backBuffer && m_backBuffer != m_pending.buffer)
- m_backBuffer->disown();
-
setBackBuffer(m_pending.buffer);
- if (!m_backBuffer && m_surfaceMapped) {
+ if (!m_buffer && m_surfaceMapped) {
m_surfaceMapped = false;
emit m_waylandSurface->unmapped();
}
+
+ m_bufferRef = QWaylandBufferRef(m_buffer);
+
+ if (m_attacher)
+ m_attacher->attach(m_bufferRef);
+ emit m_waylandSurface->configure();
}
m_pending.buffer = 0;
@@ -484,13 +424,13 @@ void Surface::surface_commit(Resource *)
m_pending.newlyAttached = false;
m_pending.damage = QRegion();
- if (m_backBuffer)
- m_backBuffer->setCommitted();
+ if (m_buffer)
+ m_buffer->setCommitted();
m_frameCallbacks << m_pendingFrameCallbacks;
m_pendingFrameCallbacks.clear();
- emit m_waylandSurface->committed();
+ emit m_waylandSurface->redraw();
}
void Surface::frameStarted()
diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h
index 6d911e915..12984a1f2 100644
--- a/src/compositor/wayland_wrapper/qwlsurface_p.h
+++ b/src/compositor/wayland_wrapper/qwlsurface_p.h
@@ -45,6 +45,7 @@
#include <private/qwlsurfacebuffer_p.h>
#include <QtCompositor/qwaylandsurface.h>
+#include <QtCompositor/qwaylandbufferref.h>
#include <QtCore/QVector>
#include <QtCore/QRect>
@@ -54,10 +55,6 @@
#include <QtCore/QTextStream>
#include <QtCore/QMetaType>
-#ifdef QT_COMPOSITOR_WAYLAND_GL
-#include <QtGui/qopengl.h>
-#endif
-
#include <wayland-util.h>
#include <QtCompositor/private/qwayland-server-wayland.h>
@@ -79,7 +76,7 @@ class FrameCallback;
class Q_COMPOSITOR_EXPORT Surface : public QtWaylandServer::wl_surface
{
public:
- Surface(struct wl_client *client, uint32_t id, Compositor *compositor);
+ Surface(struct wl_client *client, uint32_t id, QWaylandCompositor *compositor, QWaylandSurface *surface);
~Surface();
static Surface *fromResource(struct ::wl_resource *resource);
@@ -101,12 +98,6 @@ public:
QRegion inputRegion() const;
QRegion opaqueRegion() const;
- QImage image() const;
-
-#ifdef QT_COMPOSITOR_WAYLAND_GL
- GLuint textureId() const;
-#endif
-
void sendFrameCallback();
void removeFrameCallback(FrameCallback *callback);
@@ -140,20 +131,37 @@ public:
bool isCursorSurface() const { return m_isCursorSurface; }
void setCursorSurface(bool isCursor) { m_isCursorSurface = isCursor; }
- void swapBuffers();
void releaseSurfaces();
void frameStarted();
-private:
+ inline bool isDestroyed() const { return m_destroyed; }
+
+protected:
+ void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
+
+ void surface_destroy(Resource *resource) Q_DECL_OVERRIDE;
+ void surface_attach(Resource *resource,
+ struct wl_resource *buffer, int x, int y) Q_DECL_OVERRIDE;
+ void surface_damage(Resource *resource,
+ int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE;
+ void surface_frame(Resource *resource,
+ uint32_t callback) Q_DECL_OVERRIDE;
+ void surface_set_opaque_region(Resource *resource,
+ struct wl_resource *region) Q_DECL_OVERRIDE;
+ void surface_set_input_region(Resource *resource,
+ struct wl_resource *region) Q_DECL_OVERRIDE;
+ void surface_commit(Resource *resource) Q_DECL_OVERRIDE;
+
Q_DISABLE_COPY(Surface)
Compositor *m_compositor;
QWaylandSurface *m_waylandSurface;
- SurfaceBuffer *m_backBuffer;
QRegion m_damage;
- SurfaceBuffer *m_frontBuffer;
+ SurfaceBuffer *m_buffer;
+ QWaylandBufferRef m_bufferRef;
bool m_surfaceMapped;
+ QWaylandBufferAttacher *m_attacher;
struct {
SurfaceBuffer *buffer;
@@ -184,32 +192,12 @@ private:
QString m_title;
bool m_transientInactive;
bool m_isCursorSurface;
+ bool m_destroyed;
- inline SurfaceBuffer *currentSurfaceBuffer() const;
void setBackBuffer(SurfaceBuffer *buffer);
SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer);
-
- void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE;
-
- void surface_destroy(Resource *resource) Q_DECL_OVERRIDE;
- void surface_attach(Resource *resource,
- struct wl_resource *buffer, int x, int y) Q_DECL_OVERRIDE;
- void surface_damage(Resource *resource,
- int32_t x, int32_t y, int32_t width, int32_t height) Q_DECL_OVERRIDE;
- void surface_frame(Resource *resource,
- uint32_t callback) Q_DECL_OVERRIDE;
- void surface_set_opaque_region(Resource *resource,
- struct wl_resource *region) Q_DECL_OVERRIDE;
- void surface_set_input_region(Resource *resource,
- struct wl_resource *region) Q_DECL_OVERRIDE;
- void surface_commit(Resource *resource) Q_DECL_OVERRIDE;
-
};
-inline SurfaceBuffer *Surface::currentSurfaceBuffer() const {
- return m_backBuffer? m_backBuffer : m_frontBuffer;
-}
-
}
QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
index b0e67e1fa..3ed469a6c 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
+++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp
@@ -100,8 +100,6 @@ void SurfaceBuffer::initialize(struct ::wl_resource *buffer)
void SurfaceBuffer::destructBufferState()
{
- destroyTexture();
-
if (m_buffer) {
sendRelease();
@@ -239,24 +237,23 @@ QImage SurfaceBuffer::image()
return m_image;
}
-void SurfaceBuffer::bufferWasDestroyed()
-{
- destroyTexture();
- m_destroyed = true;
- m_buffer = 0;
-}
-
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;
- d->m_compositor->bufferWasDestroyed(d);
+
+ // 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::createTexture()
{
+ destroyTexture();
+
ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration();
#ifdef QT_COMPOSITOR_WAYLAND_GL
if (!m_texture)
@@ -271,6 +268,22 @@ void SurfaceBuffer::createTexture()
#endif
}
+bool SurfaceBuffer::isYInverted() const
+{
+ bool ret = false;
+ static bool negateReturn = qgetenv("QT_COMPOSITOR_NEGATE_INVERTED_Y").toInt();
+ ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration();
+
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+ if (clientBufferIntegration && waylandBufferHandle() && isShmBuffer()) {
+ ret = clientBufferIntegration->isYInverted(waylandBufferHandle());
+ } else
+#endif
+ ret = true;
+
+ return ret != negateReturn;
+}
+
}
QT_END_NAMESPACE
diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
index c2c39253a..26993b5d0 100644
--- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
+++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h
@@ -44,12 +44,14 @@
#include <QtCore/QRect>
#include <QtGui/qopengl.h>
#include <QImage>
+#include <QAtomicInt>
#include <wayland-server.h>
QT_BEGIN_NAMESPACE
class QWaylandClientBufferIntegration;
+class QWaylandBufferRef;
namespace QtWayland {
@@ -75,6 +77,7 @@ public:
QSize size() const;
bool isShmBuffer() const;
+ bool isYInverted() const;
inline bool isRegisteredWithBuffer() const { return m_is_registered_for_buffer; }
@@ -131,10 +134,13 @@ private:
mutable bool m_isSizeResolved;
mutable QSize m_size;
+ QAtomicInt m_refCount;
QImage m_image;
static void destroy_listener_callback(wl_listener *listener, void *data);
+
+ friend class ::QWaylandBufferRef;
};
GLuint SurfaceBuffer::texture() const
diff --git a/src/compositor/wayland_wrapper/qwltouch.cpp b/src/compositor/wayland_wrapper/qwltouch.cpp
index 2a4070e5e..d160bc4bf 100644
--- a/src/compositor/wayland_wrapper/qwltouch.cpp
+++ b/src/compositor/wayland_wrapper/qwltouch.cpp
@@ -54,10 +54,15 @@ Touch::Touch(Compositor *compositor)
, m_grab(this)
{
m_grab->setTouch(this);
+ connect(&m_focusDestroyListener, &WlListener::fired, this, &Touch::focusDestroyed);
}
void Touch::setFocus(Surface *surface)
{
+ m_focusDestroyListener.reset();
+ if (surface)
+ m_focusDestroyListener.listenForDestruction(surface->resource()->handle);
+
m_focus = surface;
m_focusResource = surface ? resourceMap().value(surface->resource()->client()) : 0;
}
@@ -73,6 +78,15 @@ void Touch::endGrab()
m_grab = this;
}
+void Touch::focusDestroyed(void *data)
+{
+ Q_UNUSED(data)
+ m_focusDestroyListener.reset();
+
+ m_focus = 0;
+ m_focusResource = 0;
+}
+
void Touch::sendCancel()
{
if (m_focusResource)
diff --git a/src/compositor/wayland_wrapper/qwltouch_p.h b/src/compositor/wayland_wrapper/qwltouch_p.h
index 695609809..fc6b4d0e3 100644
--- a/src/compositor/wayland_wrapper/qwltouch_p.h
+++ b/src/compositor/wayland_wrapper/qwltouch_p.h
@@ -45,9 +45,12 @@
#include <QtCompositor/qwaylandexport.h>
#include <QtCore/QPoint>
+#include <QtCore/QObject>
#include <QtCompositor/private/qwayland-server-wayland.h>
+#include "qwllistener_p.h"
+
QT_BEGIN_NAMESPACE
namespace QtWayland {
@@ -73,7 +76,7 @@ private:
Touch *m_touch;
};
-class Q_COMPOSITOR_EXPORT Touch : public QtWaylandServer::wl_touch, public TouchGrabber
+class Q_COMPOSITOR_EXPORT Touch : public QObject, public QtWaylandServer::wl_touch, public TouchGrabber
{
public:
explicit Touch(Compositor *compositor);
@@ -95,10 +98,13 @@ public:
void motion(uint32_t time, int touch_id, const QPointF &position);
private:
+ void focusDestroyed(void *data);
+
Compositor *m_compositor;
Surface *m_focus;
Resource *m_focusResource;
+ WlListener m_focusDestroyListener;
TouchGrabber *m_grab;
};
diff --git a/src/compositor/wayland_wrapper/wayland_wrapper.pri b/src/compositor/wayland_wrapper/wayland_wrapper.pri
index 3b695532c..ac34ae283 100644
--- a/src/compositor/wayland_wrapper/wayland_wrapper.pri
+++ b/src/compositor/wayland_wrapper/wayland_wrapper.pri
@@ -37,6 +37,7 @@ HEADERS += \
wayland_wrapper/qwltextinput_p.h \
wayland_wrapper/qwltextinputmanager_p.h \
wayland_wrapper/qwltouch_p.h \
+ wayland_wrapper/qwllistener_p.h \
SOURCES += \
wayland_wrapper/qwlcompositor.cpp \
@@ -65,6 +66,7 @@ SOURCES += \
wayland_wrapper/qwltextinput.cpp \
wayland_wrapper/qwltextinputmanager.cpp \
wayland_wrapper/qwltouch.cpp \
+ wayland_wrapper/qwllistener.cpp \
INCLUDEPATH += wayland_wrapper
diff --git a/tests/auto/compositor/tst_compositor.cpp b/tests/auto/compositor/tst_compositor.cpp
index 44fb2ff96..99f08a4e5 100644
--- a/tests/auto/compositor/tst_compositor.cpp
+++ b/tests/auto/compositor/tst_compositor.cpp
@@ -42,6 +42,8 @@
#include "mockclient.h"
#include "testcompositor.h"
+#include "qwaylandbufferref.h"
+
#include <QtTest/QtTest>
class tst_WaylandCompositor : public QObject
@@ -186,6 +188,24 @@ static void registerFrameCallback(wl_surface *surface, int *counter)
void tst_WaylandCompositor::frameCallback()
{
+ class BufferAttacher : public QWaylandBufferAttacher
+ {
+ public:
+ void attach(const QWaylandBufferRef &ref) Q_DECL_OVERRIDE
+ {
+ bufferRef = ref;
+ }
+
+ QImage image() const
+ {
+ if (!bufferRef || !bufferRef.isShm())
+ return QImage();
+ return bufferRef.image();
+ }
+
+ QWaylandBufferRef bufferRef;
+ };
+
TestCompositor compositor;
MockClient client;
@@ -200,7 +220,9 @@ void tst_WaylandCompositor::frameCallback()
QTRY_COMPARE(compositor.surfaces.size(), 1);
QWaylandSurface *waylandSurface = compositor.surfaces.at(0);
- QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRect &)));
+ BufferAttacher attacher;
+ waylandSurface->setBufferAttacher(&attacher);
+ QSignalSpy damagedSpy(waylandSurface, SIGNAL(damaged(const QRegion &)));
for (int i = 0; i < 10; ++i) {
registerFrameCallback(surface, &frameCounter);
@@ -209,7 +231,7 @@ void tst_WaylandCompositor::frameCallback()
QTRY_COMPARE(waylandSurface->type(), QWaylandSurface::Shm);
QTRY_COMPARE(damagedSpy.count(), i + 1);
- QCOMPARE(waylandSurface->image(), buffer.image);
+ QCOMPARE(static_cast<BufferAttacher *>(waylandSurface->bufferAttacher())->image(), buffer.image);
compositor.sendFrameCallbacks(QList<QWaylandSurface *>() << waylandSurface);
QTRY_COMPARE(frameCounter, i + 1);