一下,想像一下,当你点击了Firefox(X Client)的“刷新”按钮,将会发生以下事情:
- 你用鼠标点击了Firefox的“刷新”按钮,这时内核收到了鼠标发来的事件,并将其通过evdev输入驱动发送至了X Server.这时内核实际上做了很多事情,包括将不同品牌的鼠标发出的不同信号转换成了标准的“evdev”输入信息.
- 这时X Server可以判断哪个Window该收到这个消息,并将某座标按下按钮的消息发往X Client——Firefox.但事实上X Server并不知道它得到的窗口信息是不是正确!为什么呢?当前的Linux桌面早已经不是10年前的那样了,现在是“Composite”即合成 桌面的时代,合成桌面的一个特点便是:Compositor(如Compiz)管理窗口的一切,X Server只能知道屏幕的某个点收到了鼠标消息,却不知道这个点下面到底有没有窗口——谁知道Compiz是不是正在搞一个漂亮的、缓慢的动画,把窗口 收缩起来了呢?
- 假设应用场景没这么复杂,Firefox顺利地收到了消息,这时Firefox要决定该如何做:按钮要有按下的效果.于是Firefox再发送请求给X Server,说:“麻烦画一下按钮按下的效果.”
- 当X Server收到消息后,它就准备开始做具体的绘图工作了:它告诉显卡驱动,要画怎么样一个效果,然后它也计算了被改变的那块区域,同时告诉Compiz那块区域需要重新合成一下.
- Compiz收到消息后,它将从缓冲里取得显卡渲染出的图形并重新合成至整个屏幕——当然,Compiz的“合成”动作,也属于“渲染(render)”,也是需要请求X Server,我要画这块,然后X Server回复:你可以画了.
- 整个过程可能已经明了了,请求和渲染的动作,从X Client->X Server,再从X Server->Compositor,是双向的,确实是比较耗时的,但是,事实还不是如此.介于X Window已有的机制,尽管Compiz已经掌管了全部最终桌面呈现的效果,但X Server在收到Compiz的“渲染”请求时,还会做一些“本职工作”,如:窗口的重叠判断、被覆盖窗口的剪载计算等等(不然它怎么知道鼠标按下的坐 标下,是Firefox的窗口呢)——这些都是无意义的重复工作,Compiz不会理会这些,Compiz依然会在自己的全屏幕“画布”上,画着自己 的动画效果……
从这个过程,基本可以得出结论:
- X Client <-> X Server <-> Compositor,这三者请求渲染的过程,不是很高效;
- X Server,Compositor,这两者做了很多不必要的重复工作和正文切换.
当然,这里我没有直接说明这种模式有没有给X Window造成效率问题,我们还少一个对照组.再看对照组之前,再来看看X Server的另一个趋势:
从“什么都做”到“做得越来越少”的X Window
X Window刚出现那会,主要提供一个在操作系统内核上的抽象层,来实现一个图形环境.所谓图形环境,最主要的便是:图形+文字.当时的X Window便提供“绘图”和“渲染文字”的机制.图形桌面上的图案和文字,都通过X Window合成并绘制出来.
一个典型的例子,如果你要用X来画点,就要在你的程序中通过“XDrawPoint”来进行,X Server收到消息后,便会画出相应的点.
现在,稍微接触过图形开发的人都知道了,在X Window下,一般都通过GTK 和Qt来进行了.更深一层的是,通过Cairo(Qt不是)来绘制图形.Cairo是什么?它是一个绘图+渲染引擎,著名的浏览器Firefox,便是使用Cairo来渲染网页和文字的.
Cairo是一个全能的、跨平台的矢量绘图库,它不是简单的包装一下各个平台的绘图库而已,尽管它最初是基于X Window开发出来的绘图库.现在Cairo支持各种不同的后端,来 |