linux下图形架构的演变

来源:互联网 发布:中国农业大学网络邮局 编辑:程序博客网 时间:2024/05/23 19:34

之前看过DRI DRI2 AIGLX,有了一点自己的思考,也算是对linux下的图形渲染架构做一次整理吧。有些东西不知道对不对,因为毕竟也是自己的理解。

先说说DRI。
DRI最开始因为AP和X是两个进程,ap不会知道X的offscreen pixmap,所以不能访问这块mem。因为vidmem都是对于per-process进行映射的。需要从loader发request去X找对应的信息,比如clipinfo。
换句话说,在dri时候,没有统一的vidmem映射,所以client端的ap只能看到自己dri出来的内存。X能看到真个vidmem,包括primary。所以dri的ap只能画到某一块区域,没有composite。

到了DRI2。
Dri2时候,加入了TTM和GEM。所有的ap和x看到了统一的vid内存。所以compiz知道怎么去获取各种内存(私有的buf和primary)去进行合成动作。
DRI2从内核使用ttm。可以支持不同用户process之间vidmem的统一映射,就是ap可以看到x的offsceen pixmap(实际上就是一块vidmem),所以可以用来render了。显存统一化了。

DRI和dri2在render完都要发notifydamage,只不过对dri的x没什么意义。对于dri2,发送damage给x,x再返回damage给ap。
在dri和dri2,3d画完都会发notifyDamage消息给x,x也会把damage event发给ap。但是ap本身如果拿不到整个primary surf的handle,就不能合成,所以compiz挂了,它只能拥有自己私有的back 或者其他的buf handles。

对于AIGLX。
AIGLX在dri和dri2之间出现,就是为了在x端使用3d画图。
如果client要render X端的offscreen pixmap,需要用getImage去获取pixmap的信息。然后subImage2D上传到X,最后X从sysmem拷贝到vidmem。需要在进程之间进行拷贝,效率不行。
因此提出了AIGLX。通过使用texture_from_pixmap。Client需要bindTex。不需要再client和x之间传递pixmap信息。但是仍然需要server将pixmap从sysmem放到lfb的texture,需要texImage2D。

何为Texture from pixmap:
没有tfp的时候,ap要拿到pixmap,只能getImage和putImage函数,相当于ap和X进程间通信。
使用tfp时候,ap只需要bind这个pixmap,然后告诉X。就可以操作了。Texture还是在sysmem,仍然需要将texture从sysmem放到vidmem里面。
A卡做的tfp优化,将texture直接放在vidmem里面。

差不多就是这个历史的流程了。

不过具体实现起来还是很复杂的,大概思路如下。

DRI1:
Buf方面
CreateDrawable:
(1)client发送req给X。(2)X会在通过libdrm到kernel drm中创建drawable的对象drm_drawable_t :hwdrawable。(3)根据window的clipList的number来判断是否需要创建offscreen back/depth buf(利用dri.so)或者使用shared buf。
Swapbuf在client做了。X端没有swapbuf的任何操作。

Client还会报Damage.在libGL createNewScreen的时候会把这个extension加上. 让client 可以给X报damage?算不算一个hack.

X的dri ext需要维护所有的buf,包括生成的offscreen back/depth buf。然而产生了两个问题:
1. client需要传clipList给X,让X去做clipNotify的操作。因为client并不知道各种buf的存在。因此dri.c里面很多的clip/tree的操作。
2. 当client要做direct rendering时候,完全不知道X所做的各种offscreen的buf操作。因此就直接画到primary上面了。所以效果差。

Context方面
CreateContext:
1. 发送req给X 去createContext。X用libdrm去ioctl kernel的drm去创建HW context。将创建好的hwContext和DRIcontextPriv绑定在一起。X去call dri.so的createContext.
BindContext/UnbindContext:
直接call dri.so的bind/ubind函数。

综合来看:
DRI1 需要kernel记录每一个创建的drawable和context的信息。剩下的对于drawable和context的操作都在client做了。

DRI2:
CreateDisplay 1 createScreen 2 load ext: GetBufs/flushfrontBuf
CreateScreen :
1 connect req -> X return fd/drvname/dev name
2 autheticate req -> X

Drawable方面
Create 1 req-> X 创建drawable结构体 2 dri.so 的create drawable
GetBufs:
req -> X 获得drawable信息,分配内存/重用内存。X获得dri.so分出来的DRI2BUFFER 指针,传递给client。相当于X和client同时得到DRIBUFFER的handle(应该是GEM出来的),有安全问题。
SwapBuf: req -> X dri.so的swap。

内存的操作:GEM提供一套统一接口,client可以通过X去allocate和swap,X相当于client的一个mem操作的代理。GEM的handle在process(X和client)之间流动,存在一定的安全问题。

0 0