天天看点

Linux Graphics 周刊(第 4 期)

(2020.08.31 ~ 2020.09.06)

导读
  • LPC2020: Linux kernel 添加 Rust 支持
  • LPC2020: 只需要一笔 Patch,Android AOSP 就可以在 kernel-5.9 主线上运行
  • drm/prime: sg_table nents 漏洞修复
  • drm/vc4: 为树莓派4添加 Display 驱动
  • RenderEngine: bugfix for alpha blending func
  • MESA 发布 20.2.0-rc4
  • ACO:为 AMD ACO Back-End 添加详细的说明文档
  • Weston 9.0.0 发布
  • Collabora: 使用 Perfetto 抓取 Panfrost performance counters 信息
  • GPU 压缩纹理格式详解

一、Linux

1. LPC2020: Linux kernel 添加 Rust 支持

之前曾在我的星球中报道过关于《Linux kernel 是否要支持 Rust 语言?》 以及《Linus Torvalds 首次回应对 kernel 添加 Rust 的看法》的消息,而上周在线上举办的 Linux Plumbers Conference 2020 则更进一步的讨论了这一话题。

回顾之前关于 kernel 支持 rust 的消息,Rust 语言由 Mozilla 开发,最早发布于 2014 年 9 月。该语言最大的特点没有垃圾回收,能够确保内存安全和线程安全,它的长远目标是取代 C 语言。Google 工程师 Nick Desaulniers (因向内核添加 LLVM Clang 支持而闻名)曾在7月份向内核社区发送邮件讨论过该话题,并一度引起社区开发者的高度关注。而且很快,Linus 也回应了针对该话题的个人看法,首先他并没有直接否定该想法,反而是提倡在默认情况下应该开启该 feature,以确保该 feature 能被更充分的测试。当然该 feature 最好做成自适应的,如果在系统上检测到了 Rust 编译器,那么 Kconfig 就可以启用 Rust 支持,并构建用 Rust 编写的内核代码。

而本次 LPC 2020 大会上,Nick 则更进一步讨论了该话题的实现方案。首先他声明添加 Rust 的目的不是为了重写那 2500 万行 kernel 代码,C 语言仍然是内核代码的第一实现语言,而 Rust 只是用于后续新功能添加的代码,尤其是那些特变关注内存安全、多并发性问题的代码,以及那些更适合使用 Rust 来实现的技术领域。除此之外,他们还讨论了是否应该使用 Rust’s Cargo 来作为 Kbuild/Kconfig 中的构建工具,以及如何使用 Cargo 的离线模式来确保所有的 Rust 代码都在 kernel in-tree 中维护(因为 Cargo 默认是从外部仓库来拉取代码的)。该话题最终并没有给出一个明确的结论,而这仅仅只是一个开放式的线上讨论会,而且讨论并没有结束,该话题会在内核邮件列表中持续讨论下去。

如下 Github 为一个 Rust 版的 kernel module 实现,感兴趣的同学可以参考一下:

https://rust-for-linux.github.io/

LPC 2020 大会关于 Rust 讨论的 PPT 文档:

Barriers to in-tree Rust

更多详细内容:

  1. Supporting Linux kernel development in Rust
  2. Linux Developers Continue Evaluating The Path To Adding Rust Code To The Kernel

2. drm/prime: sg_table nents 漏洞修复

Marek Szyprowski (Samsung) 早前在重构 Exynos DRM GEM 代码时,就发现了 DRM Framework 中普遍存在的一个高风险漏洞,无论是 drm prime API 还是 Vendor 厂商自己实现的 prime 代码,都错误的使用了 sg_table 中的 nents 变量,这可能会引起 DMA 内存访问异常。

首先,DMA-Mapping 文档中有明确说明,dma_map_sg() 函数返回的 nents 值有可能会比传进去的 origin_nents 参数值小,而后续使用 dma_sync_sg_for_() 以及 dma_unmap_sg() 时,应该使用 origin_nents 作为参数。因为某些情况下,物理连续的 page 会被聚合成一个 nents,这样新生成的 nents 值就会比原始的 nents 值小。但 Marek 发现,在 DRM 驱动代码中,大家都清一色的使用 sg_table->nents 来作为 dma_sync_sg_for_() 和 dma_unmap_sg() 参数使用,而且最关键的是,这种错误的用法在大多数情况下都没有发生什么异常!正确的使用方法应该是使用 sg_table->origin_nents 作为参数来调用 dma_sync_sg_for_*() 和 dma_unmap_sg() 函数。

