summaryrefslogtreecommitdiffstats
path: root/src/compositor/compositor_api/qwaylandquickitem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/compositor/compositor_api/qwaylandquickitem.cpp')
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp376
1 files changed, 277 insertions, 99 deletions
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 891823c6b..c643598be 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -1,37 +1,12 @@
-/****************************************************************************
-**
-** Copyright (C) 2017 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:GPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3 or (at your option) any later version
-** approved by the KDE Free Qt Foundation. The licenses are as published by
-** the Free Software Foundation and appearing in the file LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
#include "qwaylandquickitem.h"
#include "qwaylandquickitem_p.h"
#include "qwaylandquicksurface.h"
#include "qwaylandinputmethodcontrol.h"
#include "qwaylandtextinput.h"
+#include "qwaylandtextinputv3.h"
#include "qwaylandqttextinputmethod.h"
#include "qwaylandquickoutput.h"
#include <QtWaylandCompositor/qwaylandcompositor.h>
@@ -56,12 +31,17 @@
#include <QtQuick/QQuickWindow>
#include <QtQuick/qsgtexture.h>
+#include <QtCore/QFile>
#include <QtCore/QMutexLocker>
#include <QtCore/QMutex>
#include <wayland-server-core.h>
#include <QThread>
+#if QT_CONFIG(opengl)
+#include <QtGui/private/qshaderdescription_p.h>
+#endif
+
#ifndef GL_TEXTURE_EXTERNAL_OES
#define GL_TEXTURE_EXTERNAL_OES 0x8D65
#endif
@@ -72,75 +52,155 @@ QT_BEGIN_NAMESPACE
static const struct {
const char * const vertexShaderSourceFile;
const char * const fragmentShaderSourceFile;
- GLenum textureTarget;
int planeCount;
bool canProvideTexture;
QSGMaterial::Flags materialFlags;
QSGMaterialType materialType;
} bufferTypes[] = {
// BufferFormatEgl_Null
- { "", "", 0, 0, false, {}, {} },
+ { "", "", 0, false, {}, {} },
- // BufferFormatEgl_RGB
+ // BufferFormatEgl_RGB (GL_TEXTURE_2D)
{
":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
":/qt-project.org/wayland/compositor/shaders/surface_rgbx.frag.qsb",
- GL_TEXTURE_2D, 1, true,
+ 1, true,
QSGMaterial::Blending,
{}
},
- // BufferFormatEgl_RGBA
+ // BufferFormatEgl_RGBA (GL_TEXTURE_2D)
{
":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
":/qt-project.org/wayland/compositor/shaders/surface_rgba.frag.qsb",
- GL_TEXTURE_2D, 1, true,
+ 1, true,
QSGMaterial::Blending,
{}
},
- // BufferFormatEgl_EXTERNAL_OES
+ // BufferFormatEgl_EXTERNAL_OES (GL_TEXTURE_EXTERNAL_OES)
{
":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
- ":/qt-project.org/wayland/compositor/shaders/surface_oes_external.frag.qsb",
- GL_TEXTURE_EXTERNAL_OES, 1, false,
+ ":/qt-project.org/wayland/compositor/shaders/surface_oes_external.frag",
+ 1, false,
QSGMaterial::Blending,
{}
},
- // BufferFormatEgl_Y_U_V
+ // BufferFormatEgl_Y_U_V (GL_TEXTURE_2D)
{
":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
":/qt-project.org/wayland/compositor/shaders/surface_y_u_v.frag.qsb",
- GL_TEXTURE_2D, 3, false,
+ 3, false,
QSGMaterial::Blending,
{}
},
- // BufferFormatEgl_Y_UV
+ // BufferFormatEgl_Y_UV (GL_TEXTURE_2D)
{
":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
":/qt-project.org/wayland/compositor/shaders/surface_y_uv.frag.qsb",
- GL_TEXTURE_2D, 2, false,
+ 2, false,
QSGMaterial::Blending,
{}
},
- // BufferFormatEgl_Y_XUXV
+ // BufferFormatEgl_Y_XUXV (GL_TEXTURE_2D)
{
":/qt-project.org/wayland/compositor/shaders/surface.vert.qsb",
":/qt-project.org/wayland/compositor/shaders/surface_y_xuxv.frag.qsb",
- GL_TEXTURE_2D, 2, false,
+ 2, false,
QSGMaterial::Blending,
{}
}
};
QWaylandBufferMaterialShader::QWaylandBufferMaterialShader(QWaylandBufferRef::BufferFormatEgl format)
- : m_format(format)
{
+ Q_UNUSED(format);
setShaderFileName(VertexStage, QString::fromLatin1(bufferTypes[format].vertexShaderSourceFile));
- setShaderFileName(FragmentStage, QString::fromLatin1(bufferTypes[format].fragmentShaderSourceFile));
+ auto fragmentShaderSourceFile = QString::fromLatin1(bufferTypes[format].fragmentShaderSourceFile);
+
+ if (format == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES)
+ setupExternalOESShader(fragmentShaderSourceFile);
+ else
+ setShaderFileName(FragmentStage, fragmentShaderSourceFile);
+}
+
+void QWaylandBufferMaterialShader::setupExternalOESShader(const QString &shaderFilename)
+{
+#if QT_CONFIG(opengl)
+ QFile shaderFile(shaderFilename);
+ if (!shaderFile.open(QIODevice::ReadOnly)) {
+ qCWarning(qLcWaylandCompositor) << "Cannot find external OES shader file:" << shaderFilename;
+ return;
+ }
+ QByteArray FS = shaderFile.readAll();
+
+ static const char *FS_GLES_PREAMBLE =
+ "#extension GL_OES_EGL_image_external : require\n"
+ "precision highp float;\n";
+ static const char *FS_GL_PREAMBLE =
+ "#version 120\n"
+ "#extension GL_OES_EGL_image_external : require\n";
+ QByteArray fsGLES = FS_GLES_PREAMBLE + FS;
+ QByteArray fsGL = FS_GL_PREAMBLE + FS;
+
+ QShaderDescription desc;
+ QShaderDescriptionPrivate *descData = QShaderDescriptionPrivate::get(&desc);
+
+ QShaderDescription::InOutVariable texCoordInput;
+ texCoordInput.name = "v_texcoord";
+ texCoordInput.type = QShaderDescription::Vec2;
+ texCoordInput.location = 0;
+
+ descData->inVars = { texCoordInput };
+
+ QShaderDescription::InOutVariable fragColorOutput;
+ fragColorOutput.name = "gl_FragColor";
+ fragColorOutput.type = QShaderDescription::Vec4;
+ fragColorOutput.location = 0;
+
+ descData->outVars = { fragColorOutput };
+
+ QShaderDescription::BlockVariable matrixBlockVar;
+ matrixBlockVar.name = "qt_Matrix";
+ matrixBlockVar.type = QShaderDescription::Mat4;
+ matrixBlockVar.offset = 0;
+ matrixBlockVar.size = 64;
+
+ QShaderDescription::BlockVariable opacityBlockVar;
+ opacityBlockVar.name = "qt_Opacity";
+ opacityBlockVar.type = QShaderDescription::Float;
+ opacityBlockVar.offset = 64;
+ opacityBlockVar.size = 4;
+
+ QShaderDescription::UniformBlock ubufStruct;
+ ubufStruct.blockName = "buf";
+ ubufStruct.structName = "ubuf";
+ ubufStruct.size = 64 + 4;
+ ubufStruct.binding = 0;
+ ubufStruct.members = { matrixBlockVar, opacityBlockVar };
+
+ descData->uniformBlocks = { ubufStruct };
+
+ QShaderDescription::InOutVariable samplerTex0;
+ samplerTex0.name = "tex0";
+ samplerTex0.type = QShaderDescription::SamplerExternalOES;
+ samplerTex0.binding = 1;
+
+ descData->combinedImageSamplers = { samplerTex0 };
+
+ QShader shaderPack;
+ shaderPack.setStage(QShader::FragmentStage);
+ shaderPack.setDescription(desc);
+ shaderPack.setShader(QShaderKey(QShader::GlslShader, QShaderVersion(100, QShaderVersion::GlslEs)), QShaderCode(fsGLES));
+ shaderPack.setShader(QShaderKey(QShader::GlslShader, QShaderVersion(120)), QShaderCode(fsGL));
+
+ setShader(FragmentStage, shaderPack);
+#else
+ Q_UNUSED(shaderFilename);
+#endif
}
bool QWaylandBufferMaterialShader::updateUniformData(RenderState &state, QSGMaterial *, QSGMaterial *)
@@ -275,6 +335,35 @@ void QWaylandBufferMaterial::ensureTextures(int count)
m_scenegraphTextures << nullptr;
}
}
+
+void QWaylandBufferMaterial::setBufferRef(QWaylandQuickItem *surfaceItem, const QWaylandBufferRef &ref)
+{
+ m_bufferRef = ref;
+ for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++) {
+ if (auto texture = ref.toOpenGLTexture(plane)) {
+ QQuickWindow::CreateTextureOptions opt;
+ QWaylandQuickSurface *waylandSurface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
+ if (waylandSurface != nullptr && waylandSurface->useTextureAlpha() && !waylandSurface->isOpaque())
+ opt |= QQuickWindow::TextureHasAlphaChannel;
+ QSGTexture *scenegraphTexture;
+ if (ref.bufferFormatEgl() == QWaylandBufferRef::BufferFormatEgl_EXTERNAL_OES) {
+ scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNativeExternalOES(texture->textureId(),
+ surfaceItem->window(),
+ ref.size(),
+ opt);
+ } else {
+ scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(),
+ surfaceItem->window(),
+ ref.size(),
+ opt);
+ }
+ scenegraphTexture->setFiltering(surfaceItem->smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
+ setTextureForPlane(plane, texture, scenegraphTexture);
+ }
+ }
+
+ bind();
+}
#endif // QT_CONFIG(opengl)
QMutex *QWaylandQuickItemPrivate::mutex = nullptr;
@@ -288,8 +377,7 @@ public:
~QWaylandSurfaceTextureProvider() override
{
- if (m_sgTex)
- m_sgTex->deleteLater();
+ delete m_sgTex;
}
void setBufferRef(QWaylandQuickItem *surfaceItem, const QWaylandBufferRef &buffer)
@@ -305,7 +393,7 @@ public:
#if QT_CONFIG(opengl)
QQuickWindow::CreateTextureOptions opt;
QWaylandQuickSurface *surface = qobject_cast<QWaylandQuickSurface *>(surfaceItem->surface());
- if (surface && surface->useTextureAlpha()) {
+ if (surface && surface->useTextureAlpha() && !surface->isOpaque()) {
opt |= QQuickWindow::TextureHasAlphaChannel;
}
@@ -337,6 +425,7 @@ private:
/*!
* \qmltype WaylandQuickItem
+ * \instantiates QWaylandQuickItem
* \inqmlmodule QtWayland.Compositor
* \since 5.8
* \brief Provides a Qt Quick item that represents a WaylandView.
@@ -361,9 +450,8 @@ private:
* Constructs a QWaylandQuickItem with the given \a parent.
*/
QWaylandQuickItem::QWaylandQuickItem(QQuickItem *parent)
- : QQuickItem(*new QWaylandQuickItemPrivate(), parent)
+ : QWaylandQuickItem(*new QWaylandQuickItemPrivate(), parent)
{
- d_func()->init();
}
/*!
@@ -373,6 +461,7 @@ QWaylandQuickItem::QWaylandQuickItem(QWaylandQuickItemPrivate &dd, QQuickItem *p
: QQuickItem(dd, parent)
{
d_func()->init();
+ connect(this, &QQuickItem::activeFocusChanged, this, &QWaylandQuickItem::updateFocus);
}
/*!
@@ -382,13 +471,16 @@ QWaylandQuickItem::~QWaylandQuickItem()
{
Q_D(QWaylandQuickItem);
disconnect(this, &QQuickItem::windowChanged, this, &QWaylandQuickItem::updateWindow);
+ disconnect(this, &QQuickItem::activeFocusChanged, this, &QWaylandQuickItem::updateFocus);
QMutexLocker locker(d->mutex);
- if (d->provider)
+ if (d->provider) {
+ disconnect(d->texProviderConnection);
d->provider->deleteLater();
+ }
}
/*!
- * \qmlproperty WaylandCompositor QtWaylandCompositor::WaylandQuickItem::compositor
+ * \qmlproperty WaylandCompositor QtWayland.Compositor::WaylandQuickItem::compositor
*
* This property holds the compositor for the surface rendered by this WaylandQuickItem.
*/
@@ -414,7 +506,7 @@ QWaylandView *QWaylandQuickItem::view() const
}
/*!
- * \qmlproperty WaylandSurface QtWaylandCompositor::WaylandQuickItem::surface
+ * \qmlproperty WaylandSurface QtWayland.Compositor::WaylandQuickItem::surface
*
* This property holds the surface rendered by this WaylandQuickItem.
*/
@@ -442,11 +534,13 @@ void QWaylandQuickItem::setSurface(QWaylandSurface *surface)
emit compositorChanged();
if (oldSurf != surface)
emit surfaceChanged();
+
+ updateFocus();
update();
}
/*!
- * \qmlproperty enum QtWaylandCompositor::WaylandQuickItem::origin
+ * \qmlproperty enum QtWayland.Compositor::WaylandQuickItem::origin
*
* This property holds the origin of the QWaylandQuickItem.
*/
@@ -665,7 +759,7 @@ void QWaylandQuickItem::keyPressEvent(QKeyEvent *event)
void QWaylandQuickItem::keyReleaseEvent(QKeyEvent *event)
{
Q_D(QWaylandQuickItem);
- if (d->shouldSendInputEvents() && hasFocus()) {
+ if (d->shouldSendInputEvents()) {
QWaylandSeat *seat = compositor()->seatFor(event);
seat->sendFullKeyEvent(event);
} else {
@@ -683,7 +777,7 @@ void QWaylandQuickItem::touchEvent(QTouchEvent *event)
QWaylandSeat *seat = compositor()->seatFor(event);
QPointF pointPos;
- const QList<QTouchEvent::TouchPoint> &points = event->touchPoints();
+ const QList<QTouchEvent::TouchPoint> &points = event->points();
if (!points.isEmpty())
pointPos = points.at(0).position();
@@ -754,10 +848,16 @@ void QWaylandQuickItem::handleSubsurfaceAdded(QWaylandSurface *childSurface)
childItem->setSurface(childSurface);
childItem->setVisible(true);
childItem->setParentItem(this);
+ childItem->setParent(this);
connect(childSurface, &QWaylandSurface::subsurfacePositionChanged, childItem, &QWaylandQuickItem::handleSubsurfacePosition);
+ connect(childSurface, &QWaylandSurface::destroyed, childItem, &QObject::deleteLater);
} else {
bool success = QMetaObject::invokeMethod(d->subsurfaceHandler, "handleSubsurfaceAdded", Q_ARG(QWaylandSurface *, childSurface));
if (!success)
+ success = QMetaObject::invokeMethod(d->subsurfaceHandler, "handleSubsurfaceAdded",
+ Q_ARG(QVariant, QVariant::fromValue(childSurface)));
+
+ if (!success)
qWarning("QWaylandQuickItem: subsurfaceHandler does not implement handleSubsurfaceAdded()");
}
}
@@ -796,8 +896,15 @@ void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface)
}
}
+void QWaylandQuickItem::updateFocus()
+{
+ Q_D(const QWaylandQuickItem);
+ if (hasActiveFocus() && compositor())
+ compositor()->defaultSeat()->setKeyboardFocus(d->view->surface());
+}
+
/*!
- \qmlproperty object QtWaylandCompositor::WaylandQuickItem::subsurfaceHandler
+ \qmlproperty object QtWayland.Compositor::WaylandQuickItem::subsurfaceHandler
This property provides a way to override the default subsurface behavior.
@@ -809,8 +916,9 @@ void QWaylandQuickItem::handlePlaceBelow(QWaylandSurface *referenceSurface)
\code
ShellSurfaceItem {
subsurfaceHandler: QtObject {
- function handleSubsurfaceAdded(child) {
- //create custom surface item, and connect the subsurfacePositionChanged signal
+ function handleSubsurfaceAdded(child) {
+ // create custom surface item, and connect the subsurfacePositionChanged signal
+ }
}
}
\endcode
@@ -835,6 +943,11 @@ void QWaylandQuickItem::setSubsurfaceHandler(QObject *handler)
}
/*!
+ * \qmlproperty WaylandOutput QtWayland.Compositor::WaylandQuickItem::output
+ *
+ * This property holds the output on which this item is displayed.
+ */
+/*!
* \property QWaylandQuickItem::output
*
* This property holds the output on which this item is displayed.
@@ -852,7 +965,7 @@ void QWaylandQuickItem::setOutput(QWaylandOutput *output)
}
/*!
- * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::bufferLocked
+ * \qmlproperty bool QtWayland.Compositor::WaylandQuickItem::bufferLocked
*
* This property holds whether the item's buffer is currently locked. As long as
* the buffer is locked, it will not be released and returned to the client.
@@ -877,6 +990,10 @@ void QWaylandQuickItem::setBufferLocked(bool locked)
{
Q_D(QWaylandQuickItem);
d->view->setBufferLocked(locked);
+
+ // Apply the latest surface size
+ if (!locked)
+ updateSize();
}
/*!
@@ -986,7 +1103,7 @@ void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
{
forceActiveFocus();
- if (!surface())
+ if (!surface() || !surface()->client())
return;
QWaylandSeat *target = device;
@@ -995,13 +1112,22 @@ void QWaylandQuickItem::takeFocus(QWaylandSeat *device)
}
target->setKeyboardFocus(surface());
- {
+ qCDebug(qLcWaylandCompositorInputMethods) << Q_FUNC_INFO << " surface:" << surface()
+ << ", client:" << surface()->client()
+ << ", textinputprotocol:" << (int)(surface()->client()->textInputProtocols());
+ if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV2)) {
QWaylandTextInput *textInput = QWaylandTextInput::findIn(target);
if (textInput)
textInput->setFocus(surface());
}
- {
+ if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::TextInputV3)) {
+ QWaylandTextInputV3 *textInputV3 = QWaylandTextInputV3::findIn(target);
+ if (textInputV3)
+ textInputV3->setFocus(surface());
+ }
+
+ if (surface()->client()->textInputProtocols().testFlag(QWaylandClient::TextInputProtocol::QtTextInputMethodV1)) {
QWaylandQtTextInputMethod *textInputMethod = QWaylandQtTextInputMethod::findIn(target);
if (textInputMethod)
textInputMethod->setFocus(surface());
@@ -1038,6 +1164,12 @@ void QWaylandQuickItem::updateSize()
{
Q_D(QWaylandQuickItem);
+ // No resize if buffer is locked
+ if (isBufferLocked()) {
+ qWarning() << "No update on item size as the buffer is currently locked";
+ return;
+ }
+
QSize size(0, 0);
if (surface())
size = surface()->destinationSize() * d->scaleFactor();
@@ -1046,7 +1178,7 @@ void QWaylandQuickItem::updateSize()
}
/*!
- * \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::focusOnClick
+ * \qmlproperty bool QtWayland.Compositor::WaylandQuickItem::focusOnClick
*
* This property specifies whether the WaylandQuickItem should take focus when
* it is clicked or touched.
@@ -1161,7 +1293,7 @@ QVariant QWaylandQuickItem::inputMethodQuery(Qt::InputMethodQuery query, QVarian
#endif
/*!
- \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::paintEnabled
+ \qmlproperty bool QtWayland.Compositor::WaylandQuickItem::paintEnabled
Returns true if the item is hidden, though the texture
is still updated. As opposed to hiding the item by
@@ -1196,7 +1328,7 @@ void QWaylandQuickItem::setPaintEnabled(bool enabled)
}
/*!
- \qmlproperty bool QtWaylandCompositor::WaylandQuickItem::touchEventsEnabled
+ \qmlproperty bool QtWayland.Compositor::WaylandQuickItem::touchEventsEnabled
This property holds \c true if touch events are forwarded to the client
surface, \c false otherwise.
@@ -1242,15 +1374,15 @@ void QWaylandQuickItem::updateWindow()
if (d->connectedWindow) {
connect(d->connectedWindow, &QQuickWindow::beforeSynchronizing, this, &QWaylandQuickItem::beforeSync, Qt::DirectConnection);
connect(d->connectedWindow, &QQuickWindow::screenChanged, this, &QWaylandQuickItem::updateSize); // new screen may have new dpr
- }
- if (compositor() && d->connectedWindow) {
- QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
- Q_ASSERT(output);
- d->view->setOutput(output);
- }
+ if (compositor()) {
+ QWaylandOutput *output = compositor()->outputFor(d->connectedWindow);
+ Q_ASSERT(output);
+ d->view->setOutput(output);
+ }
- updateSize(); // because scaleFactor depends on devicePixelRatio, which may be different for the new window
+ updateSize(); // because scaleFactor depends on devicePixelRatio, which may be different for the new window
+ }
}
void QWaylandQuickItem::updateOutput()
@@ -1291,7 +1423,7 @@ void QWaylandQuickItem::updateInputMethod(Qt::InputMethodQueries queries)
#endif
/*!
- * \qmlsignal void QtWaylandCompositor::WaylandQuickItem::surfaceDestroyed()
+ * \qmlsignal void QtWayland.Compositor::WaylandQuickItem::surfaceDestroyed()
*
* This signal is emitted when the client has destroyed the \c wl_surface associated
* with the WaylandQuickItem. The handler for this signal is expected to either destroy the
@@ -1322,7 +1454,7 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
d->lastMatrix = data->transformNode->combinedMatrix();
const bool bufferHasContent = d->view->currentBuffer().hasContent();
- if (d->view->isBufferLocked() && !bufferHasContent && d->paintEnabled)
+ if (d->view->isBufferLocked() && d->paintEnabled)
return oldNode;
if (!bufferHasContent || !d->paintEnabled || !surface()) {
@@ -1340,16 +1472,42 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
|| bufferTypes[ref.bufferFormatEgl()].canProvideTexture
#endif
) {
+#if QT_CONFIG(opengl)
+ if (oldNode && !d->paintByProvider) {
+ // Need to re-create a node
+ delete oldNode;
+ oldNode = nullptr;
+ }
+ d->paintByProvider = true;
+#endif
// This case could covered by the more general path below, but this is more efficient (especially when using ShaderEffect items).
QSGSimpleTextureNode *node = static_cast<QSGSimpleTextureNode *>(oldNode);
if (!node) {
node = new QSGSimpleTextureNode();
+ if (smooth())
+ node->setFiltering(QSGTexture::Linear);
d->newTexture = true;
}
- if (!d->provider)
+ if (!d->provider) {
d->provider = new QWaylandSurfaceTextureProvider();
+ if (compositor()) {
+ d->texProviderConnection =
+ QObject::connect(
+ compositor(),
+ &QObject::destroyed,
+ this,
+ [this](QObject*) {
+ auto *itemPriv = QWaylandQuickItemPrivate::get(this);
+ if (itemPriv->provider) {
+ itemPriv->provider->deleteLater();
+ itemPriv->provider = nullptr;
+ }
+ disconnect(itemPriv->texProviderConnection); }
+ );
+ }
+ }
if (d->newTexture) {
d->newTexture = false;
@@ -1370,6 +1528,13 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
#if QT_CONFIG(opengl)
Q_ASSERT(!d->provider);
+ if (oldNode && d->paintByProvider) {
+ // Need to re-create a node
+ delete oldNode;
+ oldNode = nullptr;
+ }
+ d->paintByProvider = false;
+
QSGGeometryNode *node = static_cast<QSGGeometryNode *>(oldNode);
if (!node) {
@@ -1388,23 +1553,20 @@ QSGNode *QWaylandQuickItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDat
if (d->newTexture) {
d->newTexture = false;
- for (int plane = 0; plane < bufferTypes[ref.bufferFormatEgl()].planeCount; plane++)
- if (auto texture = ref.toOpenGLTexture(plane)) {
- QQuickWindow::CreateTextureOptions opt;
- QWaylandQuickSurface *waylandSurface = qobject_cast<QWaylandQuickSurface *>(surface());
- if (waylandSurface != nullptr && waylandSurface->useTextureAlpha())
- opt |= QQuickWindow::TextureHasAlphaChannel;
- QSGTexture *scenegraphTexture = QNativeInterface::QSGOpenGLTexture::fromNative(texture->textureId(),
- window(),
- ref.size(),
- opt);
- scenegraphTexture->setFiltering(smooth() ? QSGTexture::Linear : QSGTexture::Nearest);
- material->setTextureForPlane(plane, texture, scenegraphTexture);
- }
- material->bind();
+ material->setBufferRef(this, ref);
}
- QSGGeometry::updateTexturedRectGeometry(geometry, rect, QRectF(0, 0, 1, 1));
+ const QSize surfaceSize = ref.size() / surface()->bufferScale();
+ const QRectF sourceGeometry = surface()->sourceGeometry();
+ const QRectF normalizedCoordinates =
+ sourceGeometry.isValid()
+ ? QRectF(sourceGeometry.x() / surfaceSize.width(),
+ sourceGeometry.y() / surfaceSize.height(),
+ sourceGeometry.width() / surfaceSize.width(),
+ sourceGeometry.height() / surfaceSize.height())
+ : QRectF(0, 0, 1, 1);
+
+ QSGGeometry::updateTexturedRectGeometry(geometry, rect, normalizedCoordinates);
node->setGeometry(geometry);
node->setFlag(QSGNode::OwnsGeometry, true);
@@ -1447,20 +1609,34 @@ void QWaylandQuickItem::setInputEventsEnabled(bool enabled)
void QWaylandQuickItem::lower()
{
- QQuickItem *parent = parentItem();
+ Q_D(QWaylandQuickItem);
+ d->lower();
+}
+
+void QWaylandQuickItemPrivate::lower()
+{
+ Q_Q(QWaylandQuickItem);
+ QQuickItem *parent = q->parentItem();
Q_ASSERT(parent);
- QQuickItem *bottom = parent->childItems().first();
- if (this != bottom)
- stackBefore(bottom);
+ QQuickItem *bottom = parent->childItems().constFirst();
+ if (q != bottom)
+ q->stackBefore(bottom);
}
void QWaylandQuickItem::raise()
{
- QQuickItem *parent = parentItem();
+ Q_D(QWaylandQuickItem);
+ d->raise();
+}
+
+void QWaylandQuickItemPrivate::raise()
+{
+ Q_Q(QWaylandQuickItem);
+ QQuickItem *parent = q->parentItem();
Q_ASSERT(parent);
- QQuickItem *top = parent->childItems().last();
- if (this != top)
- stackAfter(top);
+ QQuickItem *top = parent->childItems().constLast();
+ if (q != top)
+ q->stackAfter(top);
}
void QWaylandQuickItem::sendMouseMoveEvent(const QPointF &position, QWaylandSeat *seat)
@@ -1590,3 +1766,5 @@ void QWaylandQuickItemPrivate::placeBelowParent()
}
QT_END_NAMESPACE
+
+#include "moc_qwaylandquickitem.cpp"