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目录,如果从kernel.org上面下载一个内核源码,直接编译,编译的时间大部分都耗在编译设备驱动上。

微内核的操作系统,设备驱动不是内核的部分。这里不讨论微内核和宏内核的区别或者各自的优缺点。但是出于调试方便以及其他一些原因,Linux操作系统上面的一些驱动是放在核外的。一个主要的类别就是打印机、扫描仪这类设备,当前的打印机扫描仪通常都是通过USB 接口连接到计算机上的,对于这些设备的Linux驱动,除了USB核心部分在内核,这些打印机扫描仪本身的驱动都是在核外的。Linux上面的打印机使用CUPS系统,CUPS运行在核外,其驱动是按照CUPS的接口来开发的。Linux上面的扫描仪使用的是运行在核外的sane系统,其驱动是以动态链接库的形式存在的。另外一类核外的驱动是图形系统的驱动,由于图形系统、显卡本身比较复杂,而且由于一些历史原因,图形系统的驱动在核内核外都有,并且显卡驱动最主要的部分在核外。

在wiki词条“Free and open-source graphics device driver”的最新页面上,对linux环境下的图形系统演变过程有一个很好的图解,这里直接使用这个页面的图进行描述 http://en.wikipedia.org/wiki/Free_and_open-source_graphics_device_driver

