Wayland架构 即第三章内容 -官网翻译

文章目录

  • Wayland 体系构架
  • Wayland 渲染
  • Wayland 硬件支持
  • 说明

Wayland 体系构架

了解 Wayland 架构,以及它与 X((X11 or X Window System)) 有何不同之处的一个好方法是跟踪其完整的事件流程:事件从设备输入、到变化(受该事件影响的点)最终展现在屏幕上的整个过程。

下面是目前X的流程:
Wayland架构 即第三章内容 -官网翻译_第1张图片

  • 1、内核从输入设备中获取到一个事件,并通过evdev输入驱动发送至X。内核通过驱动设备来完成硬件部分的工作,并且将遵循不同协议的硬件事件转换为linux evdev输入事件标准。
  • 2、X 服务器确定事件影响哪个窗口,并将其发送到在该窗口上的选择了相关事件的客户端。实际上X 服务器并不知道如何正确执行此操作,因为屏幕上的窗口位置由合成器控制,并且可能以 X 服务器无法理解的多种方式进行转换(缩小、旋转、摆动等等)。
  • 3、客户端查看事件并决定要做什么。通常,UI 必须响应事件而更改 - 可能是单击了复选框,或指针进入了按钮而需要突出显示。因此,客户端将渲染请求发送回 X 服务器。
  • 4、当 X 服务器收到渲染请求时,会将该请求发送给驱动程序以驱动硬件来完成渲染工作。 X 服务器还需要计算渲染的边界区域,并将其作为损坏事件发送给合成器。
  • 5、损坏事件告诉合成器窗口中的某些内容发生了变化,并且它必须重新合成该窗口可见的屏幕部分。 合成器负责根据其场景图和 X 窗口的内容渲染整个屏幕内容。 并且它必须通过 X 服务器来渲染它。
  • 6、X 服务器接收来自合成器的渲染请求,并将合成器后台缓冲区复制到前台缓冲区或执行翻页。 在一般情况下,X 服务器必须执行此步骤,以便它可以计算重叠窗口,这可能需要裁剪并确定它是否可以翻页。 但是,对于始终全屏显示的合成器,这是另一个不必要的上下文切换。

如上所述,这种方法存在一些问题。 X 服务器没有信息来决定哪个窗口应该接收事件,也不能将屏幕坐标转换为窗口本地坐标。即使 X 已将屏幕最终绘制的责任交给合成管理器,但 X 仍控制前端缓冲区和modesetting。 X 服务器过去处理的大部分复杂性工作现在都可以在内核或自包含库(KMS、evdev、mesa、fontconfig、freetype、cairo、Qt 等)中方便的找到。总的来说,X 服务器现在只是一个中间人,它在应用程序和合成器之间引入了一个额外的步骤,在合成器和硬件之间引入了一个额外的步骤。

在wayland 中,合成器是显示服务器。我们将 KMS 和 evdev 的控制权交给了合成器。 wayland 协议让合成器直接将输入事件发送给客户端,让客户端直接将损坏事件发送给合成器,下面是Wayland的处理流程:
Wayland架构 即第三章内容 -官网翻译_第2张图片

  • 1、内核获取一个事件并将其发送到合成器。这类似于 X 的情况很好,因为我们可以重用内核中的所有输入驱动程序。
  • 2、合成器查看其场景图以确定接收事件的窗口。场景图形对应于屏幕上的内容,合成器理解可能应用于场景图形中元素的坐标转换。因此,合成器可以选择正确的窗口,并通过应用逆变换将屏幕坐标转换为窗口局部坐标。只要合成器可以计算输入事件的逆变换,那么它就可以执行这类可应用于窗口的变换操作。
  • 3、在 X 的情况下,当客户端收到事件时,它会更新 UI 作为响应。但在wayland 的情况下,渲染发生在客户端,客户端只是向合成器发送请求以指示需要更新的区域。
  • 4、合成器从其客户端收集损坏请求,然后重新合成屏幕。接下来,合成器可以直接发通过ioctl 来调度KMS 完成翻页。

Wayland 渲染

我在上面的概述中遗漏的细节之一是客户端如何在 wayland 下实现渲染。通过从图片中删除 X 服务器,我们也删除了 X 客户端通常使用的机制。但是存在另外一种我们已经使用的渲染机制,即我们已经在 X 下使用 DRI2 :直接渲染。直接渲染机制中,客户端和服务器共享一个视频内存缓冲区。客户端链接到一个渲染库,例如 OpenGL,它知道如何对硬件进行编程并直接渲染到缓冲区中。反过来合成器可以获取缓冲区并将其用作合成桌面时的纹理。在初始设置之后,客户端只需要告诉合成器使用哪个缓冲区以及它在何时何地将新内容渲染到其中。

