Mesa, also called? Mesa3D?and?? The Mesa 3D Graphics Library, is an?? open source?software implementation of?? OpenGL,? Vulkan, and other?? graphics?? API?specifications. Mesa translates these specifications to vendor-specific graphics hardware drivers.
Mesa 实际上是一个库,它实现了多种图形 API 规范,这其中就包括了最著名的 OpenGL。Mesa 底层直接使用图形硬件驱动。
Mesa implements a translation layer between a graphics API such as OpenGL and the graphics hardware drivers in the operating system kernel.
上面这句话基本上点到了 Mesa 的实质。Mesa 实际上就是一个转换层,它提供了图形 API(比如:OpenGL)到图形硬件(比如:显卡 GPU)驱动之间的一个转换。
它诞生之时,是在 CPU 上进行所有渲染的,后续又发展为通过 display server 非直接的渲染。但其内部架构在设计上支持使用显卡硬件 3D 渲染的。
可以说,在适配 DRI 架构时,正式奠定了 Mesa 的位置:
With adapting to DRI, the Mesa library finally took over the role of the front end component of a full scale OpenGL framework with varying backend components that could offer different degrees of 3D hardware support while not dropping the full software rendering capability.
Mesa (或Mesa3D)是一个 OpenGL/Vulkan 的实现,以及为所有开源图形驱动提供各种 GL 的入口点, 它是一个项目的名字。由它编译出来的库是下面这些:
或者这些文件:
其中需要注意的是这几个文件:libGL.so,libEGL.so,libGLESv2.so,根据名字很显然,他们分别实现了对应的API。
Mesa有两个作用:
作者:keyou
链接:https://juejin.cn/post/6844903841096269837
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
mesa解析1 线程本地存储 libGL.so原理_mesa libglapi.so-CSDN博客
TLS机制:
openGL维护了一个状态机,或者叫上下文;gl开头的api函数,如glUniform4fv,会修改这个上下文
系统中,如果有多个基于openGL的程序在运行,则每个程序有一个独立的上下文。每个程序调用gl api都作用于自己的上下文。
但是,libGL.so是一个共享库,每个基于openGL的程序都将其映射到自己的地址空间,共享库的代码段在系统运行期间是不变的。要同一份二进制程序,在不同程序中访问到各程序自己的gl上下文,线程本地存储(TLS / thread local storage)机制就是为了解决这个问题
每个线程有独立的地址空间,并且其中有一块用作线程本地存储(TLS)。操作系统在上下文切换时,会将TLS指针放进一个特殊的寄存器;共享库读取这个寄存器,就可以得到该线程的TLS指针,而上下文在TLS段中具体什么位置,是编译器决定的。
也就是说,约定所有程序的上下文指针都存在TLS段中特定位置,则libGL.so中读取TLS指针,加上特定偏移,就可以得到gl上下文
libGL.so基本原理
应用程序调用gl开头的函数,这些函数的定义都在libGL.so中
每个api函数的入口实现是统一的:读取TLS指针,从TLS段中读取分发表指针,从分发表中特定偏移处读取实际的实现函数的指针,通过这个函数指针进行调用
也就是说,libGL.so这个共享库是一个空壳,一个中介。在使用这个库提供的gl api函数之前,应用程序要先创建上下文和分发表,并将上下文和分发表的指针写进TLS中
上下文和分发表的定义在驱动中,如r600_dri.so,api函数的实际实现,也都在这个驱动中。
应用程序通过egl的接口,来创建gl上下文,设定上下文(将上下文和分发表注册到TLS中),之后,应用程序就可以调用libGL.so中的gl api函数了
细节上,上下文和分发表的注册功能,由libglapi.so完成,所以,libelg是调用libglapi.so中的函数,来设置上下文和分发表,libGL.so是调用libglapi.so中的函数(不过是内联调用),来获取分发表
egl以dlopen的方式,打开驱动,如r600_dri.so,从驱动中以dlsym的方式,获取驱动函数表,调用驱动函数,来创建上下文。
正向的说:egl以dlopen方式打开驱动,获取并调用驱动中的函数,来创建上下文和分发表,用glapi的接口,设置上下文和分发表到TLS;然后用户调用gl的api函数时,libGL.so中api函数会从TLS获取分发表,从分发表读取驱动函数并调用,以实现该api的功能,如glUniform4fv
————————————————
版权声明:本文为CSDN博主「xueshuangbai」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xueshuangbai/article/details/47024505
https://blog.csdn.net/qq_30599505/article/details/126494369
DRI是包含现代 Linux 图形堆栈的框架,它允许非特权用户空间程序向图形硬件发出命令,而不会与其他程序发生冲突。DRI 的主要用途是为 OpenGL 实现的 Mesa 提供硬件加速,也适用于为没有图形界面的framebuffer console提供OpenGL加速。
DRI实现分散在X Server及其关联的clients库、Mesa 3D和DRM中。所有的源代码都是开源免费的。
在经典的 X Window 系统架构中,X Server 是唯一能够独占访问图形硬件的进程,因此也是在framebuffer进行实际渲染的进程。X clients所做的就是与 X Server通信以分派渲染命令。这些命令是独立于硬件的,这意味着 X11 协议提供了一个提取图形设备的 API,因此 X clients不需要担心底层硬件的细节。任何依赖硬件的代码都位于设备相关 X 中,X Server 中管理video card或显卡驱动的部分,通常也称为视频或图形驱动程序。
3D渲染的兴起把这种框架的缺点暴露了出来。3D图形应用程序倾向于生成大量的命令和数据,这些命令和数据都必须发送到X Server进行渲染。随着 X client和 X Server 之间的进程间通信 (IPC) 数量的增加,3D 渲染性能受到了影响。X 驱动程序开发人员为了利用最新显卡的 3D 硬件功能,需要新的无 IPC 架构。Xclients应该直接访问图形硬件,而不是依赖第三方进程来执行此操作,从而节省所有 IPC 开销,这种方法称为“direct rendering”。DRI最初是为了允许任何X clients使用这种“direct rendering”方法执行3D渲染。
DRI基础架构包含3个主要组件:
在最初的 DRI 架构中,由于当时video card的内存大小,屏幕back-buffer和front-buffer的单例被DRI client和X Server所共享。渲染的数据会被先写入back-buffer,然后在v-blank间隔时间会与front-buffer进行交换。为了把数据渲染到back-buffer,DRI进程应该确保裁剪渲染数据只保留可视窗口大小。
与 X Server的同步是通过信号和称为 SAREA 的共享内存缓冲区完成的。对 DRM 设备的访问通道是唯一的,因此任何 DRI clients都必须在渲染操作开始时锁定它,其他client期间无法访问,必须等到当前渲染操作结束时释放锁。另一个缺点是在当前 DRI 进程在设备上释放锁后,操作涉及的内存不会常驻,因此上传到显存的任何数据(如纹理)都会丢失,以供即将进行的操作使用,从而对图形性能产生重大影响。
由于像 Compiz 这样的合成窗口管理器越来越受欢迎,DRI 必须重新设计以便X client在进行直接渲染时也同样支持重定向到"offscreen-pixmaps"。常规的 X client已经将 X 服务器提供的单独像素图作为渲染目标(所谓的"offscreen-pixmaps"),但 DRI client继续直接在共享的back-buffer中进行渲染,有效地绕过了合成窗口管理器。最终的解决方案是改变DRI处理渲染buffer的方式,这会导致具有一组完全不同的DRI扩展接口,并且DRM也发生了巨大变化。新的扩展名为“DRI2”,虽然它不是更高版本,而是一个不同的扩展,甚至与原始 DRI 不兼容——事实上,两者在 X Server 中共存了很长时间。
在DRI2中,每个DRI client都拥有自己私有的 back-buffer来通过硬件加速渲染器窗口内容,而不是共享back-buffer。然而,DRI client将其与一个假的"front-buffer"进行交换。假的"front-buffer"是合成窗口管理器最终合成屏幕缓冲区的buffer之一,,在 VBLANK 间隔与实际的front-buffer进行交换。
为了处理所有这些新的buffer,DRM必须必须要有新功能,特别是显存管理器。DRI2最初使用的是还不成熟的TTM内存管理器,但是DRM内存管理器还是最终选择了GEM。新的DRI2内部buffer管理模型还解决了最初 DRI 中存在的两个主要性能瓶颈:
在DRI2中,为窗口分配私有offscreen-buffers(back-buffer、fake-front-buffer、 depth-buffer、stencil-buffer等)由X Server自己完成。DRI client通过调用 DRI2 扩展中 DRI2GetBuffers 和 DRI2GetBuffersWithFormat 等接口来检索这些buffers以便渲染到窗口中。在内部,DRI2 使用 GEM 名称——一种由 GEM?API?提供的全局句柄,允许访问 DRM 设备的两个进程引用同一个缓冲区。
X Server 负责窗口渲染buffer分配的原因是 GLX 扩展允许多个 X client在同一个窗口中协同进行 OpenGL 渲染。 这样,X Server在整个渲染过程中管理渲染buffer的整个生命周期,并知道何时可以安全地回收它们。当调整窗口大小时,X server负责分配新的渲染buffer来匹配新的窗口大小,并使用 InvalidateBuffers 事件通知DRI clinet渲染到窗口中的更改,以便他们检索 GEM新缓冲区的名称。
DRI2 扩展为 DRI client提供了其他核心操作,如DRI2Connect接口可以找出他们应该使用哪个 DRM 设备和驱动程序 或DRI2Authenticate接口通过 X Server进行身份验证以便能够使用 DRM 设备的渲染和缓冲设施。使用 DRI2CopyRegion 和 DRI2SwapBuffers 请求在屏幕中呈现渲染buffer。DRI2CopyRegion 可用于在fake-front-buffer和real-front-buffer之间进行复制,但它不提供与v-black间隔的任何同步,因此会导致撕裂。 另一方面,DRI2SwapBuffers在back-buffer和front-buffer之间执行v-blank同步交换。
虽然 DRI2 比DRI 有了显着的改进,不过扩展也引入了一些新的问题。2013年,为了解决新的问题,DRI3作为DRI的第3次迭代被开发了。
DRI3 与 DRI2 相比的主要区别在于:
client的缓冲区分配打破了 GLX 的假设,因为多个 GLX 应用程序不再可能在同一个窗口中协同渲染。 从好的方面来说,DRI client在其生命周期内负责自己的缓冲区这一事实带来了许多优势,例如DRI3 client很容易确保渲染buffer的大小始终与窗口的当前大小相匹配,从而消除由于client和server之间缺乏缓冲区大小同步而困扰窗口大小调整。还实现了更好的性能,因为 DRI3 client节省了等待 X server发送渲染buffer的额外耗时。DRI3 client(尤其是合成器窗口管理器)可以利用保留前一帧的buffer区并重用它们仅对渲染窗口中变化的部分进行重绘。DRI3 扩展不再需要修改以支持新的特定缓冲区格式,因为现在直接在 DRI client驱动程序和 DRM kernel驱动程序之间处理。另一方面,文件描述符的使用允许kernel对任何未使用的 GEM buffer对象执行安全清理。
从技术上将,DRI3包含2个扩展:“DRI3”扩展和“Present”扩展。DRI3 扩展的主要目的是实现在 DRI client和 X Server之间共享直接渲染buffer的机制。DRI client分配和使用 GEM buffer对象作为渲染目标,而 X server使用一种称为“pixmap”的 X11 对象表示这些渲染缓冲区。DRI3 提供了两种接口:DRI3PixmapFromBuffer 和 DRI3BufferFromPixmap,前者是从 GEM buffer对象(在“DRI client空间”中)创建pixmap (在“X server空间”中),后者是反向操作。在这些 DRI3 接口中,GEM buffer对象作为 DMA-BUF 文件描述符而不是 GEM 名称传递。DRI3 还提供了一种在 DRI client和 X server之间共享同步对象的方法,允许对共享buffer进行序列化访问。和 DRI2不同,DRI3Open(每个 DRI 客户端必须请求知道要使用哪个 DRM 设备的操作)将已打开的文件描述符返回到设备节点而不是设备节点文件名,并且任何所需的身份验证过程已经提前执行 X sever。
DRI3 没有提供在屏幕上显示渲染缓冲区的机制,而是依赖另一个扩展,即 Present 扩展来做到这一点。Present 之所以如此命名,是因为它的主要任务是在屏幕上“Present ”缓冲区,这意味着它使用client应用程序提供的渲染缓冲区的内容来处理帧缓冲区的更新。屏幕更新必须在适当的时间完成,通常是在 VBLANK 间隔期间,以避免出现撕裂等显示问题。Present 还处理屏幕更新到 VBLANK 间隔的同步。它还使用事件让 X client知道每个缓冲区真正显示在屏幕上的时刻,因此client可以将其渲染过程与当前屏幕刷新率同步。
Present 接受任何 X pixmap 作为屏幕更新的来源.由于pixmap 是标准的 X 对象,Present 不仅可以由执行直接渲染的 DRI3 客户端使用,而且可以由任何 X 客户端以任何方式在pixmap 上渲染。例如大多数基于非 GL 的 GTK+ 和 Qt 应用程序过去使用 XRender 进行双缓冲pixmap 渲染。这些应用程序也可以使用 Present 扩展来实现高效且无撕裂的屏幕更新。这就是 Present 作为独立扩展而不是 DRI3 的一部分的原因。
除了允许非 GL X client与 VBLANK 同步之外,Present 还有其他优势。DRI3 图形性能更好,因为 Present 在交换缓冲区方面比?? DRI2 更有效。基于 Present 提供的新功能, DRI2 中许多不可用的 OpenGL 扩展被支持。
Present 为 X client提供了两个主要接口:PresentPixmap:使用pixmap 的部分或全部内容更新窗口的区域;PresentSelectInput :设置与client想要通知的窗口的Present事件的类型 。窗口可以通知 X client的三个Present事件:1、当PresentPixmap 的调用完成时(PresentCompleteNotify); 2、当 PresentPixmap 使用的pixmap 准备好被重用时(PresentIdleNotify ); 3、当窗口配置(主要是窗口大小)发生变化时 (PresentConfigureNotify)。PresentPixmap 执行直接复制 (blit) 到front-buffer还是整个back-buffer与front-buffer的交换是 Present 扩展实现的内部细节,而不是 像DRI2那样X cleint的显式选择。
几个开源 DRI 驱动程序,包括用于 ATI Mach64、ATI Rage128、ATI Radeon、3dfx Voodoo3 到 Voodoo5、Matrox G200 到 G400、SiS 300 系列、Intel i810 到 i965、S3 Savage、VIA UniChrome 图形芯片组和 Nvidia的nouveau。一些图形供应商使用的闭源 DRI 驱动程序,包括 ATI 和 PowerVR Kyro。
各种版本的 DRI 已由各种操作系统实现,其中包括 Linux kernel、FreeBSD、NetBSD、OpenBSD 和 OpenSolaris。
该项目由 Precision Insight(由 Silicon Graphics 和 Red Hat 资助)的 Jens Owen 和 Kevin E. Martin 发起,它最初是作为 XFree86 4.0的一部分广泛使用的,现在是 X.Org Server 的一部分。它目前由自由软件社区维护。
DRI2 的工作始于 2007 年 X 开发者峰会,由 Kristian H?gsberg 提出。H?gsberg 自己编写了新的 DRI2 扩展以及对 Mesa 和 GLX 的修改。2008 年 3 月,DRI2 基本完成,但它无法进入 X.Org Server 版本 1.5,不得不从 2009 年 2 月开始等到版本 1.6。DRI2 扩展正式包含在 2009 年 10 月的 X11R7.5 版本中。 DRI2 协议 (2.0) 的第一个公共版本于 2009 年 4 月发布。从那以后进行了多次修订,最近的版本是 2012 年 7 月的 2.8 版。
由于 DRI2 的一些限制,Keith Packard 和 Emma Anholt 在 2012 年 X.Org 开发者大会上提出了一个名为 DRI-Next 的新扩展,该扩展在 Linux.conf.au 2013 上再次被提议为 DRI3000,DRI3 和 Present 扩展是在 2013 年开发的,并于 2013 年 12 月合并到 X.Org Server 1.15 版本中。DRI3 协议 (1.0) 的第一个也是唯一一个版本于 2013 年 11 月发布。下面5个图是DRI框架变化过程:
图1:2D drivers在X Server
图2:通过GLX间接渲染
图3:早期DRI:由X-display-server以root身份执行mode-setting
图4:所有访问都通过DRM进行
图5:在Linux内核3.12中引入了渲染节点;DRM 和 KMS 驱动程序被拆分。Wayland 通过 EGL 实现直接渲染