QQuickRenderControl 类

The QQuickRenderControl class provides a mechanism for rendering the Qt Quick scenegraph onto an offscreen render target in a fully application-controlled manner. 更多...

头文件 #include <QQuickRenderControl>
CMakefind_package(Qt6 REQUIRED COMPONENTS Quick)
target_link_libraries(mytarget PRIVATE Qt6::Quick)
qmakeQT += quick
继承 QObject

公开函数

QQuickRenderControl(QObject *parent = nullptr)
虚拟~QQuickRenderControl() override
(since 6.0) voidbeginFrame()
(since 6.6) QRhiCommandBuffer *commandBuffer() const
(since 6.0) voidendFrame()
(since 6.0) boolinitialize()
voidinvalidate()
voidpolishItems()
voidprepareThread(QThread *targetThread)
voidrender()
virtual QWindow *renderWindow(QPoint *offset)
(since 6.6) QRhi *rhi() const
(since 6.0) intsamples() const
(since 6.0) voidsetSamples(int sampleCount)
boolsync()
(since 6.0) QQuickWindow *window() const

信号

静态公开成员

QWindow *renderWindowFor(QQuickWindow *win, QPoint *offset = nullptr)

详细描述

QQuickWindowQQuickView 及其相关的内部渲染循环将 Qt Quick 场景渲染到原生窗口。在一些情况下,例如与第三方 OpenGL、Vulkan、Metal 或 Direct 3D 渲染器集成时,将场景获取到纹理中,然后由外部渲染引擎以任意方式使用是很有用的。这种机制在与 VR 框架集成时同样必不可少。QQuickRenderControl 通过硬件加速的方式实现这一点,与使用 QQuickWindow::grabWindow() 在性能上有限的替代方案不同。

在使用 QQuickRenderControl 时,不应该显示 QQuickWindow(它不会在屏幕上可见)且不会为其提供底层本地窗口。相反,使用 QQuickWindow 构造函数的超载实例将 QQuickWindow 与渲染控制对象关联,并通过 QQuickWindow::setRenderTarget() 指定纹理或图像对象。尽管如此,由于它表示 Qt Quick 场景并提供大部分场景管理和事件传递机制,因此 QQuickWindow 对象仍然至关重要。但从视窗系统的角度来看,它并不充当真正的屏幕窗口。

图形设备、上下文、图像和纹理对象的管理由应用程序负责。在调用 initialize() 之前必须创建将被 Qt Quick 使用的设备或上下文。纹理对象的创建可以延迟,详情见下文。Qt 5.4 引入了 QOpenGLContext 采用现有本地上下文的能力。与 QQuickRenderControl 结合,这可以使创建与外部渲染引擎现有上下文共享的 QOpenGLContext 成为可能。然后,可以使用新的 QOpenGLContext 将 Qt Quick 场景渲染到其他引擎的上下文可访问的纹理中。对于 Vulkan、Metal 和 Direct 3D,由于没有提供设备对象的 Qt 包装器,因此可以通过 QQuickWindow::setGraphicsDevice() 直接传递现有的。

使用 QQmlEngine 通过加载和实例化 QML 组件发生。一旦创建了根对象,它将需要连接到 QQuickWindow 的内容项上。

应用程序通常会连接到 4 个重要的信号

要向场景发送事件,例如鼠标或键盘事件,请使用带有 QQuickWindow 实例作为接收者的 QCoreApplication::sendEvent()。

对于键盘事件,可能还需要手动设置所需的项目的焦点。实际上,这涉及在项目关联到场景(即 QQuickWindow)时,在所需的项目上(例如场景的根项)调用 forceActiveFocus()。

注意: 通常,所有 Qt Quick 后端都支持 QQuickRenderControl。但是,某些功能(特别是 grab())可能并不总是在所有情况下都可用。

成员函数文档

[显示} QQuickRenderControl::QQuickRenderControl(QObject *parent = nullptr)

构造一个带有父对象 parent 的 QQuickRenderControl 对象。

[覆盖虚函数 noexcept] QQuickRenderControl::~QQuickRenderControl()

销毁实例。释放所有场景图资源。

另请参阅invalidate

[自 6.0] void QQuickRenderControl::beginFrame()

指定图形帧的开始。调用 sync() 或 render() 必须在调用 beginFrame() 和 endFrame() 之间进行。

与 Qt 5 早期的仅 OpenGL 世界不同,使用其他图形 API 进行渲染需要更明确的开始和结束帧的点。在通过 QQuickRenderControl 手动驱动渲染循环时,现在需要 QQuickRenderControl 的用户指定这些点。

