QCanvasRhiPaintDriver Class
QCanvasRhiPaintDriver 类负责管理基于QCanvasPainter 的渲染中与QRhi 渲染目标和离屏画布相关的底层细节。更多内容...
| 标题: | #include <QCanvasRhiPaintDriver> |
| CMake: | find_package(Qt6 REQUIRED COMPONENTS CanvasPainter) target_link_libraries(mytarget PRIVATE Qt6::CanvasPainter) |
| 自: | Qt 6.11 |
公共类型
| enum class | BeginPaintFlag { DepthTest } |
| flags | BeginPaintFlags |
| enum class | EndPaintFlag { DoNotRecordRenderPass } |
| flags | EndPaintFlags |
公共函数
| void | beginPaint(QCanvasOffscreenCanvas &canvas, QRhiCommandBuffer *cb, QCanvasRhiPaintDriver::BeginPaintFlags flags = {}) |
| void | beginPaint(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QMatrix4x4 &matrix, QCanvasRhiPaintDriver::BeginPaintFlags flags = {}) |
| void | beginPaint(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, QColor fillColor = Qt::black, QSize logicalSize = QSize(), qreal dpr = 1.0, QCanvasRhiPaintDriver::BeginPaintFlags flags = {}) |
| void | endPaint(QCanvasRhiPaintDriver::EndPaintFlags flags = {}) |
| void | grabCanvas(const QCanvasOffscreenCanvas &canvas, const QObject *context, Functor &&callback) |
| void | renderPaint() |
| void | resetForNewFrame() |
详细说明
应用程序若希望使用QCanvasPainter 在基于QRhi 的渲染目标(例如QRhiTexture )上进行渲染,或渲染到QRhiSwapChain 的颜色缓冲区中,应使用QCanvasPainterFactory 来初始化并获取与QRhi 关联的QCanvasPainter 和QCanvasRhiPaintDriver。 绘制 API 由QCanvasPainter 提供,而渲染的底层方面(例如渲染目标是什么、命令缓冲区是什么等)则由 QCanvasRhiPaintDriver 控制。
注意: 仅当在不使用诸如 QCanvasPainterWidget 或QCanvasPainterItem 等便利类的情况下直接使用QCanvasPainter 时,此类 才相关,因为这些便利类会向应用程序提供一个QCanvasPainter 实例,并隐式管理其渲染。
应用程序不会自行创建 QCanvasRhiPaintDriver 的实例。而是通过调用paintDriver(),从成功加载的initialized QCanvasPainterFactory 中获取该实例。
以下是一个几乎完整的、独立的控制台应用程序,它会在QRhiTexture 中绘制一个圆,读取结果,并将其保存为PNG文件:
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
// std::unique_ptr<QRhi> rhi(QRhi::create(...));
std::unique_ptr<QRhiTexture> tex(rhi->newTexture(QRhiTexture::RGBA8, QSize(1280, 720), 1,
QRhiTexture::RenderTarget | QRhiTexture::UsedAsTransferSource));
tex->create();
std::unique_ptr<QRhiRenderBuffer> ds(rhi->newRenderBuffer(QRhiRenderBuffer::DepthStencil, QSize(1280, 720)));
ds->create();
QRhiTextureRenderTargetDescription rtDesc;
rtDesc.setColorAttachments({ tex.get() });
rtDesc.setDepthStencilBuffer(ds.get());
std::unique_ptr<QRhiTextureRenderTarget> rt(rhi->newTextureRenderTarget(rtDesc));
std::unique_ptr<QRhiRenderPassDescriptor> rp(rt->newCompatibleRenderPassDescriptor());
rt->setRenderPassDescriptor(rp.get());
rt->create();
std::unique_ptr<QCanvasPainterFactory> factory(new QCanvasPainterFactory);
QCanvasPainter *painter = factory->create(rhi.get());
QCanvasRhiPaintDriver *pd = factory->paintDriver();
QRhiCommandBuffer *cb;
QRhiReadbackResult readbackResult;
rhi->beginOffscreenFrame(&cb);
pd->resetForNewFrame();
{
pd->beginPaint(cb, rt.get());
painter->beginPath();
painter->circle(640, 360, 180);
painter->setFillStyle(Qt::red);
painter->fill();
pd->endPaint();
QRhiResourceUpdateBatch *u = rhi->nextResourceUpdateBatch();
u->readBackTexture({ tex.get() }, &readbackResult);
cb->resourceUpdate(u);
}
rhi->endOffscreenFrame();
QImage image(reinterpret_cast<const uchar *>(readbackResult.data.constData()),
readbackResult.pixelSize.width(),
readbackResult.pixelSize.height(),
QImage::Format_RGBA8888);
if (rhi->isYUpInFramebuffer())
image.flip();
image.save("result.png");
return 0;
}成员类型文档
enum class QCanvasRhiPaintDriver::BeginPaintFlag
flags QCanvasRhiPaintDriver::BeginPaintFlags
指定beginPaint() 的标志。
| 常量 | 值 | 说明 |
|---|---|---|
QCanvasRhiPaintDriver::BeginPaintFlag::DepthTest | 0x01 | 表示在渲染时应启用深度测试。通常,QCanvasPainter 不会写入或测试深度缓冲区。如果需要根据另一个渲染器写入的值进行测试,请设置此标志。使用的深度比较函数是Less 。 |
BeginPaintFlags 类型是QFlags<BeginPaintFlag> 的 typedef。它存储 BeginPaintFlag 值的按“或”运算组合。
enum class QCanvasRhiPaintDriver::EndPaintFlag
flags QCanvasRhiPaintDriver::EndPaintFlags
指定endPaint() 的标志。
| 常量 | 值 | 描述 |
|---|---|---|
QCanvasRhiPaintDriver::EndPaintFlag::DoNotRecordRenderPass | 0x01 | 表示不希望刷新QCanvasPainter 生成的命令,也不希望记录QRhi 的渲染过程,因为随后会显式调用renderPaint()。 |
EndPaintFlags 类型是QFlags<EndPaintFlag> 的 typedef。它存储 EndPaintFlag 值的按“或”运算组合。
成员函数文档
void QCanvasRhiPaintDriver::beginPaint(QCanvasOffscreenCanvas &canvas, QRhiCommandBuffer *cb, QCanvasRhiPaintDriver::BeginPaintFlags flags = {})
开始在指定的离屏canvas 上绘制,并将渲染命令记录到命令缓冲区cb 中。
注意:beginPaint () 之后必须紧跟一个endPaint()。目前不支持嵌套调用。
清画布操作由fill color set on the canvas 执行,除非设置了QCanvasOffscreenCanvas::Flag::PreserveContents 标志;在该情况下不会清画布,画布内容将被保留(这可能会对性能产生影响,具体取决于底层 GPU 架构)。
注意:关联的 QRhi 必须正在录制帧(必须已调用QRhi::beginFrame()或QRhi::beginOffscreenFrame()),但在调用此函数时,它不应处于渲染通道录制状态。
flags 指定控制渲染的可选标志。
这是一个重载函数。
void QCanvasRhiPaintDriver::beginPaint(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QMatrix4x4 &matrix, QCanvasRhiPaintDriver::BeginPaintFlags flags = {})
开始将图像绘制到渲染目标rt 上,并将渲染命令记录到命令缓冲区cb 中。
此重载接受一个自定义的matrix ,用于对顶点进行变换。该矩阵必须能够处理坐标以像素为单位的顶点。一个常见的用例是在QSGRenderNode 子类中实现基于QCanvasPainter 的渲染时,传入Qt Quick 的模型-视图-投影矩阵。
视口大小和设备像素比取自渲染目标。
此重载不接受填充颜色,因为实际上预期其后会调用带有EndPaintFlag::DoNotRecordRenderPass 标志的endPaint()方法。
注意: 使用自定义矩阵时,对裁剪的支持 有限。当矩阵指定了不带任何额外缩放或旋转的正交投影时,支持矩形且未经过变换的裁剪。通常建议避免在此模式下依赖裁剪进行绘制。
注意: beginPaint() 之后必须紧跟endPaint()。目前不支持嵌套调用。
注意: rt 应同时具有颜色和深度-模板附件。如果存在多个颜色附件,则仅写入附件 0 的颜色缓冲区。QCanvasPainter 要求存在深度-模板缓冲区。目前仅使用模板,深度测试和写入始终被禁用。
注意:关联的 QRhi 必须正在录制帧(必须已调用QRhi::beginFrame() 或QRhi::beginOffscreenFrame()),但在调用本函数时,它不应处于渲染通道录制状态。
flags 指定控制渲染的可选标志。
这是一个重载函数。
void QCanvasRhiPaintDriver::beginPaint(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, QColor fillColor = Qt::black, QSize logicalSize = QSize(), qreal dpr = 1.0, QCanvasRhiPaintDriver::BeginPaintFlags flags = {})
开始在渲染目标rt 上进行绘制,并将渲染命令记录到命令缓冲区cb 中。
fillColor 指定用于清空颜色缓冲区的颜色。当endPaint() 的标志中包含EndPaintFlag::DoNotRecordRenderPass 时,该值将被忽略。
注意:beginPaint () 之后必须紧跟一个endPaint()。目前不支持嵌套调用。
注意: rt 应同时具有颜色附件和深度-模板附件。如果存在多个颜色附件,则仅写入附件 0 的颜色缓冲区。QCanvasPainter 要求存在深度-模板缓冲区。目前仅使用模板,深度测试和写入始终被禁用。
logicalSize 是可选的。当不为空时,它指定以逻辑单位表示的视口大小。此时,dpr 必须指定缩放因子(设备像素比例),以便logicalSize 能在内部转换为像素。实际上,这很少需要,因为默认情况下会自动使用渲染目标的大小。
注意:关联的 QRhi 必须正在录制帧(必须已调用QRhi::beginFrame() 或QRhi::beginOffscreenFrame()),但在调用此函数时,它不应处于渲染通道录制状态。
flags 指定控制渲染的可选标志。
这是一个重载函数。
void QCanvasRhiPaintDriver::endPaint(QCanvasRhiPaintDriver::EndPaintFlags flags = {})
清空并记录由QCanvasPainter 绘制命令生成的所有QRhi 渲染结果。
默认情况下,此函数会记录完整的渲染通道,这意味着它会在内部调用QRhiCommandBuffer::beginPass()和QRhiCommandBuffer::endPass()。清除颜色由beginPaint()的fillColor参数指定,或采用离屏画布的填充颜色。
flags 可用于控制渲染周期的记录,因为在某些情况下,不希望让 endPaint() 触发完整的 beginPass() - endPass() 序列。
以下两个代码片段在结果上是相同的,但第二个提供了更大的灵活性,以备应用程序需要在同一个渲染通道内执行更多操作:
pd->beginPaint(cb, rt, Qt::black);
// painter->...
pd->endPaint();pd->beginPaint(cb, rt);
// painter->...
pd->endPaint(QCanvasRhiPaintDriver::EndPaintFlag::DoNotRecordRenderPass);
cb->beginPass(rt, Qt::black, { 1.0f, 0 });
pd->renderPaint();
cb->endPass();另请参阅 beginPaint() 和renderPaint()。
template <typename Functor> void QCanvasRhiPaintDriver::grabCanvas(const QCanvasOffscreenCanvas &canvas, const QObject *context, Functor &&callback)
针对canvas 发出纹理回读请求,并将该请求与context 关联。
callback 该函数的调用时机取决于底层的 `QRhi ` 和 3D API 实现,可能在函数返回之前,也可能在之后。根据 GPU 架构的不同,读回纹理内容可能涉及从 GPU 到 CPU 的数据复制。该函数接受一个 `const QImage & ` 参数,该参数可以是任何函数对象,包括仅支持移动操作的函数对象。
如果context 在读回操作完成前被销毁,则抓取操作将被取消,且callback 不会被调用。这使得回调函数可以安全地引用那些可能在待处理的读回操作完成前就已不存在的对象。
该函数既可在beginPaint() -endPaint() 代码块内调用,也可在代码块外调用。当在代码块外调用时,它会在内部调用QRhi::beginOffscreenFrame() 等方法,从而允许在任何时候执行抓取操作。
例如,以下代码将把屏幕外画布的内容保存为 PNG 文件:
void QCanvasRhiPaintDriver::renderPaint()
记录由QCanvasPainter 绘图命令生成的所有QRhi 渲染结果。仅当endPaint()以DoNotRecordRenderPass 参数调用时,才应调用此函数。否则绝不能调用此函数。
调用此函数时,关联的QRhi 必须正在记录渲染通道。
另请参阅 endPaint()。
void QCanvasRhiPaintDriver::resetForNewFrame()
重置绘图引擎的状态。该函数应在开始绘制一个全新的帧时调用一次,通常是在调用QRhi::beginFrame()或QRhi::beginOffscreenFrame()之后。
© 2026 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.