Graphics Stack总结(一)Linux Graphics Stack简介
在工作的过程中逐渐有了总结一下当前Gfx技术栈的想法,方便自己对Linux Gfx的整体结构有更好的理解。
总的来说,这一些列文章大部分会翻译自https://blogs.igalia.com/itoral/,这是在查资料的过程中发现的一个老哥的博客,其中对Linux Graphics的理解写的很好。中间根据我的理解会插入一些知识点的补充。
本篇文章会对Linux Graphics技术栈做一个简短的介绍,将着重于提供足够的背景知识来理解Mesa和3D驱动程序在技术栈的作用,以便后续文章中深入了解Mesa和Intel DRI驱动程序的本质。
一点历史
为了理解当前Graphics技术栈的一些特性,理解Graphics技术是如何变化以适应这些年不断变化的需求和挑战是非常重要的。
正如你所知,现在的Graphics技术比过去要复杂得多,在早期只有一种软件可以直接访问图形硬件:X server。这种方法简化了Graphics Stack,因为它不需要在多个客户端之间同步对Graphics hardware的访问。
在早期,Application将通过X server间接完成所有绘图。通过使用Xlib,他们将通过X11协议发送渲染命令,X server将接收、处理并转换为套接字另一侧的实际硬件命令。请注意,此“转换”是driver的工作:它将一组与硬件无关的渲染命令作为输入,并按照目标GPU的预期将其转换为硬件命令。
由于X server是设计中唯一可以与Graphics hardware通信的软件,因此这些driver是专门为其编写的,成为X server本身的模块和其体系结构的一个组成部分。这些user space driver在X server argot中称为DDX driver,它们在Graphics Stack中的作用是支持Xlib导出的2D操作以及X server实现所需的2D操作。
例如在我的ubuntu系统中,Intel GPU的DDX driver就来自xserver-xorg-video-intel package,对于其他GPU厂商来说也有类似的package.
3D Graphics
上述内容涵盖了2D Graphics,因为这正是X server过去的全部内容。然而,3D Graphics hardware的到来极大地改变了场景,我们现在将看到这一点。
在Linux中,3D Gpraphics是通过OpenGL实现的,因此人们希望该标准的实现能够充分利用3D Graphics hardware,即硬件加速(hardware accelerated)的libGL.so. 然而在一个只允许X server访问Graphics hardware的系统中,我们不能使用libGL.so直接与3D硬件进行沟通。相反,解决方案是提供一个OpenGL实现,它通过X11协议的扩展将OpenGL命令发送到X server,并让X server将这些命令转换为实际的硬件命令,就像之前对2D命令所做的那样。
我们把上述过程叫做间接渲染(Indirect Rendering),因为application没有直接把渲染命令发给graphics hardware,而是通过X server间接渲染。
不幸的是,开发人员很快就会意识到,这种解决方案不足以满足密集型3D application(如游戏)的需要,这些应用程序需要在保持高速率的同时渲染大量3D图形。问题很明显:在X11协议中包装OpenGL调用不是有效的解决方案。
为了在3D application中获得良好的性能,我们需要这些程序来直接访问hardware,这需要重新考虑大块的Graphics Stack。
Enter Direct Rendering Infrastructure (DRI)
Direct Rendering Infrastructure(DRI)是一种新的体系结构,它允许X client直接与Graphics hardware对话。实现DRI需要对Graphics stack的各个部分进行更改,包括X server、kernel 和各种client lib。
尽管术语DRI通常指的是完整的体系结构,但它通常也仅指中涉及application与X server交互的特定部分,因此在网上查阅相关资料时,尤其需要注意这一双重含义。即下图中的OpenGL DRI driver, 负责与OpenGL application直接交互,也可以与X server交互。
DRI的另一个重要部分是Direct Rendering Manager(DRM)。这是DRI体系结构中的kernel side。在这里,kernel处理诸如硬件锁定、访问同步、视频内存等方面。DRM还为用户空间提供了一个API,可用于以适合现代GPU的格式提交命令和数据,从而有效地允许user space与graphics hardware通信。
需要注意的时,许多操作都必须专门针对target hardware(目标硬件)进行,因此每个GPU都有不同的DRM驱动程序。在我的Ubuntu系统中,英特尔GPU的DRM模块是通过libdrm-intel1:amd64包提供的。
DRI/DRM提供了使user space application能够以高效和安全的方式直接访问图形硬件的构建块(building blocks),但为了使用OpenGL,我们还需要另一个software,该软件使用DRI/DRM提供的基础设施,在满足X服务器要求的同时实现OpenGL API。
Enter Mesa
Mesa是OpenGL规范的自由软件实现,它提供了一个libGL.so,使得Linux中基于OpenGL的application可以用libGL.so来输出3D图形。Mesa可以在其OpenGL API的实现(Implementation)中,利用DRI架构获取对底层Graphics hardware的直接访问,从而提供3D硬件加速。
当我们的3D应用程序在X11环境中运行时,它会将其图形输出到X server分配的surface(window)。但是,请注意,对于DRI,这将在没有X服务器干预的情况下发生,因此在这两者之间自然要进行一些同步,因为X server仍然拥有Mesa正在渲染的窗口,并且是负责在屏幕上显示其内容的窗口。OpenGL应用程序和X server之间的同步是DRI的一部分。Mesa对GLX的实现(针对X11平台的OpenGL规范的扩展)使用DRI与X server对话并完成此任务。
Mesa还必须在许多方面使用DRM。与Graphics hardware通信是通过发送命令(例如“绘制三角形”)和数据(例如三角形的顶点坐标、其颜色属性、法线等)实现的。这个过程通常涉及在图形硬件中分配一组buffer,在这些buffer中复制所有这些命令和数据,以便GPU可以访问它们并执行其工作。这是由DRM驱动程序实现的,DRM驱动程序负责管理视频内存,并向user space(本例中为Mesa)提供API,以便为特定的目标硬件执行此操作。当我们需要在Mesa中分配和管理视频内存时,也需要DRM,因此创建纹理、将数据上载到纹理、分配颜色、深度或模具缓冲区等都需要为目标硬件使用DRM API。
What’s next?
本篇解释了Mesa在Linux图形堆栈中的作用,以及它如何与DRI协同工作,通过OpenGL实现高效的3D Graphics。在下一篇文章中,我们将更详细地介绍Mesa,我们将看到它实际上是一个多个OpenGL驱动程序共存的框架,包括多种hardware和software,我们还将查看其目录结构并确定其主要模块,介绍Gallium框架等