一个典型的更新步骤,包括将渲染初始化到现有纹理中,可能如下所示。此示例代码片段假设 Direct3D 11,但相同的概念也适用于其他图形 API。

if (!m_quickInitialized) {
    m_quickWindow->setGraphicsDevice(QQuickGraphicsDevice::fromDeviceAndContext(m_engine->device(), m_engine->context()));

    if (!m_renderControl->initialize())
        qWarning("Failed to initialize redirected Qt Quick rendering");

    m_quickWindow->setRenderTarget(QQuickRenderTarget::fromNativeTexture({ quint64(m_res.texture), 0 },
                                                                         QSize(QML_WIDTH, QML_HEIGHT),
                                                                         SAMPLE_COUNT));

    m_quickInitialized = true;
}

m_renderControl->polishItems();

m_renderControl->beginFrame();
m_renderControl->sync();
m_renderControl->render();
m_renderControl->endFrame(); // Qt Quick's rendering commands are submitted to the device context here

注意:在使用 Qt Quick 的 软件 适配时,不必也不应调用此函数。

注意:内部 beginFrame() 和 endFrame() 调用 beginOffscreenFrame() 和 endOffscreenFrame(),分别。这意味着在调用此函数时,不得在 QRhi 上有任何帧(无论是离屏帧还是基于交换链的帧)正在记录。

此函数是在 Qt 6.0 中引入的。

另请参阅endFrameinitializesyncrenderQQuickGraphicsDeviceQQuickRenderTarget

[自 6.6] QRhiCommandBuffer *QQuickRenderControl::commandBuffer() const

返回当前命令缓冲区。

一旦调用 beginFrame(),就会自动设置一个 QRhiCommandBuffer。这就是 Qt Quick 场景图使用的命令缓冲区,但在某些情况下,应用程序可能还想查询它,例如,发布资源更新(例如,纹理读取回)。

返回的命令缓冲区引用仅在 beginFrame() 和 endFrame() 之间使用。存在特定的例外,例如在 endFrame() 之后以及下一个 beginFrame() 之前调用命令缓冲区上的 lastCompletedGpuTime() 是有效的。

注意:使用 Qt Quick 的 软件 适配时,此函数不适用,并将返回 null。

此函数是在 Qt 6.6 中引入的。

另请参阅rhibeginFrameendFrame

[自 6.0] void QQuickRenderControl::endFrame()

指定图形帧的结束。调用 syncrender 必须在调用 beginFrame() 和 endFrame() 之间进行。

当调用此函数时,场景图排队等待的任何图形命令都会提交到上下文或命令队列,具体取决于情况。

注意:在使用 Qt Quick 的 软件 适配时,不必也不应调用此函数。

此函数是在 Qt 6.0 中引入的。

另请参阅 beginFrame(),initialize(),sync(),render(),QQuickGraphicsDeviceQQuickRenderTarget

[自6.0以来] bool QQuickRenderControl::initialize()

初始化场景图资源。在为Qt Quick渲染使用如Vulkan、Metal、OpenGL或Direct3D等图形API时,当调用此函数时,QQuickRenderControl将设置适当的渲染引擎。只要存在QQuickRenderControl,此渲染基础设施就存在。

要控制Qt Quick使用的图形API,使用QQuickWindow::setGraphicsApi()并传入QSGRendererInterface:GraphicsApi常量之一进行操作。必须在调用此函数之前完成此操作。

要防止场景图创建其自己的设备和上下文对象,通过调用QQuickWindow::setGraphicsDevice()指定适当的QQuickGraphicsDevice并将现有图形对象包装在内。

要配置要启用的设备扩展(例如,对于Vulkan),在调用此函数之前调用QQuickWindow::setGraphicsConfiguration()。

注意:当使用Vulkan时,QQuickRenderControl不会自动创建QVulkanInstance。相反,创建适当的QVulkanInstance并将其与QQuickWindow关联是应用程序的责任。在初始化QVulkanInstance之前,强烈建议通过调用静态函数QQuickGraphicsConfiguration::preferredInstanceExtensions()查询Qt Quick希望设置的实例扩展列表,并将返回的列表传递给QVulkanInstance::setExtensions

成功时返回true,否则返回false

注意:在使用 Qt Quick 的 软件 适配时,不必也不应调用此函数。

使用默认的Qt Quick适配器,此函数创建一个新的QRhi对象,类似于在没有使用QQuickRenderControl时,带屏幕QQuickWindow将产生的情况。要使此新QRhi对象采用某些现有的设备或上下文资源(例如,使用现有的QOpenGLContext而不是创建一个新的),使用上面提到的QQuickWindow::setGraphicsDevice()。当应用程序想使Qt Quick渲染使用已存在的QRhi对象时,也可以通过QQuickGraphicsDevice::fromRhi实现。当设置了此类引用已存在的QRhiQQuickGraphicsDevice后,在initialize()中将不会创建新的QRhi对象。

