PySide6.QtQuick.QQuickRenderControl¶
- class QQuickRenderControl¶
QQuickRenderControl
类提供了一种机制,用于以完全由应用程序控制的方式将 Qt Quick 场景图渲染到离屏渲染目标上。更多…概要¶
方法¶
def
__init__()
def
beginFrame()
def
commandBuffer()
def
endFrame()
def
initialize()
def
invalidate()
def
polishItems()
def
prepareThread()
def
render()
def
rhi()
def
samples()
def
setSamples()
def
sync()
def
window()
虚拟方法¶
def
renderWindow()
信号¶
def
sceneChanged()
静态函数¶
注意
本文档可能包含从C++自动翻译到Python的代码片段。我们始终欢迎对代码片段翻译的贡献。如果您发现翻译问题,您也可以通过在我们的https:/bugreports.qt.io/projects/PYSIDE上创建工单来告知我们。
详细描述¶
QQuickWindow
和QQuickView
及其相关的内部渲染循环将 Qt Quick 场景渲染到原生窗口上。在某些情况下,例如与第三方 OpenGL、Vulkan、Metal 或 Direct 3D 渲染器集成时,将场景获取到纹理中,然后由外部渲染引擎以任意方式使用,可能会很有用。在与 VR 框架集成时,这种机制也是必不可少的。QQuickRenderControl
以硬件加速的方式实现了这一点,与性能受限的替代方案grabWindow()
不同。当使用
QQuickRenderControl
时,QQuickWindow
不能被显示(它不会在屏幕上可见),并且不会有底层的原生窗口。相反,QQuickWindow
实例与渲染控制对象相关联,使用QQuickWindow
构造函数的重载,并通过setRenderTarget()
指定的纹理或图像对象。QQuickWindow
对象仍然是必不可少的,因为它代表了Qt Quick场景,并提供了大部分的场景管理和事件传递机制。然而,从窗口系统的角度来看,它并不充当真正的屏幕窗口。图形设备、上下文、图像和纹理对象的管理由应用程序负责。Qt Quick 使用的设备或上下文必须在调用
initialize()
之前创建。纹理对象的创建可以推迟,详见下文。Qt 5.4 引入了 QOpenGLContext 采用现有本地上下文的能力。与QQuickRenderControl
结合使用,可以创建一个与外部渲染引擎现有上下文共享的 QOpenGLContext。然后,这个新的 QOpenGLContext 可以用于将 Qt Quick 场景渲染到纹理中,该纹理也可以被其他引擎的上下文访问。对于 Vulkan、Metal 和 Direct 3D,Qt 没有提供设备对象的封装,因此现有的对象可以通过setGraphicsDevice()
直接传递。QML组件的加载和实例化是通过使用QQmlEngine来完成的。一旦创建了根对象,它需要被设置为
QQuickWindow
的contentItem()的子对象。应用程序通常需要连接到4个重要信号:
sceneGraphInitialized()
在调用initialize()
之后的某个时刻发出。在此信号发出时,应用程序应创建其帧缓冲对象并将其与QQuickWindow
关联。sceneGraphInvalidated()
当场景图资源被释放时,帧缓冲对象也可以被销毁。renderRequested()
表示需要通过调用render()
来渲染场景。在使上下文成为当前上下文后,应用程序应调用render()
。sceneChanged()
表示场景已更改,这意味着在渲染之前,还需要进行抛光和同步。
要向场景发送事件,例如鼠标或键盘事件,请使用QCoreApplication::sendEvent(),并将
QQuickWindow
实例作为接收者。对于关键事件,可能还需要手动将焦点设置在所需的项目上。实际上,这涉及到在所需的项目上调用
forceActiveFocus()
,例如场景的根项目,一旦它与场景(QQuickWindow
)关联。注意
一般来说,
QQuickRenderControl
支持与所有 Qt Quick 后端结合使用。然而,某些功能,特别是 grab(),可能并非在所有情况下都可用。构造一个
QQuickRenderControl
对象,父对象为parent
。- beginFrame()¶
指定图形帧的开始。对
sync()
或render()
的调用必须包含在beginFrame()和endFrame()
的调用之间。与早期仅支持OpenGL的Qt 5世界不同,使用其他图形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的
software
适配时,不需要也不得调用此函数。注意
在内部,beginFrame() 和
endFrame()
分别调用 beginOffscreenFrame() 和 endOffscreenFrame()。这意味着在调用此函数时,QRhi 上不得有正在记录的帧(无论是离屏帧还是基于交换链的帧)。- commandBuffer()¶
- Return type:
QRhiCommandBuffer
返回当前命令缓冲区。
一旦调用了
beginFrame()
,就会自动设置一个QRhiCommandBuffer。这是Qt Quick场景图使用的命令缓冲区,但在某些情况下,应用程序可能还希望查询它,例如发出资源更新(例如,纹理回读)。返回的命令缓冲区引用应仅在
beginFrame()
和endFrame()
之间使用。有特定的例外情况,例如在endFrame()
之后但在下一个beginFrame()
之前调用命令缓冲区上的lastCompletedGpuTime()是有效的。- endFrame()¶
指定图形帧的结束。对
sync()
或render()
的调用必须包含在对beginFrame()
和endFrame()的调用中。当调用此函数时,由场景图排队的任何图形命令将提交到上下文或命令队列,视情况而定。
注意
在使用Qt Quick的
software
适配时,不需要也不得调用此函数。- initialize()¶
- Return type:
布尔
初始化场景图资源。当使用图形API(如Vulkan、Metal、OpenGL或Direct3D)进行Qt Quick渲染时,
QQuickRenderControl
将在调用此函数时设置适当的渲染引擎。只要QQuickRenderControl
存在,此渲染基础设施就会存在。要控制Qt Quick使用的图形API,请使用
setGraphicsApi()
并传入QSGRendererInterface
中的GraphicsApi常量之一。这必须在调用此函数之前完成。为了防止场景图创建自己的设备和上下文对象,通过调用
setGraphicsDevice()
,指定一个适当的QQuickGraphicsDevice
,包装现有的图形对象。要配置启用哪些设备扩展(例如,对于Vulkan),请在此函数之前调用
setGraphicsConfiguration()
。注意
在使用Vulkan时,
QQuickRenderControl
不会自动创建QVulkanInstance。相反,应用程序有责任创建一个合适的QVulkanInstance并将其与QQuickWindow
关联。在初始化QVulkanInstance之前,强烈建议通过调用静态函数preferredInstanceExtensions()
查询Qt Quick所需的实例扩展列表,并将返回的列表传递给QVulkanInstance::setExtensions()。成功时返回
true
,否则返回false
。注意
在使用Qt Quick的
software
适配时,不需要也不得调用此函数。使用默认的Qt Quick适配时,此函数会创建一个新的QRhi对象,类似于在没有使用
QQuickRenderControl
时,屏幕上的QQuickWindow
会发生的情况。为了使这个新的QRhi对象采用一些现有的设备或上下文资源(例如使用现有的QOpenGLContext而不是创建一个新的),请使用上面提到的setGraphicsDevice()
。当应用程序希望使Qt Quick渲染使用已经存在的QRhi对象时,也可以通过fromRhi()
实现。当设置了这样一个引用已经存在的QRhi的QQuickGraphicsDevice
时,initialize()中将不会创建新的、专用的QRhi对象。- invalidate()¶
停止渲染并释放资源。
这相当于当窗口隐藏时,真实的
QQuickWindow
所执行的清理操作。此函数从析构函数中调用。因此通常不需要直接调用它。
一旦调用了invalidate(),就可以通过再次调用
initialize()
来重用QQuickRenderControl
实例。注意
此函数不考虑 QQuickWindow::persistentSceneGraph() 或 QQuickWindow::persistentGraphics()。这意味着特定于上下文的资源总是会被释放。
- polishItems()¶
此函数应尽可能在
sync()
之前调用。在多线程场景中,渲染可以与此函数并行进行。准备在GUI线程之外渲染Qt Quick场景。
targetThread
指定了同步和渲染将发生的线程。在单线程场景中不需要调用此函数。- render()¶
使用当前上下文渲染场景图。
- renderRequested()¶
当场景图需要渲染时,会发出此信号。不需要调用
sync()
。注意
当此信号发出时,避免直接触发渲染。相反,建议通过使用计时器等方式来延迟渲染。这将带来更好的性能。
在子类中重新实现,以返回此渲染控件正在渲染的实际窗口。
如果
offset
不为空,它将被设置为控件在窗口内的偏移量。注意
虽然不是强制性的,但为了实现支持具有不同设备像素比的多屏幕以及正确定位从QML打开的弹出窗口,重新实现此函数变得至关重要。因此,强烈建议在子类中提供它。
- static renderWindowFor(win[, offset=None])¶
- Parameters:
win –
QQuickWindow
offset –
QPoint
- Return type:
返回
win
正在渲染到的实际窗口(如果有的话)。如果
offset
不为空,它将被设置为其窗口内渲染的偏移量。- rhi()¶
- Return type:
QRhi
返回与此
QQuickRenderControl
关联的QRhi。注意
QRhi 仅在
initialize()
成功完成后存在。在此之前,返回值为 null。- samples()¶
- Return type:
整数
返回当前的样本计数。1 或 0 表示没有多重采样。
另请参阅
- sceneChanged()¶
当场景图更新时,会发出此信号,这意味着需要调用
polishItems()
和sync()
。如果sync()
返回true,则需要调用render()
。注意
当此信号发出时,避免直接触发抛光、同步和渲染。相反,建议使用计时器等方式将其推迟。这将带来更好的性能。
- setSamples(sampleCount)¶
- Parameters:
sampleCount – int
设置用于多重采样的样本数量。当
sampleCount
为0或1时,多重采样被禁用。注意
此函数始终与多重采样渲染目标结合使用,这意味着
sampleCount
必须与传递给QQuickRenderTarget::fromNativeTexture()的采样计数匹配,而后者又必须与本机纹理的采样计数匹配。- sync()¶
- Return type:
布尔
此函数用于将QML场景与渲染场景图同步。
如果使用了专用的渲染线程,GUI线程在此调用期间应被阻塞。
如果同步改变了场景图,则返回true。
- window()¶
- Return type:
返回与此
QQuickRenderControl
关联的QQuickWindow
。注意
当构造
QQuickWindow
时,QQuickRenderControl
会与QQuickWindow
关联。在此之前,此函数的返回值为空。