summaryrefslogtreecommitdiffstats
path: root/src/compositor/wayland_wrapper
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 /src/compositor/wayland_wrapper
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>
Diffstat (limited to 'src/compositor/wayland_wrapper')
-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
16 files changed, 320 insertions, 183 deletions
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