此函数是在 Qt 6.0 中引入的。

另请参阅 QQuickRenderTargetQQuickGraphicsDeviceQQuickGraphicsConfiguration::preferredInstanceExtensions

void QQuickRenderControl::invalidate()

停止渲染并释放资源。

这等同于在窗口变为隐藏时,真实QQuickWindow发生的清理操作。

此函数在析构函数中被调用。因此通常不需要直接调用它。

调用invalidate()之后,可以通过再次调用initialize()来重用QQuickRenderControl实例。

注意:此函数不考虑QQuickWindow::persistentSceneGraph()或QQuickWindow::persistentGraphics()。这意味着上下文特定的资源总是会释放。

void QQuickRenderControl::polishItems()

在调用sync之前尽可能晚地调用此函数。在多线程场景中,渲染可以与此函数并行发生。

void QQuickRenderControl::prepareThread(QThread *targetThread)

准备在GUI线程外部渲染Qt Quick场景。

targetThread指定同步和渲染将发生的线程。在单线程场景中不需要调用此函数。

void QQuickRenderControl::render()

使用当前上下文渲染场景图。

[信号] void QQuickRenderControl::renderRequested()

当场景图需要渲染时,会发出此信号。不需要调用sync

注意:避免在发出此信号时直接触发渲染。相反,最好通过使用计时器等方式将其延迟。这将提高性能。

[虚函数] QWindow *QQuickRenderControl::renderWindow(QPoint *offset)

在子类中重新实现以返回渲染控制实际渲染到的真实窗口。

如果offset非空,它将被设置为控制在其窗口内的偏移。

注意:虽然不是强制的,但在支持具有不同设备像素比的多屏幕以及正确定位从QML打开的弹出窗口的情况下重新实现此函数变得至关重要。因此,在子类中提供它是非常推荐的。

[静态] QWindow *QQuickRenderControl::renderWindowFor(QQuickWindow *win, QPoint *offset = nullptr)

返回正在渲染到win的实际窗口(如果有)。

如果offset非空,它将被设置为渲染在其窗口内的偏移。

[自6.6起] QRhi *QQuickRenderControl::rhi() const

返回与QQuickRenderControl关联的QRhi

注意:只有在initialize成功完成后,QRhi才会存在。在此之前,返回值是null。

注意:使用 Qt Quick 的 软件 适配时,此函数不适用,并将返回 null。

此函数是在 Qt 6.6 中引入的。

另请参阅commandBuffer()、beginFrame()和endFrame()。

[自6.0起] int QQuickRenderControl::samples() const

返回当前的样本数。1或0表示没有多重采样。

此函数是在 Qt 6.0 中引入的。

另请参阅setSamples()。

[信号] void QQuickRenderControl::sceneChanged()

当场景图更新时,会发出此信号,这意味着需要调用 polishItems() 和 sync()。如果 sync() 返回 true,则需要调用 render()。

注意:当此信号发出时,应避免直接触发精炼、同步和渲染。相反,最好通过使用定时器等方式进行延迟。这将提高性能。

[自6.0起] void QQuickRenderControl::setSamples(int sampleCount)

设置用于多重采样的样本数量。当 sampleCount 为 0 或 1 时,禁用多重采样。

注意:此函数始终与多重采样渲染目标一起使用,这意味着 sampleCount 必须与传递给 QQuickRenderTarget::fromNativeTexture() 的样本数量匹配,该数量必须与原生纹理的样本数量匹配。

此函数是在 Qt 6.0 中引入的。

另请参阅:samples(),initialize(),以及 QQuickRenderTarget

bool QQuickRenderControl::sync()

此函数用于同步 QML 场景与渲染场景图。

如果使用专用的渲染线程,则 GUI 线程在此调用期间应该被阻塞。

如果同步更改了场景图,则返回 true

[自6.0起] QQuickWindow *QQuickRenderControl::window() const

返回与 QQuickWindow 关联的 QQuickRenderControl

注意:在构造 QQuickWindow 时,QQuickRenderControl 将与 QQuickWindow 关联。在此函数返回值之前,此函数的返回值为 null。

此函数是在 Qt 6.0 中引入的。

© 2024 The Qt Company Ltd. 包含在此处的文档贡献分别是其各自所有者的版权。提供的文档根据自由软件基金会发布的条款,在 GNU 自由文档许可的第1.3版 下授权。Qt 及其相关徽标是 The Qt Company Ltd. 在芬兰和/或全球其他国家的商标。所有其他商标均为其各自所有者的财产。