这给应用程序留下了两种更新其窗口内容的方法:

  • 1、将新内容渲染到新缓冲区中,并告诉合成器使用新缓冲区而不是旧缓冲区。应用程序可以在每次需要更新窗口内容时分配一个新缓冲区,或者它可以保留两个(或更多)缓冲区并在它们之间循环使用。缓冲区完全在应用程序控制之下。(即环形缓冲区或者双缓冲机制)
  • 2、将新内容渲染到它之前被合成器使用过的缓冲区中。虽然可以直接渲染到缓冲区(与合成器共享的)中,但这可能会与合成器竞争。可能发生的情况是,客户端重新绘制窗口内容的过程中可能会被合成器重新绘制桌面的动作所中断。如果应用程序在清除窗口之后,但在渲染内容之前被中断,合成器将从空白缓冲区进行纹理化。结果是应用程序窗口将在空白窗口或半渲染内容之间闪烁。避免这种情况的传统方法是将新内容渲染到后台缓冲区中,然后从那里复制到合成器表面。后台缓冲区可以动态分配,大小刚好足以容纳新内容,或者应用程序可以保留一个缓冲区。同样,这在应用程序控制之下。

在任何一种情况下,应用程序都必须告诉合成器在表面的哪个区域中包含了新内容。当应用程序直接渲染到共享缓冲区时,需要通知合成器有新的渲染内容。同样在交换缓冲区时,合成器不会假设任何更改。在重新绘制桌面之前,合成器也需要来自应用程序的请求,即使应用程序传递给合成器的新缓冲区只有一小部区域内容可能不同,例如闪烁的光标或微调器。

Wayland 硬件支持

通常,硬件启用包括模式modesetting/显示和 EGL/GLES2。最重要的是,Wayland 需要一种在进程之间有效共享缓冲区的方法。可以从两个方面保证上述工作:客户端和服务器端。

在客户端,我们定义了一个 Wayland EGL 平台。在 EGL 模型中,它由本机类型(EGLNativeDisplayType、EGLNativeWindowType 和 EGLNativePixmapType)和创建这些类型的方法组成。换句话说,胶水代码是用于将 EGL 堆栈及其缓冲区共享机制绑定到通用 Wayland API 的。 EGL 堆栈被用于提供 Wayland EGL 平台的实现。完整的 API 位于 wayland-egl.h 头文件中。 mesa EGL 堆栈中的开源实现位于 platform_wayland.c 中。

在幕后,EGL 堆栈需要定义基于特定供应商的协议扩展,允许客户端 EGL 堆栈与合成器交换缓冲区详细信息以达到共享缓冲区的目的。 wayland-egl.h API 的重点是将其抽象出来,让客户端为 Wayland 表面创建一个 EGLSurface 并开始渲染。开源堆栈使用 drm Wayland 扩展,它允许客户端发现待使用和验证的 drm 设备,然后与合成器共享 drm (GEM) 缓冲区。

在服务器端,Wayland 由合成器和具备极致用户体验(UX)的单一程序组成,包含了典型的任务切换器、应用程序启动器、锁屏功能。服务器在运行在 模式设置(modesetting) API(kernel modesetting、OpenWF display or similar)之上,并混合使用 EGL/GLES2 合成器和可用的硬件重叠(overlay)机制来合成最终 UI。模式设置启用、EGL/GLES2 和重叠应该是标准硬件启动的一部分。 Wayland 启用的额外要求是 EGL_WL_bind_wayland_display 扩展,它允许合成器从通用 Wayland 共享缓冲区创建 EGLImage。它类似于从 X 像素图创建 EGLImage 的 EGL_KHR_image_pixmap 扩展。

该扩展有一个设置步骤,您必须将 EGL 显示绑定到 Wayland 显示。然后,当合成器从客户端接收通用 Wayland 缓冲区时(通常是在客户端调用 eglSwapBuffers 时),它将能够将 struct wl_buffer 指针作为 EGLClientBuffer 参数传递给 eglCreateImageKHR,并以 EGL_WAYLAND_BUFFER_WL 作为目标。这将创建一个 EGLImage,然后合成器可以将其用作纹理或传递给模式设置代码以用作覆盖平面。同样,这是由供应商特定协议扩展实现的,服务器端将接收有关共享缓冲区的驱动程序特定详细信息,并在用户调用 eglCreateImageKHR 时将其转换为 EGL 图像。

说明

  • 文章翻译来源:wayland architecture;
  • 参考:https://xmuli.blog.csdn.net/article/details/107219047;
  • 谷歌翻译是个好东西,功能越来越强大,少敲了不少字;
  • 本章内容也是其document的第三章内容。

你可能感兴趣的:(wayland,wayland,gpu)