.小智 2025-06-20 10:59 采纳率: 0%
浏览 11

如何让 FPDF_RenderPageSkia 直接渲染到 GPU 加速的 SkCanvas?

我目前正在尝试使用 FPDF_RenderPageSkia 直接渲染 PDF 页面到 GPU 加速的 SkCanvas 上。以下是我最初尝试的代码:

std::unique_ptr<SkPictureRecorder> recorder = std::make_unique<SkPictureRecorder>();
recorder->beginRecording(width, height);
SkCanvas* canvas = recorder->getRecordingCanvas();

// 将 PDF 页面渲染到记录的 canvas 上
FPDF_RenderPageSkia(reinterpret_cast<FPDF_SKIA_CANVAS>(canvas), page, width, height);

sk_sp<SkPicture> picture = recorder->finishRecordingAsPicture();

// 创建 GPU surface 并将 SkPicture 绘制到上面
SkImageInfo info = SkImageInfo::MakeN32Premul(width, height);
sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(grContext.get(), (skgpu::Budgeted)0, info);
surface->getCanvas()->clear(SK_ColorWHITE);
surface->getCanvas()->drawPicture(picture);

这段代码可以正常渲染并调用到 GPU,但 FPDF_RenderPageSkia() 实际上是在 CPU 上执行的。也就是说,它只是录制成了 SkPicture,之后再绘制到 GPU surface 上,这并不是我想要的效果。

于是我修改了代码,尝试直接渲染到 GPU 加速的 canvas:

SkImageInfo info = SkImageInfo::Make(width, height, kUnknown_SkColorType, kPremul_SkAlphaType);
sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(grContext.get(), skgpu::Budgeted::kNo, info);
SkCanvas* canvas = surface->getCanvas();

canvas->clear(SK_ColorWHITE);
FPDF_RenderPageSkia(reinterpret_cast<FPDF_SKIA_CANVAS>(canvas), page, width, height);

但这样的话 SkSurfaces::RenderTarget() 会返回 nullptr,因此我无法获得一个有效的 SkCanvas。

我的问题是:
如何才能创建一个适用于 FPDF_RenderPageSkia 并真正支持 GPU 加速的 SkSurface 和 SkCanvas,从而使 PDF 渲染真正发生在 GPU 上,而不是通过 CPU 先生成 SkPicture 再绘制?

如果您能提供关于 SkImageInfo 正确配置的方法,或者确认 FPDF_RenderPageSkia 是否支持直接 GPU 渲染,将非常感谢!

  • 写回答

5条回答 默认 最新

  • 阿里嘎多学长 2025-06-20 10:59
    关注

    阿里嘎多学长整理AIGC生成,因移动端显示问题导致当前答案未能完全显示,请使用PC端查看更加详细的解答过程

    解决方案

    FPDF_RenderPageSkia 是一个渲染 PDF 页面的函数,它返回一个 SkBitmap 对象,而不是直接渲染到 SkCanvas 上。要将其渲染到 SkCanvas 上,你需要将 SkBitmap 对象转换为 SkImage,然后使用 SkCanvas 的 drawImage 方法渲染。

    以下是一个示例代码:

    SkBitmap bitmap;
    FPDF_RenderPageSkia(&page, &bitmap);
    
    SkImage image(bitmap);
    canvas->drawImage(image, 0, 0);
    

    在上面的代码中,我们首先使用 FPDF_RenderPageSkia 渲染 PDF 页面到 SkBitmap 对象,然后将 SkBitmap 对象转换为 SkImage 对象,最后使用 SkCanvas 的 drawImage 方法将 SkImage 对象渲染到 SkCanvas 上。

    需要注意的是,FPDF_RenderPageSkia 返回的 SkBitmap 对象可能需要被释放,以避免内存泄露。你可以使用 SkBitmap 的 refCount() 方法来检查对象的引用计数,然后使用 SkBitmap 的 unref() 方法来释放对象。

    代码核心部分

    SkBitmap bitmap;
    FPDF_RenderPageSkia(&page, &bitmap);
    
    SkImage image(bitmap);
    canvas->drawImage(image, 0, 0);
    

    依赖关系

    • FPDF_RenderPageSkia
    • SkBitmap
    • SkImage
    • SkCanvas
    评论

报告相同问题?

问题事件

  • 创建了问题 6月20日