用于 WPE WebKit 和 WebKitGTK 的 Skia 合成器

Lobsters Hottest 新闻

摘要

WPE WebKit 和 WebKitGTK 2.54 已发布,搭载了基于 Skia 的新合成器,取代了 TextureMapper,旨在现代化图形渲染、减少代码维护,并使功能实现更加容易。

<p><a href="https://lobste.rs/s/gexhnh/skia_compositor_for_wpe_webkit_webkitgtk">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/09/21 12:25

# 为WPE WebKit与WebKitGTK打造的Skia合成器 来源:https://blogs.igalia.com/carlosgc/2026/09/21/skia-compositor-for-wpe-webkit-and-webkitgtk/ WPE WebKit (https://wpewebkit.org/release/wpewebkit-2.54.0.html) 与 WebKitGTK (https://webkitgtk.org/2026/09/16/webkitgtk2.54.0-released.html) 2.54 版本已正式发布,包含了一系列改进和新API (https://wpewebkit.org/blog/2026-09-16-wpewebkit-2.54.html),一如既往。但其中有一项功能让Igalia的WebKit图形团队在整个开发周期中忙碌不已:全新的基于Skia (https://skia.org/) 的合成器。我们成功地将内容渲染从Cairo替换为Skia,并已进行了良好的集成与优化。于是我们尝试进一步用Skia替代TextureMapper来实现合成功能。TextureMapper最早于2010年为Qt移植版引入 (https://commits.webkit.org/640ce4cb41c00e7c87b101d0a77d48192227ffeb),后被其他移植版采用。它基于OpenGL ES API,并维护着一套用于绘制不同内容的着色器程序。如今TextureMapper的代码和着色器程序已基本停滞,缺乏维护且功能缺失。然而其性能一直表现优异,多年来为我们提供了可靠的服务。因此,本次目标并非追求基准测试的更好成绩,而是实现现代化、减少需自主维护的代码量(如所有着色器程序),并更便捷地实现缺失功能与修复现有错误。本文总结了我们在本周期内实现新Skia合成器的所有工作。 ## SkiaCompositingLayer 首先添加了`SkiaCompositingLayer`类 (https://commits.webkit.org/311425@main) 以替代`TextureMapperLayer`,并调整所有代码根据环境变量选择使用其中一种实现。初始实现基于TextureMapper中通用的逻辑,例如遍历图层树、计算变换等。图层生成内容的方式未变,因此我们继续接收平铺内容、视频缓冲区、WebGL、加速2D画布等纹理。`SkiaCompositingLayer`会创建一个Ganesh Skia表面,通过`SkCanvas::drawImageRect()`绘制这些纹理。这个初始实现已足以运行默认的MotionMark测试套件 (https://browserbench.org/MotionMark1.3.1/),因为它未使用其他合成功能。尽管性能不是首要目标,但我们必须确保没有性能回退。初始实现在MotionMark中表现中性。我们需要通过测试来实现这些功能并同步测量性能,因此决定为MotionMark新增一组测试 (https://commits.webkit.org/311061@main),通过扩展现有测试来要求合成,确保滤镜、遮罩、路径裁剪、变换等功能均由合成器处理。 ## 滤镜 我们首先尝试仿照TextureMapper使用中间表面实现滤镜。虽然可行,但MotionMark中滤镜测试的分数大幅下降。我们发现使用Skia时,除模糊和投影外的大多数滤镜无需中间表面即可实现。这些滤镜类型均可简化为通过`SkImageFilter::asAColorFilter()`实现的`SkColorFilter`,只需在传递给`SkCanvas::drawImageRect()`的`SkPaint`中设置颜色滤镜即可完成。这不仅解决了性能回退问题,甚至比始终需要中间表面的TextureMapper取得了更好效果。 ## 遮罩 遮罩分为两类:源遮罩本身已是图像的图像遮罩,以及由路径表示的裁剪路径遮罩。在TextureMapper中,两者均通过中间表面实现:将遮罩绘制到表面,然后被遮罩的图层创建中间表面先绘制内容,再使用`DstIn`混合模式绘制遮罩。Skia的API允许我们以更简洁高效的方式实现这两种情况。对于图像遮罩,我们一次性绘制遮罩内容并缓存,然后被遮罩的图层为图像遮罩创建`SkShader`,通过`SkCanvas::clipShader()`传递,无需绘制到中间表面。裁剪路径遮罩更为简单,我们直接获取路径并构建`SkPath`传递给`SkCanvas::clipPath()`,完全无需将遮罩绘制为图像或使用任何中间表面。再次证明,遮罩不仅更易实现,性能也更优。 (图表描述:MotionMark合成套件十个子项的分组柱状图,对比TextureMapper与Skia合成器。滤镜、裁剪和遮罩测试在Skia下快3-4倍;三个叶子测试慢约20%。来源:https://blogs.igalia.com/carlosgc/files/2026/09/[email protected]) ## 3D上下文 3D图层上下文的实现与TextureMapper和OpenGL相对独立,因此我们几乎直接沿用原逻辑,使用`SkPath`构建裁剪并做少量调整。同时修复了TextureMapper中长期存在的Z轴排序错误 (https://commits.webkit.org/318066@main)。 (图表描述:同一页面并排截图。TextureMapper下红色方块平置于3D旋转的绿色平面上;Skia合成器下方块更高,被平面切割:左侧边缘露出一条,中部被遮挡,右侧部分绘制在平面之前。来源:https://blogs.igalia.com/carlosgc/files/2026/09/[email protected]) ## 混合模式 TextureMapper从未支持混合模式,而使用Skia仅需通过`SkPaint`属性 (https://commits.webkit.org/311943@main) 即可轻松实现,这使得多个布局测试得以通过。 ## 批量绘制 实现所有功能后,我们在除三个MotionMark合成测试外的所有测试中达到与TextureMapper持平或更优的性能。这些测试使用小图层并产生高分数,意味着我们在开始跳帧前向场景添加了大量图层。根本原因是大量图层填充了Ganesh的命令队列。Skia Ganesh会排队GL绘图操作而非立即发送至GPU。当表面因任意原因刷新时,排队的GL绘图操作将被处理并发送至GPU。这使Skia能应用优化,如合并多个任务并减少实际发送给GPU的绘图操作数量。在那些创建并绘制大量图层到合成器Skia表面的测试中,内部命令队列最终变得非常庞大。分析如此长的队列以优化发送至GPU的内容,其CPU开销甚至超过了优化GL绘图操作节省的开销。 Skia提供了允许我们自行批量处理的API (https://commits.webkit.org/314626@main)。由于合成器已有信息判断哪些操作可合并,我们能在许多情况下减小内部队列规模。只要共享相同颜色滤镜、混合模式和采样选项,便可合并`SkCanvas::drawImageRect()`操作。在最佳情况下,整个内部队列可缩减为单个操作。此次改进使这些测试的分数提升至TextureMapper的93%左右,但仍略逊一筹。 ## Promise图像 Skia Ganesh后端要求为当前线程`GrDirectContext`创建由纹理支持的`SkImage`,即使借用现有纹理也是如此。在WebKit中,所有纹理均通过共享GL上下文创建,以便不同线程可通过相同共享GL上下文访问和销毁。因此,对于内容为图像的图层,若图像未加速,需在合成线程创建纹理上传像素;若图像已加速,则需获取图像的纹理标识符,然后在合成线程创建另一个借用当前`GrDirectContext`纹理的`SkImage`。 Skia Ganesh后端提供创建promise图像的API (https://commits.webkit.org/315529@main),可从任意线程创建但绑定至特定线程,并提供一个回调函数,该函数将在目标线程首次使用`SkImage`以获取封装纹理时调用。这样我们可以在主线程为合成线程创建`SkImage`,创建时无需使用OpenGL。对于非加速图像,我们意识到无需在合成器中手动创建纹理和上传像素,只需将非加速`SkImage`传递给合成器`SkCanvas`,Skia会以远优于我们的方式内部高效处理。此更改对合成测试的提升远超预期,原因在于前一节的批量处理:Skia通过比较纹理代理指针合并图像集条目,而此前我们每帧为每个图层都用新`SkImage`包装纹理,导致绘制相同图像的数百个图层产生数百个无法合并的不同代理。每次传递相同的`SkImage`可将其折叠为单个绘图操作——即上文所述的最佳情况。通过结合批量绘制与promise图像,我们显著超越了TextureMapper。 (图表描述:按WebKit修订版显示的MotionMark叶子子测试折线图。三项均在修订版314626(批量绘制引入)和315529(promise图像引入)时急剧上升。来源:https://blogs.igalia.com/carlosgc/files/2026/09/[email protected]) ## 延迟显示列表(DDL) 切换到Skia进行绘制时,我们保留了多线程渲染模型,仅为GPU渲染工作者使用单独的小队列。GPU工作者创建自己的`GrDirectContext`绘制图层平铺。生成的纹理在合成线程通过fence进行适当同步后,重新包装用于合成器`GrDirectContext`。我们知道这不是多线程使用Skia Ganesh的推荐方式,但在TextureMapper下别无选择。然而,使用Skia合成器时,我们可采用推荐方式:在合成线程使用单个`GrDirectContext`,并利用延迟显示列表(DDL)和promise图像绘制平铺 (https://commits.webkit.org/315027@main)。 使用DDL后,GPU工作者完全不再使用GL,也无需`GrDirectContext`,他们将图层平铺绘制到记录GL绘图操作但不接触GL的显示列表中。对于记录到DDL的图像绘图操作,也使用promise图像。由于这些均为CPU操作,我们可移除小规模GPU工作者队列,改用单个更大规模的工作者队列。合成器将DDL重放至`SkSurface`,随后传递给合成器`SkCanvas`。 此更改修复了Android上的渲染故障,对整个合成套件和大多数MotionMark测试性能保持中性,但在15fps的MotionMark 1.3中,Suits测试下降29%,Leaves测试下降14%,Images测试提升9%。正确性与其他DDL优势使我们接受了这些回退。 (图表描述:MotionMark suits得分随WebKit修订版变化的折线图。启用延迟显示列表时分数从约470降至约335,禁用时恢复至470,再次启用时再次下降并保持。来源:https://blogs.igalia.com/carlosgc/files/2026/09/[email protected]) ## 损坏信息 TextureMapper已支持使用损坏信息优化合成时的绘制,但运行时始终禁用,因存在未解决的问题。在Skia合成器中,我们决定从头开始,在合成时正确处理损坏信息,仅渲染实际变化的帧部分。此处不展开细节,Nikolas Zimmermann (https://blogs.igalia.com/nzimmermann) 已撰写了精彩博文 (https://blogs.igalia.com/nzimmermann/posts/2026-09-21-skia-compositor-damaging/) 详述。 ## 当前状态 Skia合成器已完成并在2.54中默认启用 (https://commits.webkit.org/313297@main)。尽管非主要目标,其在大多数基准测试中性能优于TextureMapper:新增的合成套件快45%,MotionMark 1.3.1快35%。例外是15fps下GPU渲染的MotionMark 1.3,因上述延迟显示列表权衡,Suits和Leaves测试仍落后约26%和10%。 我们已开始修复TextureMapper中从未解决的现有合成问题。在主分支中,TextureMapper现已在构建时默认禁用 (https://commits.webkit.org/320146@main),且对GTK和WPE移植版的支持将很快移除。在2.54中仍为运行时决策,若发现问题,可通过环境变量`WEBKIT_USE_SKIA_FOR_COMPOSITION=0`尝试TextureMapper,以判断是否为Skia合成器回退。 (图表描述:今日基准测试总分相对于TextureMapper基线的柱状图。合成套件在GPU渲染下领先45%,MotionMark 1.3.1领先35%,MotionMark 1.3在15fps GPU渲染下持平,CPU渲染下领先10%。来源:https://blogs.igalia.com/carlosgc/files/2026/09/[email protected]) (图表描述:MotionMark 1.3在15fps下子测试从TextureMapper基线到今日的变化柱状图。GPU渲染下Suits落后26%,Leaves落后10%;CPU渲染下两者均大幅领先;其余子测试持平或领先。来源:https://blogs.igalia.com/carlosgc/files/2026/09/[email protected]) ## 未来计划 我们已着手进一步改进,如使用pr

相似文章

通过Skia进行绘制的编译器风格优化

Hacker News Top

本文介绍了μSkia,一种用于Skia 2D图形库的形式语义,并开发了一个优化器,在来自顶级网站的真实Skia程序中实现了18.7%的加速,使用Lean进行了验证。

《我的世界》中的 Wayland 合成器

Hacker News Top

一个在《我的世界》中实现完整 Wayland 合成器的模组,允许用户在游戏内启动和管理 Firefox、GIMP、VLC 等窗口。仅限 Linux。

Comfy-Org/Qwen-Image-2.1

Hugging Face Models Trending

为 ComfyUI 工作流程优化的 Qwen-Image-2.1 重打包模型文件,支持文本生成图像和图像编辑功能。