【原创】Linux环境下的图形系统和AMDR600显卡编程(1)
——Linux环境下的图形系统简介
linux操作系统书籍
Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过扩展的⽅式以适应显卡和桌⾯图形发展的需要,然⽽随着软硬件的发展,特别是嵌⼊式系统的发展,Xorg显得庞⼤⽽落后。开源社区开发开发了⼀些新的图形系统,⽐如Wayland图形系统。
由于图形系统、3D图形本⾝的复杂以及历史原因,Linux下的图形系统相关的源码庞⼤⽽且复杂,⽽且缺少学习的资料(所有源代码分析或者驱动编程的书籍都很少介绍显卡驱动)。在后续⼀系列⽂章中,笔者将从对AMD硬件编程的⾓度出发对部分问题做⼀个简单的介绍,当然,这种介绍是很初级的,旨在希望能够对初学着有所帮助。
内核DRM、Xorg以及Mesa三部分加起来的代码和整个Linux内核的体量是差不多⼤的。⽽且现代的显卡上的GPU的复杂程度在⼀定程度上可以和CPU相聘美,从程序员的⾓度看,操作系统(CPU的驱动)包含的许多功能在GPU驱动上都能够到。⽐如,GPU有⾃⼰的指令系统,着⾊器程序(GLSL、HLSL、Cg这类着⾊语⾔)需要经过编译成GPU的指令集,然后才能够在GPU上运⾏,符合着⾊语⾔规范的3D 驱动都包含⼀个编译器。3D应⽤程序需要使⽤⼤量内存,GPU在进⾏运算的时候需要访问这些内存,GPU在访问这些内存的时候也使⽤⼀套和CPU页表⼀样的机制。另外,在中断系统上,GPU和CPU也有
相似之处。后⾯的⼀些内容将会陆续对这些问题做⼀个简单的介绍。
传统上认为Linux是⼀个宏内核,设备驱动⼤部分都是包含在内核⾥⾯的,因此可以看到内核代码最庞⼤的部分是drivers⽬录,如果从上⾯下载⼀个内核源码,直接编译,编译的时间⼤部分都耗在编译设备驱动上。
微内核的操作系统,设备驱动不是内核的部分。这⾥不讨论微内核和宏内核的区别或者各⾃的优缺点。但是出于调试⽅便以及其他⼀些原因,Linux操作系统上⾯的⼀些驱动是放在核外的。⼀个主要的类别就是打印机、扫描仪这类设备,当前的打印机扫描仪通常都是通过USB 接⼝连接到计算机上的,对于这些设备的Linux驱动,除了USB核⼼部分在内核,这些打印机扫描仪本⾝的驱动都是在核外的。Linux 上⾯的打印机使⽤CUPS系统,CUPS运⾏在核外,其驱动是按照CUPS的接⼝来开发的。Linux上⾯的扫描仪使⽤的是运⾏在核外的sane系统,其驱动是以动态链接库的形式存在的。另外⼀类核外的驱动是图形系统的驱动,由于图形系统、显卡本⾝⽐较复杂,⽽且由于⼀些历史原因,图形系统的驱动在核内核外都有,并且显卡驱动最主要的部分在核外。
在wiki词条“Free and open-source graphics device driver”的最新页⾯上,对linux环境下的图形系统演变过程有⼀个很好的图解,这⾥直接使⽤这个页⾯的图进⾏描述。
显卡最早只有基本的显⽰功能,可以成为显⽰控制器(Display Controller)或者帧缓冲设备,对于这
样的显⽰控制器,当前的Linux内核对其的⽀持表现为framebuffer驱动,Xorg部分对其的⽀持是⼀个名为fbdev的驱动。
图1
其后显卡上逐渐加上了2D加速部件,这种情况下⾯的驱动如上图显⽰。这个情况下的架构还是⽐较简单的。
图2
随着3D图形显⽰和运算的需要,带有图形运算功能的显卡出现,这个时候需要有专门的3D驱动来处理3D,于是出现了上图的GLX driver,这⾥注意到X server依然处在⼀个中⼼节点的位置,⽆论是X11程序还是3D OpenGL程序,都要通过X server才能到底层。同时注意到到现在为⽌X的2D driver和GLX driver都是直接调⽤到硬件,⽽没有通过内核调⽤。在2.6版本的内核的系统上,依然能看到X 2D driver中有访问硬件有MMIO和CP两套代码,MMIO就是这⾥的情况,显卡寄存器直接暴露给核外的2D driver(和GLX driver,⽬前已经不存在这个了)。
这种情况下的结构仍然是⽐较简单的,然⽽这种情况有⼀个很⼤的问题,读过X server代码的(或者参考这篇⽂章“X Window System Internals”)应该知道,X server是单线程的(关于多线程X server,可以google到⼀些邮件讨论记录),main函数完成系统初始化之后就进⼊了⼀个循环,等待客户端程序的连⼊,等⼀个客户端程序发送完数据之后其他的客户端才能连上来,OpenGL客户端程序每次要请求硬件都必须先经过X server,然后由X server“代表”OpenGL程序进⼊硬件,对于场景稍微复杂的3D应⽤程序来说,这样频繁的和X server交互是难以保证3D渲染的实时性的。
鉴于上⾯的问题,引⼊了DRI机制,在这个机制下⾯,OpenGL程序对硬件的请求不再经过X server,⽽是⾃⼰直接和硬件交互。整个过程是这样的:在绘图之前,OpenGL程序向内核申请到⼀⽚渲染⽬标并告诉X server,然后OpenGL程序不经过X server⽽直接调⽤进内核请求硬件进⾏渲染操作,并将结果渲染到申请到的渲染⽬标中,渲染结束后,OpenGL程序通知X server该渲染⽬标发⽣了变化,对应的屏幕上的窗⼝区域需要进⾏更新,X server收到这个通知后,进⾏⼀次重新的窗⼝混合⼯作(当前代码是EXA的Composite功能提供的)。这个时候的情况如下图⽰,GLX driver被DRI driver取代,和Dri driver交互的不再是X server⽽直接是OpenGL程序。另外DRI(原来是GLX)不直接操作硬件,⽽是通过内核drm驱动操作硬件,drm提供硬件访问通道和访问机制。在当前的系统上,2D driver以EXA 2D加速驱动的形式存在于Xorg⾥⾯,DRI driver则在Mesa中。
react router缓存
图3
然后⼜添加了对远程3D client的⽀持AIGLX,这部分的功能和原来的Utah GLX有类似之处。AIGLX可以参考wiki页⾯()。
图4
X server通过不断扩展形成了现在的样⼦,显得庞⼤⽽且复杂,有些⼯作是不必要的。开源社区提出了更为简洁的wayland图形系统,在“揭开Wayland的⾯纱(⼀)(⼆)”两篇⽂章⾥⾯对wayland做了说明,读者可以点击下⾯的地址:
图5
在这两篇⽂章⾥⾯描述了这么⼀个场景:在⼀个图形程序上点击某个按钮。在X图形系统下,X的evdev驱动捕获到这个信息,X被告知有应⽤程序需要进⾏渲染,然后X server查询到需要渲染的窗⼝,然后将“⿏标点击”这个事件通知给需要渲染的窗⼝对应的X程序,X程序接收到通知后再告诉X server“如何进⾏渲染”,X server接收到“如何渲染”的消息后进⾏渲染(2D情况下X/EXA⾃⼰完成,3D情况下⽆需先通知X server,使⽤DRI完成绘制并由应⽤程序告知X渲染已经完成),完成通知X的“composite”扩展进⾏混合,X的composite扩展接到混合请求后告知X server混合已经完成,这⾥⾯
X server和X client以及X server和X composite之间都有双向的通信,这两部分是⽐较耗时的,⽽且由于X server通知X composite之前还需要进⾏窗⼝的重叠判断、被覆盖窗⼝的剪载计算等——然⽽这些是X composite不需要的,因此会有⼀些额外的时间消耗。
在Wayland情况下,server主要进⾏composite,应⽤程序全部使⽤DRI直接渲染机制,完成后通知Server(composite)进⾏混合,结构上⾮常简单⽽且⾼效。
另外对窗⼝的请求也发⽣了变化,在X DRI下,X11和3D程序需要向X server请求窗⼝,那个时候X server进⾏的加速操作必须依赖单独的EXA驱动(⽆法直接调⽤OpenGL加速),后来的mesa做了⼀些修改,在wayland环境下,Application直接通过EGL、GLES driver向内核drm请求绘图窗⼝,⽽这⾥的composite可以直接调⽤OpenGLES进⾏加速,⽽⽆需单独有2D加速驱动。
echarts柱状图颜渐变还注意到,内核⾥⾯有⼀个KMS,全称是kernel mode setting(内核模式设置,设置显⽰分辨率之类的),前⾯曾经提到过,早期的显卡寄存器是直接暴漏给核外驱动的,直到现在的EXA内核代码⾥⾯仍然有MMIO和CP两种操作⽅式,早期X进⾏模式设置的时候直接写寄存器进⾏操作,后来内核引⼊了KMS(在wayland之前就已经有了),于是核外驱动可以通过调⽤KMS接⼝进⾏模式操作⽽不需要了解硬件细节。
上⾯提到了composite,X的composite的操作如下图⽰:
Composite
图6
过去的X11 client直接在显⽰区域上,现在X11 client窗⼝在off-screen显存上,compositor从这些显存上取出内容并最终混合到显⽰区域上去。X⾥⾯和composite操作相关的扩展有damage、render、composite,这三者描述参考以下资料:
为什么要用malloc函数关于X composite的引⼊过程读者可以参考以下资料:
Keith Packard.
Matthieu Herrb, Matthias Hopf.
spring构造方法注入bean
Andy Ritger.
当前的Linux环境上的图形系统架构如下图⽰:
这⾥的部分内容在前⾯描述过了,需要注意的是X server的EXA驱动部分出现了glamor,glamor直接调⽤到了mesa⾥⾯,过去EXA驱动是单独的驱动,通过drm调⽤操作硬件,⽽由于mesa的改变,X可以和wayland composite⼀样直接调⽤Mesa的接⼝。
后⾯的描述将针对Fedora 16操作系统,Fedora 16系统和现在最新的系统(图7)有⼀定的区别,后⾯
的⼀些问题的讨论主要使⽤图4。在后续blog中,将先对Fedora的图形系统内核、X、Mesa这个层次的部分进⾏⼀个简单的描述,然后开始介绍驱动对AMD显卡硬件部分模块(功能)的编程。
其他参考资料:
是intel的开发⼈员编写的⼀份介绍图形架构的⽂档。
excel函数match用法Linux Graphics Drivers: an Introduction 是开源社区的开发⼈员写的⼀份⽂档,对Linux图形系统的各个⽅⾯都有⼀些介绍。这⼀份ppt对图形系统架构有⽐较深⼊的探讨。
这篇博⽂对图形架构的部分细节有⼀些探讨。
这本书描述了如何在framebuffer上构建⼀个完整的图形系统,其中的许多概念和原理在X图形系统中也能够看到。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。