为此,它提交了一组长达32笔 patch 的提交,用于修改 drm prime 框架和 Vendor 厂商对 sg_table->nents 引用的代码,以确保程序的健壮性。该 patch 目前已经进行到第9轮 review 阶段,看起来已经很有希望在9月底合入 drm-misc next 分支。

详情:[PATCH v9 00/32] DRM: fix struct sg_table nents vs. orig_nents misuse

3. drm/vkms: 一个 gamma_set 接口引发的讨论

Sidong.Yang 向社区提交了一笔 patch,用于在 vkms 驱动的 vkms_crtc_funcs 中添加 gamma_set 回调接口,并且采用 drm_atomic_helper_legacy_gamma_set() 函数来实现。他提交该 patch 的理由是:现有的 vkms 驱动不支持 gamma 操作,这会导致 IGT 测试中的 kms_plane (pixel-format-pipe-A-plan) 测试项 fail,因为该测试 case 中调用了 drmModeCrtcSetGamma() 函数。

而 Simon Ser 则认为这样的 patch 显然不合理:首先,这应该是 IGT 测试 case 的问题,而不应该是 vkms 驱动的问题,因为 vkms 驱动本身不支持 gamma 操作,那么上层测试程序就不应对该驱动发起 gamma 调用的操作。其次,该 patch 给 vkms 添加了支持 gamma 的能力,但是却没有在任何地方使用上层传下来的 gamma 参数,这就没什么意义。

经过一番讨论后,最终的结论是:IGT 测试 case 添加 gamma 操作的目的其实并非真正想要执行 gamma 相关操作,而是为了方便 C8 格式的 CRC 校验处理字节序的问题而使用了 gamma LUT 这段内存。所以应该针对 C8 格式的 plane 单独设置一个 test case,这样就可以将多余的 gamma LUT 删掉了。

详情:[PATCH] drm/vkms: add support for gamma_set interface

4. drm/i915: 优化 DisplayPort DFP 的处理

Ville Syrjala (Intel) 正在为 Intel 915 DisplayPort 驱动优化 DFP (Downstream Facing Port) 的处理流程。为了让 DFP 的处理过程更加顺畅,Ville 为 drm/dp 框架新增了如下 feature:

  • 添加 DP 1.3 & 1.4 新增寄存器的宏定义
  • 完善 DPCD DFP capabilities
  • 添加 helper 函数用于判断当前 downstream facing port 的类型
  • 添加 helper 函数用于获取 TMDS clock 的能力限制
  • 添加

    drm_dp_downstream_mode()

    函数用于根据 DPCD 来获取当前 sink 所支持的 display mode
  • 添加 helper 函数用于处理 DFP YCbCr 4:2:0 格式

详情:[PATCH v2 00/18] drm/i915: Pimp DP DFP handling

5. drm/vc4: 为树莓派4添加 Display 驱动

  • 树莓派4:开源开发板,采用博通BCM2711 SoC,CPU 4核64bit Cotex-A72,GPU 采用博通自研 VideoCore VI,支持 OpenGLES 3.x。
  • VC4: 博通 GPU VideoCore IV 驱动在 drm 和 mesa 中的名字(罗马数字 IV 是 4 的意思)
  • V3D: 博通 GPU VideoCore VI 驱动在 drm 和 mesa 中的名字(罗马数字 VI 是 6 的意思)

目前 broadcom 在 drm 目录下存放着 vc4 和 v3d 两个目录,vc4 既包含 Display 驱动也包含 GPU 驱动,主要用于树莓派3及之前的 SoC;而 v3d 则只包含 gpu 驱动,专用于树莓派4。由于 vc4 和 v3d 的 Display 硬件差异不大,为了让树莓派4最大化利用 vc4 现有的 Display 驱动,Maxime Ripard (DRM-Misc Maintainer) 半年前就向社区提交了一组长达 80 笔 patch 的 VC4 KMS 提交,而上周已经更新到第5轮 review 了。这组 patch 除了对原来 VC4 KMS 相关代码的重构外,还新增了 HDMI 的支持,因为树莓派4 SoC 内部有2个 HDMI 控制器。同时 Maxime 还修复了一些 4K 显示以及双屏输出的 bug,如果没有什么大的问题,该 patch 有望合入 linux-5.10 主线。

