QQuickRenderControl Class
QQuickRenderControl 类提供了一种机制,用于以完全由应用程序控制的方式将Qt Quick 场景图渲染到屏幕外的渲染目标上。更多
Header: | #include <QQuickRenderControl> |
CMake: | find_package(Qt6 REQUIRED COMPONENTS Quick) target_link_libraries(mytarget PRIVATE Qt6::Quick) |
qmake: | QT += quick |
继承: | QObject |
公共函数
QQuickRenderControl(QObject *parent = nullptr) | |
virtual | ~QQuickRenderControl() override |
(since 6.0) void | beginFrame() |
(since 6.6) QRhiCommandBuffer * | commandBuffer() const |
(since 6.0) void | endFrame() |
(since 6.0) bool | initialize() |
void | invalidate() |
void | polishItems() |
void | prepareThread(QThread *targetThread) |
void | render() |
virtual QWindow * | renderWindow(QPoint *offset) |
(since 6.6) QRhi * | rhi() const |
(since 6.0) int | samples() const |
(since 6.0) void | setSamples(int sampleCount) |
bool | sync() |
(since 6.0) QQuickWindow * | window() const |
信号
void | renderRequested() |
void | sceneChanged() |
静态公共成员
QWindow * | renderWindowFor(QQuickWindow *win, QPoint *offset = nullptr) |
详细说明
QQuickWindow 和 及其相关内部渲染循环将 场景渲染到本地窗口。在某些情况下,例如与第三方 OpenGL、Vulkan、Metal 或 Direct 3D 渲染器集成时,将场景转换为纹理可能非常有用,外部渲染引擎可以任意使用纹理。在与 VR 框架集成时,这种机制也是必不可少的。QQuickRenderControl 以硬件加速的方式实现了这一点,而不像使用 () 那样性能有限。QQuickView Qt Quick QQuickWindow::grabWindow
使用 QQuickRenderControl 时,QQuickWindow 不得是shown (在屏幕上不可见),也不会有底层本地窗口。相反,QQuickWindow 实例与渲染控件对象相关联,使用QQuickWindow 构造函数的重载,并通过QQuickWindow::setRenderTarget() 指定纹理或图像对象。QQuickWindow 对象仍然非常重要,因为它代表了Qt Quick 场景,并提供了大部分场景管理和事件传送机制。不过,从窗口系统的角度来看,它并不充当真正的屏幕窗口。
图形设备、上下文、图像和纹理对象的管理由应用程序负责。Qt Quick 将使用的设备或上下文必须在调用initialize() 之前创建。纹理对象的创建可以延迟,见下文。Qt 5.4 引入了QOpenGLContext 采用现有本地上下文的功能。有了 QQuickRenderControl,就可以创建一个与外部渲染引擎现有上下文共享的QOpenGLContext 。然后,新的QOpenGLContext 可用于将Qt Quick 场景渲染为其他引擎上下文也可访问的纹理。对于 Vulkan、Metal 和 Direct 3D 来说,没有 Qt XML 提供的设备对象封装器,因此可以通过QQuickWindow::setGraphicsDevice() 原封不动地传递现有的设备对象。
QML 组件的加载和实例化是通过QQmlEngine 来实现的。一旦创建了根对象,就需要将它作为QQuickWindow'contentItem() 的父对象。
应用程序通常需要连接 4 个重要信号:
- QQuickWindow::sceneGraphInitialized() 在调用QQuickRenderControl::initialize() 后的某个时刻发出。调用该信号后,应用程序将创建帧缓冲对象,并将其与QQuickWindow 关联。
- QQuickWindow::sceneGraphInvalidated(当场景图资源被释放时,帧缓冲对象也会被销毁。
- QQuickRenderControl::renderRequested() 表示必须通过调用render() 来渲染场景。将上下文设置为当前后,应用程序应调用render() 。
- QQuickRenderControl::sceneChanged() 表示场景已发生变化,这意味着在渲染之前,还需要抛光和同步。
要向场景发送事件(如鼠标或键盘事件),请使用QCoreApplication::sendEvent() 并将QQuickWindow 实例作为接收器。
对于按键事件,可能还需要手动将焦点设置到所需的项目上。在实践中,这需要在所需项目(例如场景的根项目)与场景关联后,调用forceActiveFocus() (QQuickWindow)。
注: 一般来说,QQuickRenderControl 支持与所有Qt Quick 后端结合使用。不过,某些功能,尤其是 grab() 功能,可能并非在所有情况下都可用。
成员函数文档
[explicit]
QQuickRenderControl::QQuickRenderControl(QObject *parent = nullptr)
构造一个 QQuickRenderControl 对象,其父对象为parent 。
[override virtual noexcept]
QQuickRenderControl::~QQuickRenderControl()
销毁实例。释放所有场景图资源。
另请参见 invalidate().
[since 6.0]
void QQuickRenderControl::beginFrame()
指定图形帧的起始位置。对sync() 或render() 的调用必须包含对 beginFrame() 和endFrame() 的调用。
与 Qt 5 早期仅使用 OpenGL 的世界不同,使用其他图形 API 进行渲染需要更明确的帧开始和结束点。在通过QQuickRenderControl 手动驱动渲染循环时,现在需要由QQuickRenderControl 的用户来指定这些点。
典型的更新步骤(包括初始化渲染到现有纹理)如下所示。示例片段假定使用 Direct3D 11,但同样的概念也适用于其他图形应用程序接口。
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
注: 在使用software
适配的Qt Quick 时,无需调用此函数,也不得调用此函数。
注: 内部 beginFrame() 和endFrame() 分别调用beginOffscreenFrame() 和endOffscreenFrame() 。这意味着在调用该函数时,QRhi 上必须没有正在记录的帧帧(既非屏幕外帧,也非基于交换链的帧帧)。
此函数在 Qt 6.0 中引入。
另请参阅 endFrame(),initialize(),sync(),render(),QQuickGraphicsDevice, 和QQuickRenderTarget 。
[since 6.6]
QRhiCommandBuffer *QQuickRenderControl::commandBuffer() const
返回当前的命令缓冲区。
调用beginFrame() 后,将自动建立QRhiCommandBuffer 。这是Qt Quick scenegraph 使用的命令缓冲区,但在某些情况下,应用程序可能也想查询它,例如发布资源更新(如纹理回读)。
返回的命令缓冲区引用只能在beginFrame() 和endFrame() 之间使用。有一些特殊的例外情况,例如,在endFrame() 之后但在下一个beginFrame() 之前,在命令缓冲区上调用lastCompletedGpuTime() 是有效的。
注意: 当使用software
改编的Qt Quick 时,此函数不适用并返回空值。
此函数在 Qt 6.6 中引入。
另请参阅 rhi()、beginFrame() 和endFrame()。
[since 6.0]
void QQuickRenderControl::endFrame()
指定图形帧的结束。调用sync() 或render() 时必须同时调用beginFrame() 和 endFrame()。
调用该函数时,场景图所排队的任何图形命令都将提交给上下文或命令队列(以适用者为准)。
注意: 在使用software
适配的Qt Quick 时,不需要也不得调用此函数。
此函数在 Qt 6.0 中引入。
另请参阅 beginFrame(),initialize(),sync(),render(),QQuickGraphicsDevice, 和QQuickRenderTarget 。
[since 6.0]
bool QQuickRenderControl::initialize()
初始化场景图资源。当使用图形 API(如 Vulkan、Metal、OpenGL 或 Direct3D)进行Qt Quick 渲染时,QQuickRenderControl 会在调用此函数时设置适当的渲染引擎。只要QQuickRenderControl 存在,该呈现基础架构就会存在。
要控制Qt Quick 使用何种图形 API,请使用QSGRendererInterface:GraphicsApi 常量之一调用QQuickWindow::setGraphicsApi() 。这必须在调用此函数之前完成。
要防止场景图创建自己的设备和上下文对象,可通过调用QQuickWindow::setGraphicsDevice() 指定一个适当的QQuickGraphicsDevice ,封装现有的图形对象。
要配置启用哪些设备扩展(例如 Vulkan),请在调用本函数之前调用QQuickWindow::setGraphicsConfiguration() 。
注意: 使用 Vulkan 时,QQuickRenderControl 不会自动创建QVulkanInstance 。应用程序有责任通过QQuickWindow 创建合适的QVulkanInstance 和associate it 。在初始化QVulkanInstance 之前,强烈建议调用静态函数QQuickGraphicsConfiguration::preferredInstanceExtensions() 查询Qt Quick 所需的实例扩展名列表,并将返回的列表传递给QVulkanInstance::setExtensions()。
成功时返回true
,否则返回false
。
注意: 在使用software
适配Qt Quick 时,无需也不得调用此函数。
在默认的Qt Quick 适配模式下,该函数会创建一个新的QRhi 对象,这与未使用QQuickRenderControl 时屏幕上的QQuickWindow 的情况类似。要使这个新的QRhi 对象采用现有的设备或上下文资源(例如,使用现有的QOpenGLContext 而不是创建一个新的),请使用上文提到的QQuickWindow::setGraphicsDevice()。如果应用程序想让Qt Quick 渲染使用已有的QRhi 对象,也可以通过QQuickGraphicsDevice::fromRhi() 来实现。如果设置了这样一个QQuickGraphicsDevice ,并引用了一个已存在的QRhi ,那么在 initialize() 中就不会创建新的、专用的QRhi 对象。
该函数在 Qt 6.0 中引入。
另请参阅 QQuickRenderTarget,QQuickGraphicsDevice, 和QQuickGraphicsConfiguration::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()
使用当前上下文渲染场景图。
[signal]
void QQuickRenderControl::renderRequested()
当需要渲染场景图时,会发出该信号。无需调用sync() 。
注意: 避免在此信号发出时直接触发渲染。相反,最好使用定时器等方式推迟渲染。这样性能会更好。
[virtual]
QWindow *QQuickRenderControl::renderWindow(QPoint *offset)
在子类中重新实现,以返回该呈现控件正在呈现的真实窗口。
如果offset 非空,它将被设置为控件在窗口内的偏移量。
注: 虽然不是强制性的,但重新实现该函数对于支持不同设备像素比例的多屏幕以及正确定位从 QML 打开的弹出窗口至关重要。因此,强烈建议在子类中提供该功能。
[static]
QWindow *QQuickRenderControl::renderWindowFor(QQuickWindow *win, QPoint *offset = nullptr)
返回win 正在渲染的真实窗口(如果有)。
如果offset 非空,它将被设置为窗口内渲染的偏移量。
[since 6.6]
QRhi *QQuickRenderControl::rhi() const
返回此QQuickRenderControl 关联的QRhi 。
注意: 只有在initialize() 成功完成后,QRhi 才会存在。在此之前,返回值为空。
注: 使用software
改编的Qt Quick 时,此函数不适用并返回空值。
此函数在 Qt 6.6 中引入。
另请参阅 commandBuffer()、beginFrame() 和endFrame()。
[since 6.0]
int QQuickRenderControl::samples() const
返回当前采样次数。1 或 0 表示无多重采样。
此函数在 Qt 6.0 中引入。
另请参阅 setSamples()。
[signal]
void QQuickRenderControl::sceneChanged()
该信号在场景图更新时发出,这意味着需要调用polishItems() 和sync() 。如果sync() 返回 true,则需要调用render()。
注意: 避免在此信号发出时直接触发抛光、同步和渲染。相反,最好使用定时器等方式来延迟。这样性能会更好。
[since 6.0]
void QQuickRenderControl::setSamples(int sampleCount)
设置用于多重采样的采样个数。当sampleCount 为 0 或 1 时,多重采样将被禁用。
注意: 此函数总是与多采样渲染目标结合使用,这意味着sampleCount 必须与传给 QQuickRenderTarget::fromNativeTexture() 的采样数相匹配,而 QQuickRenderTarget::fromNativeTexture() 又必须与本地纹理的采样数相匹配。
此函数在 Qt 6.0 中引入。
另请参阅 samples(),initialize() 和QQuickRenderTarget 。
bool QQuickRenderControl::sync()
此函数用于同步 QML 场景和渲染场景图。
如果使用了专用的渲染线程,GUI 线程应在此调用期间被阻塞。
如果同步改变了场景图,则返回true。
[since 6.0]
QQuickWindow *QQuickRenderControl::window() const
返回此QQuickRenderControl 关联的QQuickWindow 。
注意: 在构建QQuickWindow 时,一个QQuickRenderControl 会与一个QQuickWindow 关联。在此之前,该函数的返回值为空。
此函数在 Qt 6.0 中引入。
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.