aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/items/qquickgraphicsdevice.cpp
diff options
context:
space:
mode:
authorLaszlo Agocs <laszlo.agocs@qt.io>2020-01-15 09:08:24 +0100
committerLaszlo Agocs <laszlo.agocs@qt.io>2020-04-11 18:23:55 +0200
commit400d176760de84626500787674b1ece387b25893 (patch)
treedbb8b5fd50440e6c01d6b940fe1692ba8e6a1f5c /src/quick/items/qquickgraphicsdevice.cpp
parent654959e2e2b74855036f949a9c23c9d9c7a614ac (diff)
Allow redirecting QRhi-based rendering via QQuickRenderControl
Implement the Qt 6 TODO for using an externally-provided render target when rendering the scene via QRhi. And say hello to QQuickRenderTarget. This class exists to allow potentially extending later what a "render target" consists of. Instead of hard-coding taking a single void * in the setRenderTarget() function, it takes a (implicitly shared, d-pointered) QQuickRenderTarget, which in turn can be created via static factory functions - of which new ones can be added later on. The new version of QQuickWindow::setRenderTarget() takes a QQuickRenderTarget. QQuickRenderControl gets a new initialize() variant, and a few extra functions (beginFrame(), endFrame()). This allows it to, by using QSGRhiSupport internally, create a QRhi under the hood. As a bonus, this also fixes an existing scenegraph resource leak when destroying the QQuickRenderControl. The qquickrendercontrol autotest is extended, with a QRhi-based test case that is executed for all of the QRhi backends that succeed to initialize. This is the internal verification. In addition, there is a Vulkan-based one that creates its own VkDevice, VkImage, and friends, and then uses Qt Quick with the same Vulkan device, targeting the VkImage. This test verifies the typical application use case. (sadly, life is too short to waste it on writing Vulkan boilerplate for an on-screen version of this, but we have the D3D11 example instead) What QQuickRenderControl loses, when used in combination with QRhi, is the grab() function. This never made much sense as a public API: QQuickWindow::grabWindow() call this when the window is associated with a rendercontrol, so as a public API QQuickRenderControl::grab() is redundant, because one gets the same result via the standard QQuickWindow API. It is now made private. More importantly, reading back the content is no longer supported, unless the 'software' backend is in use. The reasoning here is that, if the client of the API manages and provides the render target (as abstracted by QQuickRenderTarget), it is then expected to be capable of reading back the content in whatever way it sees fit, because it owns and manages the resource (e.g. the texture) in the first place. Providing fragile convenience functions for this is not reasonable anymore, and was questionable even with OpenGL, given that it is not future proof - what if the target is suddenly a floating point texture, for instance? The software backend case makes sense because that relies on private APIs - and has no render target concept either - so there the same cannot be achieved by applications by relying on public APIs only. Another new class is QQuickGraphicsDevice. This is very similar to QQuickRenderTarget, it is a simple container capable of holding a set of of native objects, mostly in the form of void*s, with future extensibility thanks to the static factory functions. (examples of native object sets would be a ID3D11Device + ID3D11DeviceContext, or a QOpenGLContext, or a MTLDevice + MTLCommandQueue, or a number of Vulkan device-related objects, etc.) This allows one to specify that the QRhi created under the hood (either by QQuickRenderControl or by the render loop) should use an existing graphics device (i.e. it is basically a public wrapper for values that go into a QRhi*InitParams under the hood). QQuickRenderTarget and QQuickGraphicsDevice are both demonstrated in a new example: rendercontrol_d3d11. We choose D3D11 because it is reasonably simple to set up a renderer with a window, and, because there is known user demand for Qt Quick - external D3D engine interop. Passing in the custom engine's own ID3D11Device and ID3D11DeviceContext is essential: the texture (ID3D11Texture2D) Qt Quick is targeting would not be usable if Qt Quick's QRhi was using a different ID3D11Device. Task-number: QTBUG-78595 Change-Id: I5dfe7f6cf1540daffc2f11136be114a08e87202b Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
Diffstat (limited to 'src/quick/items/qquickgraphicsdevice.cpp')
-rw-r--r--src/quick/items/qquickgraphicsdevice.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/src/quick/items/qquickgraphicsdevice.cpp b/src/quick/items/qquickgraphicsdevice.cpp
new file mode 100644
index 0000000000..029546a5f8
--- /dev/null
+++ b/src/quick/items/qquickgraphicsdevice.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtQuick module 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 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or 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.GPL2 and 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-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquickgraphicsdevice_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QQuickGraphicsDevice
+ \since 6.0
+ \inmodule QtQuick
+
+ \brief The QQuickGraphicsDevice class provides an opaque container for
+ native graphics objects representing graphics devices or contexts.
+
+ \sa QQuickWindow::setGraphicsDevice(), QQuickRenderTarget
+*/
+
+/*!
+ Constructs a default QQuickGraphicsDEvice that does not reference any native
+ objects.
+ */
+QQuickGraphicsDevice::QQuickGraphicsDevice()
+ : d(new QQuickGraphicsDevicePrivate)
+{
+}
+
+/*!
+ \internal
+ */
+void QQuickGraphicsDevice::detach()
+{
+ qAtomicDetach(d);
+}
+
+/*!
+ \internal
+ */
+QQuickGraphicsDevice::QQuickGraphicsDevice(const QQuickGraphicsDevice &other)
+ : d(other.d)
+{
+ d->ref.ref();
+}
+
+/*!
+ \internal
+ */
+QQuickGraphicsDevice &QQuickGraphicsDevice::operator=(const QQuickGraphicsDevice &other)
+{
+ qAtomicAssign(d, other.d);
+ return *this;
+}
+
+/*!
+ Destructor.
+ */
+QQuickGraphicsDevice::~QQuickGraphicsDevice()
+{
+ if (!d->ref.deref())
+ delete d;
+}
+
+/*!
+ Constructs a default QQuickRenderTarget that does not reference any native
+ objects.
+ */
+bool QQuickGraphicsDevice::isNull() const
+{
+ return d->type == QQuickGraphicsDevicePrivate::Type::Null;
+}
+
+/*!
+ \return a new QQuickGraphicsDevice referencing an existing QOpenGLContext.
+
+ This factory function is suitable for OpenGL.
+ */
+QQuickGraphicsDevice QQuickGraphicsDevice::fromOpenGLContext(QOpenGLContext *context)
+{
+ QQuickGraphicsDevice dev;
+ QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev);
+ d->type = QQuickGraphicsDevicePrivate::Type::OpenGLContext;
+ d->u.context = context;
+ return dev;
+}
+
+/*!
+ \return a new QQuickGraphicsDevice referencing a native device and context
+ object.
+
+ This factory function is suitable for:
+
+ \list
+
+ \li Direct3D11 - \a device is expected to be a \c{ID3D11Device*}, \a
+ context is expected to be a \c{ID3D11DeviceContext*}.
+
+ \endlist
+
+ \note the resulting QQuickGraphicsDevice does not own any native resources,
+ it merely contains references. It is the caller's responsibility to ensure
+ that the native resource exists as long as necessary.
+
+ */
+QQuickGraphicsDevice QQuickGraphicsDevice::fromDeviceAndContext(void *device, void *context)
+{
+ QQuickGraphicsDevice dev;
+ QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev);
+ d->type = QQuickGraphicsDevicePrivate::Type::DeviceAndContext;
+ d->u.deviceAndContext = { device, context };
+ return dev;
+}
+
+/*!
+ \return a new QQuickGraphicsDevice referencing a native device and command
+ queue object.
+
+ This factory function is suitable for:
+
+ \list
+
+ \li Metal - \a device is expected to be a \c{MTLDevice*}, \a cmdQueue is
+ expected to be a \c{MTLCommandQueue*}.
+
+ \endlist
+
+ \note the resulting QQuickGraphicsDevice does not own any native resources,
+ it merely contains references. It is the caller's responsibility to ensure
+ that the native resource exists as long as necessary.
+
+ */
+QQuickGraphicsDevice QQuickGraphicsDevice::fromDeviceAndCommandQueue(void *device, void *cmdQueue)
+{
+ QQuickGraphicsDevice dev;
+ QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev);
+ d->type = QQuickGraphicsDevicePrivate::Type::DeviceAndCommandQueue;
+ d->u.deviceAndCommandQueue = { device, cmdQueue };
+ return dev;
+}
+
+/*!
+ \return a new QQuickGraphicsDevice referencing a native device and related
+ objects.
+
+ This factory function is suitable for:
+
+ \list
+
+ \li Vulkan - \a physicalDevice is expected to be \c VkPhysicalDevice, \a
+ device is expected to be a \a VkDevice, while \a queueFamilyIndex is the
+ index of the graphics queue family on the device.
+
+ \endlist
+
+ \note the resulting QQuickGraphicsDevice does not own any native resources,
+ it merely contains references. It is the caller's responsibility to ensure
+ that the native resource exists as long as necessary.
+
+ */
+QQuickGraphicsDevice QQuickGraphicsDevice::fromDeviceObjects(void *physicalDevice, void *device, int queueFamilyIndex)
+{
+ QQuickGraphicsDevice dev;
+ QQuickGraphicsDevicePrivate *d = QQuickGraphicsDevicePrivate::get(&dev);
+ d->type = QQuickGraphicsDevicePrivate::Type::DeviceObjects;
+ d->u.deviceObjects = { physicalDevice, device, queueFamilyIndex };
+ return dev;
+}
+
+QQuickGraphicsDevicePrivate::QQuickGraphicsDevicePrivate()
+ : ref(1)
+{
+}
+
+QQuickGraphicsDevicePrivate::QQuickGraphicsDevicePrivate(const QQuickGraphicsDevicePrivate *other)
+ : ref(1),
+ type(other->type),
+ u(other->u)
+{
+}
+
+QT_END_NAMESPACE