详情:[PATCH v5 00/80] drm/vc4: Support BCM2711 Display Pipeline

二、AOSP

1. LPC2020: 只需要一笔 Patch,Android AOSP 就可以在 kernel-5.9 主线上运行

Satya Tangirala(Google)和 Sumit Semwal(kernel ION/DMA-BUF/Heap/dma-fence Maintainer,Linaro)在上周的 Linux Plumbers Conference 2020 线上大会上为大家介绍了 Android 在最新的 Linux Kernel 主线上的开发进展。他们宣称,只需要借助一笔 patch,Android AOSP master 分支就可以直接在 Linux-5.9 mainline 上运行了,当然前提是你的 SoC 驱动都已经 upstreaming 到 kernel-5.9 主线中了。而需要额外打上的那笔 patch 则其实是 Android kernel 由来已久的 “anonymous VMA naming support” patch,该 patch 的历史可以追溯到 2013 年,是 AOSP 启动所必须的 patch,一直都只在 Android 自己的 kernel 仓库中维护,从未进入过社区。

虽然 Google 声称只需要一笔 patch,但由于大部分的移动手机厂商(或芯片厂商)并没有将自己完整的 SoC 驱动都 Upstream 到内核主线中,实际上对于大多数的移动平台来说,它们需要的其实不只一笔 anonymous VMA patch。

更多详细内容:

  1. Android AOSP Can Boot Off Mainline Linux 5.9 With Just One Patch
  2. LPC2020 PPT:State of Android on Mainline kernels

2. RenderEngine: bugfix for alpha blending func

默认情况下,GPU 合成输出的 Alpha 为 Premultiplied,且为 Coverage blending mode。如果这时候再和其它 Device 的 layer 做合成,使用现有的 RenderEngine blend 函数,GPU 的 layer 将会直接覆盖 Device 的 layer,这是不正确的。

修改前的代码,当 alpha 为 premultiplied 时,GLES 后端使用的 blending 函数为 glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA),该函数对应的公式如下:

out.rgba = src.rgba * src.rgba + dst.rgba * (1 - src.rgba)

当 alpha 不为 premultiplied 时,则使用 glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_ALPHA),对应的公式如下:

out.rgba = dst.rgba * (1 - src.rgba)

这是不正确的,正确的 alpha blending 公式应该如下:

out.a = src.a + dst.a * (1 - src.a)

