在本页

QCanvasRhiPaintDriver Class

QCanvasRhiPaintDriver 类管理QCanvasPainter 基于QRhi 渲染目标和离屏画布的渲染的底层方面。更多

Header: #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, const QColor &fillColor = Qt::black, QSize logicalSize = QSize(), float dpr = 1.0f, QCanvasRhiPaintDriver::BeginPaintFlags flags = {})
void endPaint(QCanvasRhiPaintDriver::EndPaintFlags flags = {})
void grabCanvas(const QCanvasOffscreenCanvas &canvas, std::function<void (const QImage &)> callback)
void renderPaint()
void resetForNewFrame()

详细说明

应用程序希望使用QCanvasPainter 渲染基于QRhi 的渲染目标,如渲染到QRhiTexture 或渲染到QRhiSwapChain 的颜色缓冲区,可使用QCanvasPainterFactory 初始化和检索QCanvasPainter 以及与QRhi 关联的 QCanvasRhiPaintDriver。绘图 API 由QCanvasPainter 提供,而渲染的底层方面(渲染目标、命令缓冲区等)由 QCanvasRhiPaintDriver 控制。

注意: 该类仅在使用QCanvasPainter 而不使用QCanvasPainterWidgetQCanvasPainterItem 等便利类时才有意义,因为这些类为应用程序提供了一个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;
}

成员类型文档

枚举类 QCanvasRhiPaintDriver::BeginPaintFlag
flags QCanvasRhiPaintDriver::BeginPaintFlags

指定beginPaint() 的标志。

常量说明
QCanvasRhiPaintDriver::BeginPaintFlag::DepthTest0x01表示渲染时应启用深度测试。通常情况下,QCanvasPainter 不会写入或测试深度缓冲区。如果需要对其他渲染器写入的值进行测试,请设置此标记。使用的深度比较函数是Less

BeginPaintFlags 类型是QFlags<BeginPaintFlag> 的类型定义。它存储 BeginPaintFlag 值的 OR 组合。

枚举类 QCanvasRhiPaintDriver::EndPaintFlag
flags QCanvasRhiPaintDriver::EndPaintFlags

指定endPaint() 的标志。

常量说明
QCanvasRhiPaintDriver::EndPaintFlag::DoNotRecordRenderPass0x01表示不希望刷新QCanvasPainter 生成的命令并记录QRhi 渲染传递,因为之后将明确调用renderPaint()。

EndPaintFlags 类型是QFlags<EndPaintFlag> 的类型定义。它存储 EndPaintFlag 值的 OR 组合。

成员函数文档

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 的 modelview-projection 矩阵。

视口尺寸和设备像素比例取自渲染目标。

该重载不需要填充颜色,因为在实际应用中,该重载的后面应该是设置了EndPaintFlag::DoNotRecordRenderPass 标志的endPaint() 。

注: 使用自定义矩阵时,对剪切的支持会受到限制。如果矩阵指定的是正投影,而没有添加任何缩放或旋转,则支持矩形、非变换剪辑。一般建议避免在此模式下依靠剪切进行绘制。

注意: beginPaint() 后必须跟一个endPaint() 。目前不支持嵌套。

注: 预计rt 将同时具有颜色和深度模板附件。如果有多个颜色附件,则只写入附件 0 的颜色缓冲区。QCanvasPainter 需要有深度钢网缓冲区。目前只使用模版,深度测试和写入始终处于禁用状态。

注意: 相关的QRhi 必须正在记录帧(QRhi::beginFrame() 或QRhi::beginOffscreenFrame() 必须已被调用),但调用此函数时不应处于渲染传递记录状态。

flags 指定控制渲染的可选标记。

这是一个重载函数。

void QCanvasRhiPaintDriver::beginPaint(QRhiCommandBuffer *cb, QRhiRenderTarget *rt, const QColor &fillColor = Qt::black, QSize logicalSize = QSize(), float dpr = 1.0f, 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()可以用来控制渲染过程的记录,因为在某些情况下,让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()。

void QCanvasRhiPaintDriver::grabCanvas(const QCanvasOffscreenCanvas &canvas, std::function<void (const QImage &)> callback)

canvas 发出纹理回读请求。

callback 在函数返回之前或之后调用,具体取决于底层QRhi 和 3D API 实现。读回纹理内容可能涉及 GPU->CPU 复制,具体取决于 GPU 架构。

该函数既可以在beginPaint() -endPaint() 代码块内调用,也可以在代码块外调用。在外部调用时,它将在内部调用QRhi::beginOffscreenFrame() 等,以便随时进行抓取。

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.