diff options
author | Jørgen Lind <jorgen.lind@theqtcompany.com> | 2015-07-29 14:58:54 +0200 |
---|---|---|
committer | Jørgen Lind <jorgen.lind@theqtcompany.com> | 2015-08-28 13:09:41 +0200 |
commit | a327ca8d8a1f6e0a44a3aa6bd4dac716911c434e (patch) | |
tree | ae4c432c495a7baee8f97737160836cbb2e38476 /src | |
parent | 6c9c54587c6cd1059d5de652d06e248456832ab6 (diff) |
Move the texture ownership from the QWaylandSurface
to the respective QWaylandSurfaceView. For all GL applications this will have no
significant impact, but will cause a memory regression for shm surfaces
with multiple views.
This is done to simplify the creation and destruction of textures,
especially in multi-threaded environments.
Also the same patch removes the y_inverted property and replaces it with
a origin property. Its done in the same patch as a lot of the code was
overlapping.
Change-Id: I4bce50c614c9ac3ba0580e0560339476eac03433
Diffstat (limited to 'src')
22 files changed, 376 insertions, 534 deletions
diff --git a/src/compositor/compositor_api/qwaylandbufferref.cpp b/src/compositor/compositor_api/qwaylandbufferref.cpp index 8a0b9242c..7b5b3cd2b 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.cpp +++ b/src/compositor/compositor_api/qwaylandbufferref.cpp @@ -46,6 +46,10 @@ class QWaylandBufferRefPrivate { public: QtWayland::SurfaceBuffer *buffer; + + bool nullOrDestroyed() { + return !buffer || buffer->isDestroyed(); + } }; QWaylandBufferRef::QWaylandBufferRef() @@ -65,8 +69,9 @@ QWaylandBufferRef::QWaylandBufferRef(QtWayland::SurfaceBuffer *buffer) QWaylandBufferRef::QWaylandBufferRef(const QWaylandBufferRef &ref) : d(new QWaylandBufferRefPrivate) { - d->buffer = 0; - *this = ref; + d->buffer = ref.d->buffer; + if (d->buffer) + d->buffer->ref(); } QWaylandBufferRef::~QWaylandBufferRef() @@ -88,44 +93,75 @@ QWaylandBufferRef &QWaylandBufferRef::operator=(const QWaylandBufferRef &ref) return *this; } -QWaylandBufferRef::operator bool() const +bool QWaylandBufferRef::operator==(const QWaylandBufferRef &ref) { - return d->buffer && d->buffer->waylandBufferHandle(); + return d->buffer == ref.d->buffer; } -bool QWaylandBufferRef::isShm() const +bool QWaylandBufferRef::operator!=(const QWaylandBufferRef &ref) { - return d->buffer->isShmBuffer(); + return d->buffer != ref.d->buffer; } -QImage QWaylandBufferRef::image() const +bool QWaylandBufferRef::isNull() const { - if (d->buffer->isShmBuffer()) - return d->buffer->image(); - return QImage(); + return !d->buffer; } -#ifdef QT_COMPOSITOR_WAYLAND_GL +bool QWaylandBufferRef::hasBuffer() const +{ + return d->buffer && !d->buffer->isDestroyed(); +} -GLuint QWaylandBufferRef::createTexture() +struct ::wl_resource *QWaylandBufferRef::wl_buffer() const { - if (!d->buffer->isShmBuffer() && !d->buffer->textureCreated()) { - d->buffer->createTexture(); - } - return d->buffer->texture(); + return d->buffer ? d->buffer->waylandBufferHandle() : Q_NULLPTR; } -void QWaylandBufferRef::destroyTexture() +QSize QWaylandBufferRef::size() const { - if (!d->buffer->isShmBuffer() && d->buffer->textureCreated()) { - d->buffer->destroyTexture(); - } + if (d->nullOrDestroyed()) + return QSize(); + + return d->buffer->size(); +} + +QWaylandSurface::Origin QWaylandBufferRef::origin() const +{ + if (d->nullOrDestroyed()) + return QWaylandSurface::OriginBottomLeft; + + return d->buffer->origin(); +} + +bool QWaylandBufferRef::isShm() const +{ + if (d->nullOrDestroyed()) + return false; + + return d->buffer->isShm(); +} + +QImage QWaylandBufferRef::image() const +{ + if (d->nullOrDestroyed()) + return QImage(); + + return d->buffer->image(); +} + +void QWaylandBufferRef::bindToTexture() const +{ + if (d->nullOrDestroyed()) + return; + + return d->buffer->bindToTexture(); + } void *QWaylandBufferRef::nativeBuffer() const { return d->buffer->handle(); } -#endif QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandbufferref.h b/src/compositor/compositor_api/qwaylandbufferref.h index b397116a2..fa978fe80 100644 --- a/src/compositor/compositor_api/qwaylandbufferref.h +++ b/src/compositor/compositor_api/qwaylandbufferref.h @@ -43,8 +43,11 @@ #include <QtGui/qopengl.h> #endif +#include <QtCompositor/QWaylandSurface> #include <QtCompositor/qwaylandexport.h> +struct wl_resource; + QT_BEGIN_NAMESPACE namespace QtWayland @@ -61,20 +64,22 @@ public: ~QWaylandBufferRef(); QWaylandBufferRef &operator=(const QWaylandBufferRef &ref); - operator bool() const; - bool isShm() const; + bool isNull() const; + bool hasBuffer() const; + bool operator==(const QWaylandBufferRef &ref); + bool operator!=(const QWaylandBufferRef &ref); + + wl_resource *wl_buffer() const; + QSize size() const; + QWaylandSurface::Origin origin() const; + + bool isShm() const; QImage image() const; -#ifdef QT_COMPOSITOR_WAYLAND_GL - /** - * There must be a GL context bound when calling this function. - * The texture will be automatically destroyed when the last QWaylandBufferRef - * referring to the same underlying buffer will be destroyed or reset. - */ - GLuint createTexture(); - void destroyTexture(); + + void bindToTexture() const; + void *nativeBuffer() const; -#endif private: class QWaylandBufferRefPrivate *const d; diff --git a/src/compositor/compositor_api/qwaylandquickcompositor.cpp b/src/compositor/compositor_api/qwaylandquickcompositor.cpp index 15923659d..7c37e6c59 100644 --- a/src/compositor/compositor_api/qwaylandquickcompositor.cpp +++ b/src/compositor/compositor_api/qwaylandquickcompositor.cpp @@ -38,6 +38,8 @@ #include <QtCompositor/private/qwlcompositor_p.h> #include <QtCompositor/private/qwlsurface_p.h> +#include <QtQml/QQmlEngine> + #include "qwaylandclient.h" #include "qwaylandquickcompositor.h" #include "qwaylandquicksurface.h" @@ -101,16 +103,22 @@ QWaylandOutput *QWaylandQuickCompositor::createOutput(QWindow *window, const QString &manufacturer, const QString &model) { + QQmlEngine::setObjectOwnership(window, QQmlEngine::CppOwnership); + QQuickWindow *quickWindow = qobject_cast<QQuickWindow *>(window); if (!quickWindow) qFatal("%s: couldn't cast QWindow to QQuickWindow. All output windows must " "be QQuickWindow derivates when using QWaylandQuickCompositor", Q_FUNC_INFO); - return new QWaylandQuickOutput(this, quickWindow, manufacturer, model); + QWaylandQuickOutput *output = new QWaylandQuickOutput(this, quickWindow, manufacturer, model); + QQmlEngine::setObjectOwnership(output, QQmlEngine::CppOwnership); + return output; } QWaylandSurfaceView *QWaylandQuickCompositor::createView() { - return new QWaylandSurfaceItem(); + QWaylandSurfaceItem *view = new QWaylandSurfaceItem(); + QQmlEngine::setObjectOwnership(view, QQmlEngine::JavaScriptOwnership); + return view; } QWaylandSurface *QWaylandQuickCompositor::createSurface(QWaylandClient *client, quint32 id, int version) diff --git a/src/compositor/compositor_api/qwaylandquicksurface.cpp b/src/compositor/compositor_api/qwaylandquicksurface.cpp index a55569da9..ebefb3bc3 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.cpp +++ b/src/compositor/compositor_api/qwaylandquicksurface.cpp @@ -49,96 +49,21 @@ 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() - { - bufferRef = nextBuffer; - delete texture; - texture = 0; - - QQuickWindow *window = static_cast<QQuickWindow *>(surface->mainOutput()->window()); - if (nextBuffer) { - 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 unmap() Q_DECL_OVERRIDE - { - nextBuffer = QWaylandBufferRef(); - update = true; - } - - void invalidateTexture() - { - if (bufferRef) - bufferRef.destroyTexture(); - delete texture; - texture = 0; - update = true; - bufferRef = QWaylandBufferRef(); - } - - QWaylandQuickSurface *surface; - QWaylandBufferRef bufferRef; - QWaylandBufferRef nextBuffer; - QSGTexture *texture; - bool update; -}; - - class QWaylandQuickSurfacePrivate : public QWaylandSurfacePrivate { public: QWaylandQuickSurfacePrivate(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *c, QWaylandQuickSurface *surf) : QWaylandSurfacePrivate(client, id, version, 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 @@ -149,7 +74,6 @@ public: output->waylandOutput()->update(); } - BufferAttacher *buffer; QWaylandQuickCompositor *compositor; bool useTextureAlpha; QQmlPropertyMap *windowPropertyMap; @@ -160,8 +84,10 @@ QWaylandQuickSurface::QWaylandQuickSurface(wl_client *client, quint32 id, int ve : QWaylandSurface(new QWaylandQuickSurfacePrivate(client, id, version, compositor, this)) { Q_D(QWaylandQuickSurface); - d->buffer->surface = this; - setBufferAttacher(d->buffer); + connect(this, &QWaylandSurface::shellViewCreated, this, &QWaylandQuickSurface::shellViewCreated); + connect(this, &QWaylandSurface::outputChanged, this, &QWaylandQuickSurface::outputWindowChanged); + connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert); + connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty); connect(this, &QWaylandSurface::windowPropertyChanged, d->windowPropertyMap, &QQmlPropertyMap::insert); connect(d->windowPropertyMap, &QQmlPropertyMap::valueChanged, this, &QWaylandSurface::setWindowProperty); @@ -173,12 +99,6 @@ QWaylandQuickSurface::~QWaylandQuickSurface() } -QSGTexture *QWaylandQuickSurface::texture() const -{ - Q_D(const QWaylandQuickSurface); - return d->buffer->texture; -} - bool QWaylandQuickSurface::useTextureAlpha() const { Q_D(const QWaylandQuickSurface); @@ -191,7 +111,7 @@ void QWaylandQuickSurface::setUseTextureAlpha(bool useTextureAlpha) if (d->useTextureAlpha != useTextureAlpha) { d->useTextureAlpha = useTextureAlpha; emit useTextureAlphaChanged(); - emit configure(d->buffer->bufferRef); + emit configure(handle()->currentBufferRef().hasBuffer()); } } @@ -251,25 +171,6 @@ bool QWaylandQuickSurface::event(QEvent *e) return QObject::event(e); } -void QWaylandQuickSurface::updateTexture() -{ - Q_D(QWaylandQuickSurface); - const bool update = d->buffer->update; - if (d->buffer->update) - d->buffer->createTexture(); - foreach (QWaylandSurfaceView *view, views()) - static_cast<QWaylandSurfaceItem *>(view)->updateTexture(update); -} - -void QWaylandQuickSurface::invalidateTexture() -{ - Q_D(QWaylandQuickSurface); - d->buffer->invalidateTexture(); - foreach (QWaylandSurfaceView *view, views()) - static_cast<QWaylandSurfaceItem *>(view)->updateTexture(true); - emit redraw(); -} - bool QWaylandQuickSurface::clientRenderingEnabled() const { Q_D(const QWaylandQuickSurface); diff --git a/src/compositor/compositor_api/qwaylandquicksurface.h b/src/compositor/compositor_api/qwaylandquicksurface.h index 0ab019d6c..3f262a402 100644 --- a/src/compositor/compositor_api/qwaylandquicksurface.h +++ b/src/compositor/compositor_api/qwaylandquicksurface.h @@ -43,8 +43,6 @@ struct wl_client; QT_BEGIN_NAMESPACE -class QSGTexture; - class QWaylandSurfaceItem; class QWaylandQuickSurfacePrivate; class QWaylandQuickCompositor; @@ -62,8 +60,6 @@ public: QWaylandQuickSurface(wl_client *client, quint32 id, int version, QWaylandQuickCompositor *compositor); ~QWaylandQuickSurface(); - QSGTexture *texture() const; - bool useTextureAlpha() const; void setUseTextureAlpha(bool useTextureAlpha); @@ -83,12 +79,6 @@ Q_SIGNALS: void clientRenderingEnabledChanged(); void shellViewCreated(); void outputWindowChanged(); - -private: - void updateTexture(); - void invalidateTexture(); - - void onOutputChanged(QWaylandOutput *newOutput, QWaylandOutput *oldOutput); }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp index bec39a184..5ffe58e0a 100644 --- a/src/compositor/compositor_api/qwaylandsurface.cpp +++ b/src/compositor/compositor_api/qwaylandsurface.cpp @@ -132,20 +132,17 @@ QWaylandOutput *QWaylandSurfaceLeaveEvent::output() const QWaylandSurface::QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor) : QObject(*new QWaylandSurfacePrivate(client, id, version, compositor, this)) { - } QWaylandSurface::QWaylandSurface(QWaylandSurfacePrivate *dptr) : QObject(*dptr) { - } QWaylandSurface::~QWaylandSurface() { Q_D(QWaylandSurface); qDeleteAll(d->interfaces); - delete d->m_attacher; } QWaylandClient *QWaylandSurface::client() const @@ -186,18 +183,6 @@ void QWaylandSurface::removeInterface(QWaylandSurfaceInterface *iface) d->interfaces.removeOne(iface); } -QWaylandSurface::Type QWaylandSurface::type() const -{ - Q_D(const QWaylandSurface); - return d->type(); -} - -bool QWaylandSurface::isYInverted() const -{ - Q_D(const QWaylandSurface); - return d->isYInverted(); -} - bool QWaylandSurface::visible() const { return isMapped(); @@ -253,6 +238,12 @@ QWaylandSurface::WindowType QWaylandSurface::windowType() const return d->windowType; } +QWaylandSurface::Origin QWaylandSurface::origin() const +{ + Q_D(const QWaylandSurface); + return d->origin(); +} + QWaylandSurface *QWaylandSurface::transientParent() const { Q_D(const QWaylandSurface); @@ -459,18 +450,6 @@ void QWaylandSurface::setMapped(bool mapped) d->setMapped(mapped); } -void QWaylandSurface::setBufferAttacher(QWaylandBufferAttacher *attacher) -{ - Q_D(QWaylandSurface); - d->m_attacher = attacher; -} - -QWaylandBufferAttacher *QWaylandSurface::bufferAttacher() const -{ - Q_D(const QWaylandSurface); - return d->m_attacher; -} - QList<QWaylandSurfaceView *> QWaylandSurface::views() const { Q_D(const QWaylandSurface); diff --git a/src/compositor/compositor_api/qwaylandsurface.h b/src/compositor/compositor_api/qwaylandsurface.h index a8ce58495..9dce15a6b 100644 --- a/src/compositor/compositor_api/qwaylandsurface.h +++ b/src/compositor/compositor_api/qwaylandsurface.h @@ -66,18 +66,6 @@ class SurfacePrivate; class ExtendedSurface; } -class Q_COMPOSITOR_EXPORT QWaylandBufferAttacher -{ -public: - virtual ~QWaylandBufferAttacher() {} - -protected: - virtual void attach(const QWaylandBufferRef &ref) = 0; - virtual void unmap() = 0; - - friend class QtWayland::Surface; -}; - class QWaylandSurfaceEnterEventPrivate; class Q_COMPOSITOR_EXPORT QWaylandSurfaceEnterEvent : public QEvent @@ -126,7 +114,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurface : public QObject Q_PROPERTY(QWaylandSurface *transientParent READ transientParent) Q_PROPERTY(QPointF transientOffset READ transientOffset) Q_PROPERTY(QWaylandOutput *output READ output NOTIFY outputChanged) - Q_PROPERTY(bool isYInverted READ isYInverted NOTIFY yInvertedChanged) + Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged); Q_ENUMS(WindowFlag WindowType) Q_FLAGS(WindowFlag WindowFlags) @@ -146,10 +134,9 @@ public: Popup }; - enum Type { - Invalid, - Shm, - Texture + enum Origin { + OriginTopLeft, + OriginBottomLeft }; QWaylandSurface(wl_client *client, quint32 id, int version, QWaylandCompositor *compositor); @@ -162,9 +149,6 @@ public: void addInterface(QWaylandSurfaceInterface *interface); void removeInterface(QWaylandSurfaceInterface *interface); - Type type() const; - bool isYInverted() const; - bool visible() const; bool isMapped() const; @@ -177,6 +161,7 @@ public: WindowFlags windowFlags() const; WindowType windowType() const; + Origin origin() const; QWindow::Visibility visibility() const; void setVisibility(QWindow::Visibility visibility); @@ -217,9 +202,6 @@ public: void deref(); void setMapped(bool mapped); - void setBufferAttacher(QWaylandBufferAttacher *attacher); - QWaylandBufferAttacher *bufferAttacher() const; - QList<QWaylandSurfaceView *> views() const; QList<QWaylandSurfaceInterface *> interfaces() const; @@ -257,7 +239,7 @@ Q_SIGNALS: void surfaceDestroyed(); void shellViewCreated(); void outputChanged(QWaylandOutput *newOutput, QWaylandOutput *oldOutput); - void yInvertedChanged(); + void originChanged(); void configure(bool hasBuffer); void redraw(); diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp index de5172ff5..4c3615c9f 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.cpp @@ -38,6 +38,9 @@ #include "qwaylandquicksurface.h" #include <QtCompositor/qwaylandcompositor.h> #include <QtCompositor/qwaylandinput.h> +#include <QtCompositor/qwaylandbufferref.h> +#include <QtCompositor/private/qwlcompositor_p.h> +#include <QtCompositor/private/qwlclientbufferintegration_p.h> #include <QtGui/QKeyEvent> #include <QtGui/QGuiApplication> @@ -49,6 +52,8 @@ #include <QtCore/QMutexLocker> #include <QtCore/QMutex> +#include <wayland-server.h> +#include <QThread> QT_BEGIN_NAMESPACE QMutex *QWaylandSurfaceItem::mutex = 0; @@ -56,30 +61,76 @@ QMutex *QWaylandSurfaceItem::mutex = 0; class QWaylandSurfaceTextureProvider : public QSGTextureProvider { public: - QWaylandSurfaceTextureProvider() : t(0) { } + QWaylandSurfaceTextureProvider() + : m_smooth(false) + , m_sgTex(0) + { + } + + ~QWaylandSurfaceTextureProvider() + { + if (m_sgTex) + m_sgTex->deleteLater(); + } + + void setBufferRef(QWaylandSurfaceItem *surfaceItem, const QWaylandBufferRef &buffer) + { + Q_ASSERT(QThread::currentThread() == thread()); + m_ref = buffer; + delete m_sgTex; + m_sgTex = 0; + if (m_ref.hasBuffer()) { + if (buffer.isShm()) { + m_sgTex = surfaceItem->window()->createTextureFromImage(buffer.image()); + m_invertY = false; + if (m_sgTex) { + m_sgTex->bind(); + } + } else { + QQuickWindow::CreateTextureOptions opt = QQuickWindow::TextureOwnsGLTexture; + if (surfaceItem->surface()->useTextureAlpha()) { + opt |= QQuickWindow::TextureHasAlphaChannel; + } + + GLuint texture; + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + buffer.bindToTexture(); + m_sgTex = surfaceItem->window()->createTextureFromId(texture , QSize(surfaceItem->width(), surfaceItem->height()), opt); + m_invertY = buffer.origin() == QWaylandSurface::OriginBottomLeft; + } + } + emit textureChanged(); + } QSGTexture *texture() const Q_DECL_OVERRIDE { - if (t) - t->setFiltering(smooth ? QSGTexture::Linear : QSGTexture::Nearest); - return t; + if (m_sgTex) + m_sgTex->setFiltering(m_smooth ? QSGTexture::Linear : QSGTexture::Nearest); + return m_sgTex; } - bool smooth; - QSGTexture *t; + void setSmooth(bool smooth) { m_smooth = smooth; } + bool invertY() const { return m_invertY; } +private: + bool m_smooth; + bool m_invertY; + QSGTexture *m_sgTex; + QWaylandBufferRef m_ref; }; QWaylandSurfaceItem::QWaylandSurfaceItem(QQuickItem *parent) : QQuickItem(parent) , QWaylandSurfaceView() - , m_provider(0) + , m_provider(Q_NULLPTR) , m_paintEnabled(true) , m_touchEventsEnabled(false) - , m_yInverted(false) , m_resizeSurfaceToItem(false) - , m_newTexture(false) , m_followRequestedPos(true) , m_inputEventsEnabled(true) + , m_newTexture(false) + , m_connectedWindow(Q_NULLPTR) + , m_origin(QWaylandSurface::OriginTopLeft) { setAcceptHoverEvents(true); if (!mutex) @@ -98,11 +149,7 @@ QWaylandSurfaceItem::QWaylandSurfaceItem(QQuickItem *parent) Qt::ExtraButton12 | Qt::ExtraButton13); setAcceptHoverEvents(true); - connect(this, &QWaylandSurfaceItem::widthChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); - connect(this, &QWaylandSurfaceItem::heightChanged, this, &QWaylandSurfaceItem::updateSurfaceSize); - - - emit yInvertedChanged(); + connect(this, &QQuickItem::windowChanged, this, &QWaylandSurfaceItem::updateWindow); } QWaylandSurfaceItem::~QWaylandSurfaceItem() @@ -122,15 +169,13 @@ void QWaylandSurfaceItem::setSurface(QWaylandQuickSurface *surface) QWaylandSurfaceView::setSurface(surface); } -bool QWaylandSurfaceItem::isYInverted() const +QWaylandSurface::Origin QWaylandSurfaceItem::origin() const { - return m_yInverted; + return m_origin; } QSGTextureProvider *QWaylandSurfaceItem::textureProvider() const { - if (!m_provider) - m_provider = new QWaylandSurfaceTextureProvider(); return m_provider; } @@ -291,7 +336,7 @@ void QWaylandSurfaceItem::waylandSurfaceChanged(QWaylandSurface *newSurface, QWa if (oldSurface) { disconnect(oldSurface, &QWaylandSurface::mapped, this, &QWaylandSurfaceItem::surfaceMapped); disconnect(oldSurface, &QWaylandSurface::unmapped, this, &QWaylandSurfaceItem::surfaceUnmapped); - disconnect(oldSurface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); + disconnect(oldSurface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::handleSurfaceDestroyed); disconnect(oldSurface, &QWaylandSurface::parentChanged, this, &QWaylandSurfaceItem::parentChanged); disconnect(oldSurface, &QWaylandSurface::sizeChanged, this, &QWaylandSurfaceItem::updateSize); disconnect(oldSurface, &QWaylandSurface::configure, this, &QWaylandSurfaceItem::updateBuffer); @@ -300,16 +345,16 @@ void QWaylandSurfaceItem::waylandSurfaceChanged(QWaylandSurface *newSurface, QWa if (newSurface) { connect(newSurface, &QWaylandSurface::mapped, this, &QWaylandSurfaceItem::surfaceMapped); connect(newSurface, &QWaylandSurface::unmapped, this, &QWaylandSurfaceItem::surfaceUnmapped); - connect(newSurface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::surfaceDestroyed); + connect(newSurface, &QWaylandSurface::surfaceDestroyed, this, &QWaylandSurfaceItem::handleSurfaceDestroyed); connect(newSurface, &QWaylandSurface::parentChanged, this, &QWaylandSurfaceItem::parentChanged); connect(newSurface, &QWaylandSurface::sizeChanged, this, &QWaylandSurfaceItem::updateSize); connect(newSurface, &QWaylandSurface::configure, this, &QWaylandSurfaceItem::updateBuffer); connect(newSurface, &QWaylandSurface::redraw, this, &QQuickItem::update); setWidth(surface()->size().width()); setHeight(surface()->size().height()); - if (newSurface->isYInverted() != m_yInverted) { - m_yInverted = newSurface->isYInverted(); - emit yInvertedChanged(); + if (newSurface->origin() != m_origin) { + m_origin = newSurface->origin(); + emit originChanged(); } } @@ -359,10 +404,13 @@ void QWaylandSurfaceItem::updateSize() } } -void QWaylandSurfaceItem::updateSurfaceSize() +void QWaylandSurfaceItem::geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) { + QQuickItem::geometryChanged(newGeometry, oldGeometry); + if (surface() && m_resizeSurfaceToItem) { - surface()->requestSize(QSize(width(), height())); + surface()->requestSize(newGeometry.size().toSize()); } } @@ -422,6 +470,11 @@ void QWaylandSurfaceItem::setRequestedYPosition(qreal yPos) setRequestedPosition(reqPos); } +void QWaylandSurfaceItem::syncGraphicsState() +{ + +} + /*! \qmlproperty bool QtWayland::QWaylandSurfaceItem::paintEnabled @@ -443,38 +496,39 @@ void QWaylandSurfaceItem::setPaintEnabled(bool enabled) void QWaylandSurfaceItem::updateBuffer(bool hasBuffer) { - Q_UNUSED(hasBuffer) - - bool inv = m_yInverted; - m_yInverted = surface()->isYInverted(); - if (inv != m_yInverted) - emit yInvertedChanged(); - - m_newTexture = true; + Q_UNUSED(hasBuffer); + if (m_origin != surface()->origin()) { + m_origin = surface()->origin(); + emit originChanged(); + } } -void QWaylandSurfaceItem::updateTexture() +void QWaylandSurfaceItem::updateWindow() { - updateTexture(false); + if (m_connectedWindow) { + disconnect(m_connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandSurfaceItem::beforeSync); + } + + m_connectedWindow = window(); + + if (m_connectedWindow) { + connect(m_connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandSurfaceItem::beforeSync, Qt::DirectConnection); + } } -void QWaylandSurfaceItem::updateTexture(bool changed) +void QWaylandSurfaceItem::beforeSync() { - if (!m_provider) - m_provider = new QWaylandSurfaceTextureProvider(); - - m_provider->t = static_cast<QWaylandQuickSurface *>(surface())->texture(); - m_provider->smooth = smooth(); - if (m_newTexture || changed) - emit m_provider->textureChanged(); - m_newTexture = false; + if (advance()) { + m_newTexture = true; + update(); + } } QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *) { - bool mapped = surface() && surface()->isMapped(); + bool mapped = surface() && surface()->isMapped() && currentBuffer().hasBuffer(); - if (!mapped || !m_provider || !m_provider->t || !m_paintEnabled) { + if (!mapped || !m_paintEnabled) { delete oldNode; return 0; } @@ -483,14 +537,21 @@ QSGNode *QWaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeD if (!node) node = new QSGSimpleTextureNode(); - node->setTexture(m_provider->t); - // Surface textures come by default with the OpenGL coordinate system, which is inverted relative - // to the QtQuick one. So we're dealing with a double invertion here, and if isYInverted() returns - // true it means it is NOT inverted relative to QtQuick, while if it returns false it means it IS. - if (surface()->isYInverted()) { - node->setRect(0, 0, width(), height()); + + if (!m_provider) + m_provider = new QWaylandSurfaceTextureProvider(); + + if (m_newTexture) { + m_provider->setBufferRef(this, currentBuffer()); + node->setTexture(m_provider->texture()); + } + + m_provider->setSmooth(smooth()); + + if (m_provider->invertY()) { + node->setRect(0, height(), width(), -height()); } else { - node->setRect(0, height(), width(), -height()); + node->setRect(0, 0, width(), height()); } return node; @@ -521,4 +582,10 @@ void QWaylandSurfaceItem::setInputEventsEnabled(bool enabled) } } +void QWaylandSurfaceItem::handleSurfaceDestroyed() +{ + emit surfaceDestroyed(); + setSurface(Q_NULLPTR); +} + QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceitem.h b/src/compositor/compositor_api/qwaylandsurfaceitem.h index 6711d8ef2..4c5db4ad5 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceitem.h +++ b/src/compositor/compositor_api/qwaylandsurfaceitem.h @@ -61,7 +61,7 @@ class Q_COMPOSITOR_EXPORT QWaylandSurfaceItem : public QQuickItem, public QWayla Q_PROPERTY(QWaylandQuickSurface* surface READ surface WRITE setSurface NOTIFY surfaceChanged) Q_PROPERTY(bool paintEnabled READ paintEnabled WRITE setPaintEnabled) Q_PROPERTY(bool touchEventsEnabled READ touchEventsEnabled WRITE setTouchEventsEnabled NOTIFY touchEventsEnabledChanged) - Q_PROPERTY(bool isYInverted READ isYInverted NOTIFY yInvertedChanged) + Q_PROPERTY(QWaylandSurface::Origin origin READ origin NOTIFY originChanged); Q_PROPERTY(bool resizeSurfaceToItem READ resizeSurfaceToItem WRITE setResizeSurfaceToItem NOTIFY resizeSurfaceToItemChanged) Q_PROPERTY(bool followRequestedPosition READ followRequestedPosition WRITE setFollowRequestedPosition NOTIFY followRequestedPositionChanged) Q_PROPERTY(qreal requestedXPosition READ requestedXPosition WRITE setRequestedXPosition NOTIFY requestedXPositionChanged) @@ -75,7 +75,7 @@ public: QWaylandQuickSurface *surface() const; void setSurface(QWaylandQuickSurface *surface); - bool isYInverted() const; + QWaylandSurface::Origin origin() const; bool isTextureProvider() const { return true; } QSGTextureProvider *textureProvider() const; @@ -83,7 +83,6 @@ public: bool paintEnabled() const; bool touchEventsEnabled() const { return m_touchEventsEnabled; } bool resizeSurfaceToItem() const { return m_resizeSurfaceToItem; } - void updateTexture(); void setTouchEventsEnabled(bool enabled); void setResizeSurfaceToItem(bool enabled); @@ -101,6 +100,9 @@ public: qreal requestedYPosition() const; void setRequestedYPosition(qreal yPos); + Q_INVOKABLE void syncGraphicsState(); + + void markForNewBuffer(); protected: void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); @@ -117,6 +119,8 @@ protected: void waylandSurfaceChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) Q_DECL_OVERRIDE; + void geometryChanged(const QRectF &newGeometry, + const QRectF &oldGeometry) Q_DECL_OVERRIDE; public Q_SLOTS: virtual void takeFocus(QWaylandInputDevice *device = 0); void setPaintEnabled(bool paintEnabled); @@ -126,13 +130,14 @@ private Q_SLOTS: void surfaceUnmapped(); void parentChanged(QWaylandSurface *newParent, QWaylandSurface *oldParent); void updateSize(); - void updateSurfaceSize(); void updateBuffer(bool hasBuffer); + void updateWindow(); + void beforeSync(); Q_SIGNALS: void surfaceChanged(); void touchEventsEnabledChanged(); - void yInvertedChanged(); + void originChanged(); void resizeSurfaceToItemChanged(); void surfaceDestroyed(); void followRequestedPositionChanged(); @@ -146,20 +151,21 @@ protected: private: friend class QWaylandSurfaceNode; friend class QWaylandQuickSurface; - void init(QWaylandQuickSurface *); - void updateTexture(bool changed); bool shouldSendInputEvents() const { return surface() && m_inputEventsEnabled; } + void handleSurfaceDestroyed(); static QMutex *mutex; mutable QWaylandSurfaceTextureProvider *m_provider; bool m_paintEnabled; bool m_touchEventsEnabled; - bool m_yInverted; bool m_resizeSurfaceToItem; - bool m_newTexture; bool m_followRequestedPos; bool m_inputEventsEnabled; + bool m_newTexture; + + QQuickWindow *m_connectedWindow; + QWaylandSurface::Origin m_origin; }; QT_END_NAMESPACE diff --git a/src/compositor/compositor_api/qwaylandsurfaceview.cpp b/src/compositor/compositor_api/qwaylandsurfaceview.cpp index 88bd61fea..b8f7c0d1a 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceview.cpp +++ b/src/compositor/compositor_api/qwaylandsurfaceview.cpp @@ -40,6 +40,8 @@ #include "qwaylandcompositor.h" #include "qwaylandinput.h" +#include <QtCore/QMutex> + QT_BEGIN_NAMESPACE class QWaylandSurfaceViewPrivate @@ -50,6 +52,9 @@ public: { } QWaylandSurface *surface; QPointF requestedPos; + QMutex bufferMutex; + QWaylandBufferRef currentBuffer; + QWaylandBufferRef nextBuffer; }; QWaylandSurfaceView::QWaylandSurfaceView() @@ -89,6 +94,8 @@ void QWaylandSurfaceView::setSurface(QWaylandSurface *newSurface) QWaylandSurfacePrivate::get(newSurface)->refView(this); waylandSurfaceChanged(newSurface, oldSurface); + d->currentBuffer = QWaylandBufferRef(); + d->nextBuffer = QWaylandBufferRef(); } QWaylandCompositor *QWaylandSurfaceView::compositor() const @@ -111,6 +118,28 @@ QPointF QWaylandSurfaceView::pos() const return d->requestedPos; } +void QWaylandSurfaceView::attach(const QWaylandBufferRef &ref) +{ + QMutexLocker locker(&d->bufferMutex); + d->nextBuffer = ref; +} + +bool QWaylandSurfaceView::advance() +{ + QMutexLocker locker(&d->bufferMutex); + if (d->currentBuffer == d->nextBuffer) + return false; + + d->currentBuffer = d->nextBuffer; + return true; +} + +QWaylandBufferRef QWaylandSurfaceView::currentBuffer() +{ + QMutexLocker locker(&d->bufferMutex); + return d->currentBuffer; +} + void QWaylandSurfaceView::waylandSurfaceChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface) { Q_UNUSED(newSurface); diff --git a/src/compositor/compositor_api/qwaylandsurfaceview.h b/src/compositor/compositor_api/qwaylandsurfaceview.h index 1685abfbb..c6bd288aa 100644 --- a/src/compositor/compositor_api/qwaylandsurfaceview.h +++ b/src/compositor/compositor_api/qwaylandsurfaceview.h @@ -39,6 +39,7 @@ #include <QPointF> +#include <QtCompositor/QWaylandBufferRef> #include <QtCompositor/qwaylandexport.h> QT_BEGIN_NAMESPACE @@ -61,6 +62,9 @@ public: virtual QPointF requestedPosition() const; virtual QPointF pos() const; + virtual void attach(const QWaylandBufferRef &ref); + virtual bool advance(); + virtual QWaylandBufferRef currentBuffer(); protected: virtual void waylandSurfaceChanged(QWaylandSurface *newSurface, QWaylandSurface *oldSurface); diff --git a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h index f03d5ad2c..9d684553a 100644 --- a/src/compositor/hardware_integration/qwlclientbufferintegration_p.h +++ b/src/compositor/hardware_integration/qwlclientbufferintegration_p.h @@ -38,6 +38,7 @@ #define QWAYLANDCLIENTBUFFERINTEGRATION_H #include <QtCompositor/qwaylandexport.h> +#include <QtCompositor/qwaylandsurface.h> #include <QtCore/QSize> #include <QtGui/qopengl.h> #include <QtGui/QOpenGLContext> @@ -68,7 +69,7 @@ public: // Called with the texture bound. virtual void bindTextureToBuffer(struct ::wl_resource *buffer) = 0; - virtual bool isYInverted(struct ::wl_resource *) const { return true; } + virtual QWaylandSurface::Origin origin(struct ::wl_resource *) const { return QWaylandSurface::OriginBottomLeft; } virtual void *lockNativeBuffer(struct ::wl_resource *) const { return 0; } virtual void unlockNativeBuffer(void *) const { return; } diff --git a/src/compositor/wayland_wrapper/qwlsurface.cpp b/src/compositor/wayland_wrapper/qwlsurface.cpp index 8f94f97cc..9ac0293ab 100644 --- a/src/compositor/wayland_wrapper/qwlsurface.cpp +++ b/src/compositor/wayland_wrapper/qwlsurface.cpp @@ -47,6 +47,8 @@ #include "qwaylandsurfaceview.h" #include "qwaylandoutput.h" +#include "qwaylandsurface_p.h" + #include <QtCore/QDebug> #include <QTouchEvent> #include <QGuiApplication> @@ -114,7 +116,6 @@ Surface::Surface(struct wl_client *client, uint32_t id, int version, QWaylandCom , m_mainOutput(0) , m_buffer(0) , m_surfaceMapped(false) - , m_attacher(0) , m_shellSurface(0) , m_extendedSurface(0) , m_subSurface(0) @@ -173,25 +174,6 @@ Surface *Surface::fromResource(struct ::wl_resource *resource) return static_cast<Surface *>(Resource::fromResource(resource)->surface_object); } -QWaylandSurface::Type Surface::type() const -{ - if (m_buffer && m_buffer->waylandBufferHandle()) { - if (m_buffer->isShmBuffer()) { - return QWaylandSurface::Shm; - } else { - return QWaylandSurface::Texture; - } - } - return QWaylandSurface::Invalid; -} - -bool Surface::isYInverted() const -{ - if (m_buffer) - return m_buffer->isYInverted(); - return false; -} - bool Surface::mapped() const { return !m_unmapLocks.isEmpty() || (m_buffer && bool(m_buffer->waylandBufferHandle())); @@ -379,9 +361,10 @@ void Surface::removeFromOutput() * The backbuffer represents the current state of the surface for the * purpose of GUI-thread accessible properties such as size and visibility. */ -void Surface::setBackBuffer(SurfaceBuffer *buffer) +void Surface::setBackBuffer(SurfaceBuffer *buffer, const QRegion &damage) { m_buffer = buffer; + m_bufferRef = QWaylandBufferRef(m_buffer); if (m_buffer) { bool valid = m_buffer->waylandBufferHandle() != 0; @@ -393,7 +376,16 @@ void Surface::setBackBuffer(SurfaceBuffer *buffer) } else { m_compositor->resetInputDevice(this); } - m_damage = QRegion(); + m_damage = damage; + + QWaylandSurfacePrivate *priv = QWaylandSurfacePrivate::get(waylandSurface()); + for (int i = 0; i < priv->views.size(); i++) { + priv->views.at(i)->attach(m_bufferRef); + } + + emit m_waylandSurface->configure(m_bufferRef.hasBuffer()); + if (!m_pending.offset.isNull()) + emit m_waylandSurface->offsetForNextFrame(m_pending.offset); } void Surface::setMapped(bool mapped) @@ -502,26 +494,8 @@ void Surface::surface_set_input_region(Resource *, struct wl_resource *region) void Surface::surface_commit(Resource *) { - m_damage = m_pending.damage; - if (m_pending.buffer || m_pending.newlyAttached) { - setBackBuffer(m_pending.buffer); - m_bufferRef = QWaylandBufferRef(m_buffer); - - if (m_attacher) { - if (m_bufferRef) { - m_attacher->attach(m_bufferRef); - } else if (!mapped()) { - setSize(QSize()); - m_attacher->unmap(); - } - } - emit m_waylandSurface->configure(m_bufferRef); - if (m_roleHandler) - m_roleHandler->configure(m_pending.offset.x(), m_pending.offset.y()); - - if (!m_pending.offset.isNull()) - emit m_waylandSurface->offsetForNextFrame(m_pending.offset); + setBackBuffer(m_pending.buffer, m_pending.damage); } m_pending.buffer = 0; diff --git a/src/compositor/wayland_wrapper/qwlsurface_p.h b/src/compositor/wayland_wrapper/qwlsurface_p.h index 127ff3576..2ba1b1428 100644 --- a/src/compositor/wayland_wrapper/qwlsurface_p.h +++ b/src/compositor/wayland_wrapper/qwlsurface_p.h @@ -89,9 +89,6 @@ public: static Surface *fromResource(struct ::wl_resource *resource); - QWaylandSurface::Type type() const; - bool isYInverted() const; - bool mapped() const; using QtWaylandServer::wl_surface::resource; @@ -161,6 +158,9 @@ public: Qt::ScreenOrientation contentOrientation() const; + QWaylandSurface::Origin origin() const { return m_buffer ? m_buffer->origin() : QWaylandSurface::OriginTopLeft; } + + QWaylandBufferRef currentBufferRef() const { return m_bufferRef; } protected: void surface_destroy_resource(Resource *resource) Q_DECL_OVERRIDE; @@ -189,7 +189,6 @@ protected: SurfaceBuffer *m_buffer; QWaylandBufferRef m_bufferRef; bool m_surfaceMapped; - QWaylandBufferAttacher *m_attacher; QVector<QWaylandUnmapLock *> m_unmapLocks; struct { @@ -230,10 +229,9 @@ protected: const SurfaceRole *m_role; RoleBase *m_roleHandler; - void setBackBuffer(SurfaceBuffer *buffer); - SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); + void setBackBuffer(SurfaceBuffer *buffer, const QRegion &damage); - QList<QWaylandSurfaceView *> views; + SurfaceBuffer *createSurfaceBuffer(struct ::wl_resource *buffer); friend class QWaylandSurface; friend class RoleBase; diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp index cbb2fb0f3..225b49f4f 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer.cpp @@ -62,14 +62,8 @@ SurfaceBuffer::SurfaceBuffer(Surface *surface) , m_surface_has_buffer(false) , m_destroyed(false) , m_is_displayed(false) - , m_texture(0) - , m_is_shm_resolved(false) - , m_shmBuffer(0) - , m_isSizeResolved(false) - , m_size() , m_used(false) , m_destroyIfUnused(false) - , m_image(0) { } @@ -82,17 +76,11 @@ SurfaceBuffer::~SurfaceBuffer() void SurfaceBuffer::initialize(struct ::wl_resource *buffer) { m_buffer = buffer; - m_texture = 0; m_committed = false; m_is_registered_for_buffer = true; m_surface_has_buffer = true; m_is_displayed = false; m_destroyed = false; - m_handle = 0; - m_is_shm_resolved = false; - m_shmBuffer = 0; - m_isSizeResolved = false; - m_size = QSize(); m_destroy_listener.surfaceBuffer = this; m_destroy_listener.listener.notify = destroy_listener_callback; if (buffer) @@ -101,58 +89,14 @@ void SurfaceBuffer::initialize(struct ::wl_resource *buffer) void SurfaceBuffer::destructBufferState() { - destroyTexture(); if (m_buffer) { sendRelease(); - - if (m_handle) { - if (m_shmBuffer) { - delete static_cast<QImage *>(m_handle); -#ifdef QT_COMPOSITOR_WAYLAND_GL - } else { - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - hwIntegration->unlockNativeBuffer(m_handle); -#endif - } - } wl_list_remove(&m_destroy_listener.listener.link); } m_buffer = 0; - m_handle = 0; m_committed = false; m_is_registered_for_buffer = false; m_is_displayed = false; - m_image = QImage(); -} - -QSize SurfaceBuffer::size() const -{ - if (!m_isSizeResolved) { - if (isShmBuffer()) { - m_size = QSize(wl_shm_buffer_get_width(m_shmBuffer), wl_shm_buffer_get_height(m_shmBuffer)); -#ifdef QT_COMPOSITOR_WAYLAND_GL - } else { - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - m_size = hwIntegration->bufferSize(m_buffer); -#endif - } - } - - return m_size; -} - -bool SurfaceBuffer::isShmBuffer() const -{ - if (!m_is_shm_resolved) { -#if (WAYLAND_VERSION_MAJOR >= 1) && (WAYLAND_VERSION_MINOR >= 2) - m_shmBuffer = wl_shm_buffer_get(m_buffer); -#else - if (wl_buffer_is_shm(static_cast<struct ::wl_buffer*>(m_buffer->data))) - m_shmBuffer = static_cast<struct ::wl_buffer*>(m_buffer->data); -#endif - m_is_shm_resolved = true; - } - return m_shmBuffer != 0; } void SurfaceBuffer::sendRelease() @@ -173,74 +117,6 @@ void SurfaceBuffer::setDisplayed() m_is_displayed = true; } -void SurfaceBuffer::destroyTexture() -{ -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (m_texture) { - Q_ASSERT(QOpenGLContext::currentContext()); - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); - if (hwIntegration->textureForBuffer(m_buffer) == 0) - glDeleteTextures(1, &m_texture); - else - hwIntegration->destroyTextureForBuffer(m_buffer); - m_texture = 0; - } -#endif -} - -void SurfaceBuffer::handleAboutToBeDisplayed() -{ - qDebug() << Q_FUNC_INFO; -} - -void SurfaceBuffer::handleDisplayed() -{ - qDebug() << Q_FUNC_INFO; -} - -void *SurfaceBuffer::handle() const -{ - if (!m_buffer) - return 0; - - if (!m_handle) { - SurfaceBuffer *that = const_cast<SurfaceBuffer *>(this); - if (isShmBuffer()) { - const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_shmBuffer)); - int stride = wl_shm_buffer_get_stride(m_shmBuffer); - int width = wl_shm_buffer_get_width(m_shmBuffer); - int height = wl_shm_buffer_get_height(m_shmBuffer); - QImage *image = new QImage(data,width,height,stride, QImage::Format_ARGB32_Premultiplied); - that->m_handle = image; -#ifdef QT_COMPOSITOR_WAYLAND_GL - } else { - ClientBufferIntegration *clientBufferIntegration = m_compositor->clientBufferIntegration(); - that->m_handle = clientBufferIntegration->lockNativeBuffer(m_buffer); -#endif - } - } - return m_handle; -} - -QImage SurfaceBuffer::image() -{ - /* This api may be available on non-shm buffer. But be sure about it's format. */ - if (!m_buffer || !isShmBuffer()) - return QImage(); - - if (m_image.isNull()) - { - const uchar *data = static_cast<const uchar *>(wl_shm_buffer_get_data(m_shmBuffer)); - int stride = wl_shm_buffer_get_stride(m_shmBuffer); - int width = wl_shm_buffer_get_width(m_shmBuffer); - int height = wl_shm_buffer_get_height(m_shmBuffer); - QImage::Format format = QWaylandShmFormatHelper::fromWaylandShmFormat(wl_shm_format(wl_shm_buffer_get_format(m_shmBuffer))); - m_image = QImage(data, width, height, stride, format); - } - - return m_image; -} - void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data) { Q_UNUSED(data); @@ -254,39 +130,6 @@ void SurfaceBuffer::destroy_listener_callback(wl_listener *listener, void *data) d->m_buffer = 0; } -void SurfaceBuffer::createTexture() -{ - destroyTexture(); - - ClientBufferIntegration *hwIntegration = m_compositor->clientBufferIntegration(); -#ifdef QT_COMPOSITOR_WAYLAND_GL - if (!m_texture) - m_texture = hwIntegration->textureForBuffer(m_buffer); - if (!m_texture) - glGenTextures(1, &m_texture); - glBindTexture(GL_TEXTURE_2D, m_texture); - hwIntegration->bindTextureToBuffer(m_buffer); -#else - Q_UNUSED(hwIntegration); -#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; -} - void SurfaceBuffer::ref() { m_used = m_refCount.ref(); @@ -311,6 +154,68 @@ void SurfaceBuffer::destroyIfUnused() delete this; } +QSize SurfaceBuffer::size() const +{ + if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { + int width = wl_shm_buffer_get_width(shmBuffer); + int height = wl_shm_buffer_get_height(shmBuffer); + return QSize(width, height); + } + if (ClientBufferIntegration *integration = m_compositor->clientBufferIntegration()) { + return integration->bufferSize(m_buffer); + } + + return QSize(); +} + +QWaylandSurface::Origin SurfaceBuffer::origin() const +{ + if (isShm()) { + return QWaylandSurface::OriginTopLeft; + } + + if (ClientBufferIntegration *integration = m_compositor->clientBufferIntegration()) { + return integration->origin(m_buffer); + } + return QWaylandSurface::OriginTopLeft; +} + +QImage SurfaceBuffer::image() const +{ + if (wl_shm_buffer *shmBuffer = wl_shm_buffer_get(m_buffer)) { + int width = wl_shm_buffer_get_width(shmBuffer); + int height = wl_shm_buffer_get_height(shmBuffer); + int bytesPerLine = wl_shm_buffer_get_stride(shmBuffer); + uchar *data = static_cast<uchar *>(wl_shm_buffer_get_data(shmBuffer)); + return QImage(data, width, height, bytesPerLine, QImage::Format_ARGB32_Premultiplied); + } + + return QImage(); +} + +void SurfaceBuffer::bindToTexture() const +{ + Q_ASSERT(m_compositor); + if (isShm()) { + QImage image = this->image(); + if (image.hasAlphaChannel()) { + if (image.format() != QImage::Format_RGBA8888) { + image = image.convertToFormat(QImage::Format_RGBA8888); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image.width(), image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); + } else { + if (image.format() != QImage::Format_RGBX8888) { + image = image.convertToFormat(QImage::Format_RGBX8888); + } + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.width(), image.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, image.constBits()); + } + } else { + if (QtWayland::ClientBufferIntegration *clientInt = m_compositor->clientBufferIntegration()) { + clientInt->bindTextureToBuffer(m_buffer); + } + } +} + } QT_END_NAMESPACE diff --git a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h index 7003e9360..8eecfa73f 100644 --- a/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h +++ b/src/compositor/wayland_wrapper/qwlsurfacebuffer_p.h @@ -42,6 +42,8 @@ #include <QImage> #include <QAtomicInt> +#include <QtCompositor/QWaylandSurface> + #include <wayland-server.h> QT_BEGIN_NAMESPACE @@ -70,11 +72,6 @@ public: void initialize(struct ::wl_resource *bufferResource); void destructBufferState(); - QSize size() const; - - bool isShmBuffer() const; - bool isYInverted() const; - inline bool isRegisteredWithBuffer() const { return m_is_registered_for_buffer; } void sendRelease(); @@ -86,29 +83,19 @@ public: inline void setCommitted() { m_committed = true; } inline bool isDisplayed() const { return m_is_displayed; } - inline bool textureCreated() const { return m_texture; } - bool isDestroyed() { return m_destroyed; } - void createTexture(); -#ifdef QT_COMPOSITOR_WAYLAND_GL - inline GLuint texture() const; -#else - inline uint texture() const; -#endif - - void destroyTexture(); - inline struct ::wl_resource *waylandBufferHandle() const { return m_buffer; } - void handleAboutToBeDisplayed(); - void handleDisplayed(); - - void bufferWasDestroyed(); void setDestroyIfUnused(bool destroy); - void *handle() const; - QImage image(); + QSize size() const; + QWaylandSurface::Origin origin() const; + bool isShm() const { return wl_shm_buffer_get(m_buffer); } + + QImage image() const; + void bindToTexture() const; + private: void ref(); void deref(); @@ -124,47 +111,16 @@ private: bool m_destroyed; bool m_is_displayed; -#ifdef QT_COMPOSITOR_WAYLAND_GL - GLuint m_texture; -#else - uint m_texture; -#endif - void *m_handle; - mutable bool m_is_shm_resolved; - -#if (WAYLAND_VERSION_MAJOR >= 1) && (WAYLAND_VERSION_MINOR >= 2) - mutable struct ::wl_shm_buffer *m_shmBuffer; -#else - mutable struct ::wl_buffer *m_shmBuffer; -#endif - - mutable bool m_isSizeResolved; - mutable QSize m_size; + QAtomicInt m_refCount; bool m_used; bool m_destroyIfUnused; - QImage m_image; - static void destroy_listener_callback(wl_listener *listener, void *data); friend class ::QWaylandBufferRef; }; -#ifdef QT_COMPOSITOR_WAYLAND_GL -GLuint SurfaceBuffer::texture() const -{ - if (m_buffer) - return m_texture; - return 0; -} -#else -uint SurfaceBuffer::texture() const -{ - return 0; -} -#endif - } QT_END_NAMESPACE diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp index 0453a31b7..d22b2db04 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.cpp @@ -190,7 +190,7 @@ void WaylandEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resource d->egl_destroy_image(d->egl_display, image); } -bool WaylandEglClientBufferIntegration::isYInverted(struct ::wl_resource *buffer) const +QWaylandSurface::Origin WaylandEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const { #if defined(EGL_WAYLAND_Y_INVERTED_WL) Q_D(const WaylandEglClientBufferIntegration); @@ -203,11 +203,11 @@ bool WaylandEglClientBufferIntegration::isYInverted(struct ::wl_resource *buffer // value (not supported) should be treated the same as EGL_TRUE return value // and EGL_TRUE in value. if (ret == EGL_FALSE || isYInverted == EGL_TRUE) - return true; - return false; + return QWaylandSurface::OriginTopLeft; + return QWaylandSurface::OriginBottomLeft; #endif - return QtWayland::ClientBufferIntegration::isYInverted(buffer); + return QtWayland::ClientBufferIntegration::origin(buffer); } diff --git a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h index 66b827caa..874d960f5 100644 --- a/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h +++ b/src/hardwareintegration/compositor/wayland-egl/waylandeglclientbufferintegration.h @@ -53,7 +53,7 @@ public: void initializeHardware(QtWayland::Display *waylandDisplay) Q_DECL_OVERRIDE; void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - bool isYInverted(struct ::wl_resource *) const Q_DECL_OVERRIDE; + QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE; void *lockNativeBuffer(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; void unlockNativeBuffer(void *native_buffer) const Q_DECL_OVERRIDE; diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp index 0c46172b7..0d909dcf6 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.cpp @@ -115,7 +115,7 @@ void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resou qDebug() << "Failed to create eglsurface" << pixmap << compositorBuffer->window(); } - compositorBuffer->setInvertedY(true); + compositorBuffer->setOrigin(QWaylandSurface::OriginTopLeft); if (!eglBindTexImage(mEglDisplay,surface,EGL_BACK_BUFFER)) { qDebug() << "Failed to bind"; @@ -124,10 +124,10 @@ void XCompositeEglClientBufferIntegration::bindTextureToBuffer(struct ::wl_resou // eglDestroySurface(mEglDisplay,surface); } -bool XCompositeEglClientBufferIntegration::isYInverted(struct ::wl_resource *buffer) const +QWaylandSurface::Origin XCompositeEglClientBufferIntegration::origin(struct ::wl_resource *buffer) const { XCompositeBuffer *compositorBuffer = XCompositeBuffer::fromResource(buffer); - return compositorBuffer->isYInverted(); + return compositorBuffer->origin(); } QSize XCompositeEglClientBufferIntegration::bufferSize(struct ::wl_resource *buffer) const diff --git a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h index a976963d2..27d99eb28 100644 --- a/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h +++ b/src/hardwareintegration/compositor/xcomposite-egl/xcompositeeglintegration.h @@ -53,7 +53,7 @@ public: void initializeHardware(QtWayland::Display *waylandDisplay) Q_DECL_OVERRIDE; void bindTextureToBuffer(struct ::wl_resource *buffer) Q_DECL_OVERRIDE; - bool isYInverted(struct ::wl_resource *) const Q_DECL_OVERRIDE; + QWaylandSurface::Origin origin(struct ::wl_resource *) const Q_DECL_OVERRIDE; QSize bufferSize(struct ::wl_resource *buffer) const Q_DECL_OVERRIDE; diff --git a/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp b/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp index 58f333f6a..a14b8f136 100644 --- a/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp +++ b/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.cpp @@ -42,7 +42,7 @@ XCompositeBuffer::XCompositeBuffer(Window window, const QSize &size, struct ::wl_client *client, uint32_t id) : QtWaylandServer::wl_buffer(client, id, 1) , mWindow(window) - , mInvertedY(false) + , mOrigin(QWaylandSurface::OriginBottomLeft) , mSize(size) { } diff --git a/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.h b/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.h index b753c4ccf..e6753e185 100644 --- a/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.h +++ b/src/hardwareintegration/compositor/xcomposite_share/xcompositebuffer.h @@ -39,6 +39,7 @@ #include <private/qwlcompositor_p.h> #include <qwayland-server-wayland.h> +#include <QtCompositor/QWaylandSurface> #include <QtCore/QSize> @@ -59,8 +60,8 @@ public: Window window(); - bool isYInverted() const { return mInvertedY; } - void setInvertedY(bool inverted) { mInvertedY = inverted; } + QWaylandSurface::Origin origin() const { return mOrigin; } + void setOrigin(QWaylandSurface::Origin origin) { mOrigin = origin; } QSize size() const { return mSize; } @@ -72,7 +73,7 @@ protected: private: Window mWindow; - bool mInvertedY; + QWaylandSurface::Origin mOrigin; QSize mSize; }; |