显卡最早只有基本的显示功能,可以成为显示控制器(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”http://xwindow.angelfire.com/)应该知道,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中。

图3

然后又添加了对远程3D client的支持AIGLX,这部分的功能和原来的Utah GLX有类似之处。AIGLX可以参考wiki页面(http://en.wikipedia.org/wiki/AIGLX)。

图4

X server通过不断扩展形成了现在的样子,显得庞大而且复杂,有些工作是不必要的。开源社区提出了更为简洁的wayland图形系统,在“揭开Wayland的面纱(一)(二)”两篇文章里面对wayland做了说明,读者可以点击下面的地址:

http://www.ibentu.org/2010/11/06/introduce-to-wayland-01.html

http://www.ibentu.org/2010/11/06/introduce-to-wayland-01.html

图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加速驱动。

还注意到,内核里面有一个KMS,全称是kernel mode setting(内核模式设置,设置显示分辨率之类的),前面曾经提到过,早期的显卡寄存器是直接暴漏给核外驱动的,直到现在的EXA内核代码里面仍然有MMIO和CP两种操作方式,早期X进行模式设置的时候直接写寄存器进行操作,后来内核引入了KMS(在wayland之前就已经有了),于是核外驱动可以通过调用KMS接口进行模式操作而不需要了解硬件细节。

上面提到了composite,X的composite的操作如下图示:

图6

过去的X11 client直接在显示区域上,现在X11 client窗口在off-screen显存上,compositor从这些显存上取出内容并最终混合到显示区域上去。X里面和composite操作相关的扩展有damage、render、composite,这三者描述参考以下资料:

http://cgit.freedesktop.org/xorg/proto/compositeproto/plain/compositeproto.txt

http://cgit.freedesktop.org/xorg/proto/damageproto/plain/damageproto.txt

http://cgit.freedesktop.org/xorg/proto/renderproto/plain/renderproto.txt

关于X composite的引入过程读者可以参考以下资料:

Keith Packard. Design and Implementation of the X Rendering Extension

Matthieu Herrb, Matthias Hopf. New Evolutions in the X Window System

Andy Ritger. Using the Existing XFree86/X.Org Loadable Driver Framework to Achieve a Composited X Desktop

当前的Linux环境上的图形系统架构如下图示:

图7

这里的部分内容在前面描述过了,需要注意的是X server的EXA驱动部分出现了glamor,glamor直接调用到了mesa里面,过去EXA驱动是单独的驱动,通过drm调用操作硬件,而由于mesa的改变,X可以和wayland composite一样直接调用Mesa的接口。

后面的描述将针对Fedora 16操作系统,Fedora 16系统和现在最新的系统(图7)有一定的区别,后面的一些问题的讨论主要使用图4。在后续blog中,将先对Fedora的图形系统内核、X、Mesa这个层次的部分进行一个简单的描述,然后开始介绍驱动对AMD显卡硬件部分模块(功能)的编程。

其他参考资料:

Inside Linux graphics 是intel的开发人员编写的一份介绍图形架构的文档。

Linux Graphics Drivers: an Introduction 是开源社区的开发人员写的一份文档,对Linux图形系统的各个方面都有一些介绍。

A deeper look into GPUs and the Linux Graphics Stack 这一份ppt对图形系统架构有比较深入的探讨。

Graphics Card Interfaces 这篇博文对图形架构的部分细节有一些探讨。

精通嵌入式Linux编程:构建自己的GUI环境 这本书描述了如何在framebuffer上构建一个完整的图形系统,其中的许多概念和原理在X图形系统中也能够看到。

【原创】Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介的更多相关文章

  1. Linux环境下的图形系统和AMD R600显卡编程(1)——Linux环境下的图形系统简介

    转:https://www.cnblogs.com/shoemaker/p/linux_graphics01.html Linux/Unix环境下最早的图形系统是Xorg图形系统,Xorg图形系统通过 ...

  2. 【原创】Linux环境下的图形系统和AMD R600显卡编程(2)——Framebuffer、DRM、EXA和Mesa简介【转】

    转自:http://www.cnblogs.com/shoemaker/p/linux_graphics02.html 1. Framebuffer Framebuffer驱动提供基本的显示,fram ...

  3. 【原创】Linux环境下的图形系统和AMD R600显卡编程(6)——AMD显卡GPU命令格式

    前面一篇blog里面描述了命令环缓冲区机制,在命令环机制下,驱动写入PM4(不知道为何会取这样一个名字)包格式的命令对显卡进行配置.这一篇blog将详细介绍命令包的格式. 当前定义了4中命令包,分别是 ...

  4. 【原创】Linux环境下的图形系统和AMD R600显卡编程(5)——AMD显卡显命令处理机制

    通常通过读写设备寄存器对设备进行编程,在X86系统上,有专门的IO指令进行编程,在其他诸如MIPS.SPARC这类系统上,通过将设备的寄存器映射到内存地址空间直接使用读写内存的方式对设备进行编程. R ...

  5. 【原创】Linux环境下的图形系统和AMD R600显卡编程(3)——AMD显卡简介

    早期的显卡仅用于显示,后来显卡中加入了2D加速部件,这些部件用于做拷屏,画点,画线等操作.随着游戏.三维模拟以及科学计算可视化等需要,对3D的需求逐渐增加,早期图形绘制工作由CPU来完成,要达到真实感 ...

  6. 【原创】Linux环境下的图形系统和AMD R600显卡编程(9)——R600显卡的3D引擎和图形流水线

    1. R600 3D引擎 R600核心是AMD一款非常重要的GPU核心,这个核心引入了统一处理器架构,其寄存器和指令集同以前的GPU 都完全不同,对其编程也有比较大的区别. 图1显示了R600 GPU ...

  7. 【原创】Linux环境下的图形系统和AMD R600显卡编程(10)——R600显卡的3D引擎编程

    3D图形处理流水线需要流经多个硬件单元才能得到最后的渲染结果,流水线上的所有的硬件单元必须被正确编程,才能得到正确的结果. 总体上看,从图形处理流水线的源头开始,需要准备好vertex和index,在 ...

  8. 【原创】Linux环境下的图形系统和AMD R600显卡编程(7)——AMD显卡的软件中断

    CPU上处理的中断可以分成“硬件中断”和“软件中断”两类,比如网卡产生的中断称为硬件中断,而如果是软件使用诸如"int 0x10"(X86平台上)这样的指令产生中断称为软件中断,硬 ...

  9. 【原创】Linux环境下的图形系统和AMD R600显卡编程(4)——AMD显卡显存管理机制

    显卡使用的内存分为两部分,一部分是显卡自带的显存称为VRAM内存,另外一部分是系统主存称为GTT内存(graphics translation table和后面的GART含义相同,都是指显卡的页表,G ...

随机推荐

  1. 罗辑思维CEO脱不花:关于工作和成长,这是我的121条具体建议

    1 关于面对批评 01. 没有人对被批评感到高兴.如果有,TA撒谎. 02. 面对批评,得体的第一反应是“不急于解释,不反唇相讥”. 03. 每天,或者最长每周养成习惯,把自己存在的问题和造成的麻烦用 ...

  2. [BZOJ4556][Tjoi2016&Heoi2016]字符串 后缀数组+主席树

    4556: [Tjoi2016&Heoi2016]字符串 Time Limit: 20 Sec  Memory Limit: 128 MB Description 佳媛姐姐过生日的时候,她的小 ...

  3. CF1088F Ehab and a weird weight formula 贪心 倍增

    CF1088F Ehab and a weird weight formula 题意 给定一棵树,点有点权,其中这棵树满足除了权值最小的点外,每个点至少有一个点权小于它的相邻点. 要求你重新构建这棵树 ...

  4. Missing $ inserted解决方法

    目录 问题描述 解决 参考 问题描述 在学习LaTex Tutorial的时候,按照教程输入矩阵的时候发现出现了 ! Missing $ inserted的错误. 解决 在矩阵前后要加上$,如图所示 ...

  5. NetApp常用巡检命令

    常用检查命令 environment status 查看环境信息 version 查看OS版本 sysconfig -v 查看系统信息(设备序列号 系统软.硬件信息等) sysconfig -a 查看 ...

  6. Mac OS 装gdb

    1 要求按照mac ports 2 命令:sudo port install gdb 3 安装位置在: /opt/local/bin/ggdb , 注意,ggdb是执行命令

  7. GridView中网络图片延迟加载导致高度计算失败的问题

    在使用下拉刷新以及加载更多控件的时候,出现了列表上滚不完的现象,经过半天的分析,最后得出结论:由于图片采用了延迟加载,导致列表按照没有加载图片时候的大小进行布局,相关的加载更多控件也就傻逼了. 最终解 ...

  8. HDU 5306 线段树

    吉司机课件题. 区间min,区间最值,区间和. 如果用最大值和次大值能更新区间和那就更新打标记,否则暴力dfs. #include<iostream> #include<cstdio ...

  9. Maven settings.xml配置(指定本地仓库、阿里云镜像设置)

    转: 详解Maven settings.xml配置(指定本地仓库.阿里云镜像设置) 更新时间:2018年12月18日 11:14:45   作者:AmaniZ   我要评论   一.settings. ...

  10. supervisor 添加新配置不生效的问题

    supervisorctl reread supervisorctl reload (不运行这一步会导致启动不了) supervisorctl start xxx:* 提示:No config upd ...