out.rgb = ((src.rgb * src.a + dst.rgb * dst.a * (1 - src.a)) / out.a

  • 当使用 coverage blend mode:

out.a = src.a + dst.a * (1 - src.a)

out.rgb * out.a = (src.rgb * src.a + dst.rgb * dst.a * (1 - src.a)

  • 当使用 premultiplied blend mode:

out.a = src.a + dst.a * (1 - src.a)

out.rgb = src.rgb + dst.rgb * (1 - src.a)

详情:aosp/native[master]: [RenderEngine] correct alpha blending func

3. ashmem: 为 ASharedMemory_create() 添加 CLOEXEC flag

熟悉 fork() 的同学都知道,当父进程 fork() 子进程后,子进程就继承了父进程所有的堆&栈数据,包括已 open 的 fd 资源。如果后续子进程通过调用 exec() 来执行新的可执行程序的话,新的可执行程序将会彻底覆盖原子进程的所有代码段和数据段,那么原来子进程中被打开的 fd 就无法被 close,于是出现 fd 泄露。为了防止这类问题的发生,可以事先在 open() 某个文件时传入

O_CLOEXEC

flag 来告诉该进程在执行 exec() 后就自动关闭之前已打开的 fd。

Android share memory 就存在这样的 fd 泄露风险,为此需要在执行 memfd_create() 时传入 MFD_CLOEXEC flag 来避免此类问题的发生。

详情:

  1. aosp/core[master]: ashmem: ensure ashmem fds are CLOEXEC.
  2. aosp/native[master]: Document that ASharedMemory_create fds may or may not be CLOEXEC

三、Mesa

1. MESA 发布 20.2.0-rc4

上周 Mesa 发布了 20.2.0-rc4 版本,同时也将是 20.2.0 的最后一个候选版本,Dylan Baker(Mesa 版本维护者,Intel)使用“pretty tame”来形容此次版本的发布。如果不出意外,下周应该可以正式 release Mesa-20.2.0 版本。

此次发布的 20.2.0-rc4 主要包含如下修改(Vendor修改不计算在内):

  • egl/x11_dri3: 实现了 EGL_KHR_swap_buffers_with_damage 接口
  • bugfix for OpenBSD
  • gallium/dri2: 修复了 YUYV & UYVY plane count 误报的问题
  • vulkan/wsi/x11: 添加 sent image counter
  • vulkan/wsi/x11: wait for acquirable images in FIFO mode
  • vulkan: 内存泄露 bugfix

详情:[ANNOUNCE] mesa 20.2.0-rc4

2. ACO:为 AMD ACO Back-End 添加详细的说明文档

ACO (AMD Compiler) 是 Valve 公司为 AMD GPU 的 Mesa 开源 Vulkan 驱动 “RADV” 专门开发的 Shader 编译器,旨在提供更快的编译速度,以及生成更适合游戏运行的优化代码。目前 RADV 使用 LLVM 作为 Shader 编译器后端,而在即将到来的 Mesa-20.2 中,ACO 将作为 RADV 的默认编译器后端而被使能。

9月1日,Mesa 社区合入了一份关于 ACO 的 README 文档,该文档详细描述了:

  • ACO 是什么?
  • 为什么要开发这个编译器?
  • 它的控制流程是怎样的?
  • 它的编译过程是如何工作的?
  • 它都支持哪些 Shader Stage?
  • 如何 debug?

该文档写的非常详细,可以作为 ACO 使用的参考手册。

详情:aco: Add README which explains about what ACO is and how it works

四、Wayland

Weston 9.0.0 发布

9月4日,Wayland 社区发布了 Weston 9.0.0 版本。Weston 作为 Wayland Compositor 的官方参考实现,旨在提供一个高效、逻辑清晰、功能简单的 Linux 参考桌面。此次版本发布主要包括如下内容:

  • 新增 Kiosk Shell,适用于只有单个 UI 进程的全屏显示需求
  • 优化了测试框架,新增 DRM 和 OpenGL 测试用例
  • 添加对 DRM panel orientation property 的支持
  • 其他 bugfix

详情:[ANNOUNCE] weston 9.0.0

五、其它

1. Collabora: 使用 Perfetto 抓取 Panfrost performance counters 信息

Perfetto 是 Google 去年新推出的一个开源性能分析工具,用于取代 systrace。它的功能远比 systrace 强大,抓取 trace 的时间更长,抓取的信息量更大,且提供了灵活的扩展接口,方便开发人员抓取自定义的数据信息。

目前的 Perfetto 虽然也可以抓取 GPU 的信息,但也只限于 GPU 的频率信息,如果想要抓取更多 GPU 相关信息,则只能通过 Perfetto 的扩展功能进行抓取。

gfx-pps (Graphics Performance Producers) 是由 Collabora 公司开发的一款专门搜集 Graphics 性能数据的 Perfetto 扩展插件,它作为 client 进程将搜集到的 Graphics 性能数据发送给 Perfetto trace service。它是开源的,遵循 MIT license,源码放在 freedesktop GitLab 上托管。目前 gfx-pps 主要搜集两种 data source:一种是 Mali GPU 的 Performance Counters 信息,另一种则是 Weston timeline 的 track events。

Collabora 官方专门发表了一篇关于 gfx-pps 的博客,并描述了如何使用 gfx-pps 以及如何分析抓取的 graphics 性能数据,感兴趣的同学请访问如下链接:

Panfrost performance counters with Perfetto

2. GPU 压缩纹理格式详解

如下两篇文章详细介绍了 GPU Compressed Texture Format 压缩原理及其解压方式,值得一看。

  1. Compressed GPU texture formats – a review and compute shader decoders – part 1
  2. Compressed GPU texture formats – a review and compute shader decoders – part 2