简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .
若是想要更好的理解 Wayland
架构及其与 X (X11 or X Window System)
结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。
这就是我们现在对 X
的理解。
如上所述,这种方法都有瑕疵。X服务器没有信息来决定哪个窗口应该接收事件,也不能将屏幕坐标转换为窗口局部坐标。而且即使X已经把最终绘制屏幕的责任交给了合成管理器,X仍然控制着前面的缓冲区和模式设置。过去X服务器处理的大部分复杂问题,现在都可以在内核或自带的库中找到(KMS、evdev、mesa、fontconfig、freetype、cairo、Qt等)。总的来说,X服务器现在只是一个中间人,在应用程序和合成器之间多引入了一步,在合成器和硬件之间多引入了一步。
在wayland中,合成器就是显示服务器。我们把KMS和evdev的控制权转移到合成器上。wayland协议让合成器直接向客户端发送输入事件,让客户端直接向合成器发送损坏事件。
在上面的概述中,有漏掉了一个细节,那就是客户端在wayland下究竟是如何渲染的。通过将X服务器从画面中移除,我们也移除了X客户端通常的渲染机制。但是我们在X下的DRI2已经使用了另一种机制:直接渲染。通过直接渲染,客户端和服务器共享一个视频内存缓冲区。客户端链接到一个渲染库,比如OpenGL,它知道如何对硬件进行编程,并直接渲染到缓冲区。而合成器则可以在合成桌面时,将缓冲区作为纹理使用。在初始设置之后,客户端只需要告诉合成器使用哪个缓冲区,以及何时何地的将新内容渲染到缓冲区中。
这就给应用程序留下了两种更新窗口内容的方法:
无论在哪种情况下,应用程序都必须告诉合成器表面的哪个区域存放新内容。当应用程序直接渲染到共享缓冲区时,需要注意到合成器有新内容。但在交换缓冲区时,合成器也不会认为有什么变化,只有需要应用程序提出请求才会重新绘制桌面。即使应用程序传递给合成器一个新的缓冲区,也可能只有一小部分缓冲区是不同的,比如一个闪烁的光标或一个旋转器。
通常情况下,硬件启用包括 modesetting / display 和 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的服务器端是垂直领域的合成器和核心用户体验,典型的是将任务切换器、应用启动器、锁屏整合在一个单体应用中。服务器运行在模式设置 API(内核模式设置、OpenWF Display或类似)之上,并使 EGL / GLES2 合成器和硬件覆盖(如果有的话)混合合成最终的UI。启用模式设置、EGL/GLES2和覆盖是标准硬件启动的一部分。启用Wayland的额外要求是EGL_WL_bind_wayland_display扩展,它允许合成器从通用Wayland共享缓冲区创建EGLImage。它类似于EGL_KHR_image_pixmap扩展,可从X像素图创建EGLImage。
该扩展有一个设置步骤,您必须将EGL显示与Wayland显示绑定。然后当合成器从客户端接收通用的Wayland缓冲区时(通常在客户端调用eglSwapBuffers时),它将能够将结构wl_buffer指针传递给eglCreateImageKHR作为EGLClientBuffer参数,并以EGL_WAYLAND_BUFFER_WL作为目标。这将创建一个EGLImage,它可以被合成器用作纹理,或传递给模式设置代码作为覆盖平面使用。同样这是由厂商特定的协议扩展来实现的,在服务器端,它将接收驱动程序关于共享缓冲区的具体细节,并在用户调用eglCreateImageKHR时将其转化为EGL图像。