刺络放血的禁用部位:Gtk+/Cairo/Glitz

来源:百度文库 编辑:偶看新闻 时间:2024/05/05 03:40:27

Gtk+/Cairo/Glitz扯开漫谈

Cairo是一个矢量图形及图像合成的类库,从GTK+ 2.8开始,GTK+大量的图形绘制功能用的就是Cairo。GTK+的官方文档说:

GDK does not wrap the Cairo API, instead it allows to create Cairo contexts which can be used to draw on GDK drawables. Additional functions allow to convert GDK's rectangles and regions into Cairo paths and to use pixbufs as sources for drawing operations.

Linux的图像系统就是复杂,这里牵扯出另一个类库GDK,GDK (GIMP Drawing Kit)是LINUX的底层图像绘制及窗口功能的封装类库。这里其实涉及另外一个类库XLIB,XLIB是什么呢,XLIB是X Window的协议客户端类库。因此,GDK是XLIB的高一级封装类库。于是,GTK+-->GDK-->XLIB-->XServer-->显卡驱动/硬件,是经典的Linux的窗口系统的层次结构。

再说说Cairo,如何插入这个层次结构中呢?Cairo是设备无关的图像库,能够支持多种绘图的后端(backend),Cairo能够支持硬件图像加速。按照Cairo的Wiki说法,Cairo的Backend: support includes output to the X Window System , Win32 GDI , Mac OS X Quartz BeOS API, OS/2 , OpenGL contexts (via glitz ), local image buffers, PNG files, PDF , PostScript , DirectFB and SVG files. Cairo的硬件图像加速的功能是调用路径是:Cairo-->Glitz-->OpenGL(显卡支持OpenGL工业标准,例如,Intel的 GMA500)。这里需要说明的是:虽然OpenGL为3D图像设计,但是高质量的2D图像绘制涉及到与显卡硬件交互,也是通过OpenGL的接口,这是为何2D的矢量图形库Cairo需要OpenGL的BackEnd。

说了这么多,仍然无法理解上述那段英文,还扯出来另外二个名词,OpenGL和Glitz。OpenGL是什么呢,OpenGL是跨平台跨语言的工业标准规范,用于2D和3D图像的绘制,不少手持设备从硬件上就支持OpenGL/OpenGL ES(又多了一个名词,自己Google吧),例如:iphone 3g s。Glitz是什么呢?是OpenGL的封装类库,Glitz不仅精确实现了X Render extension的规范,还扩展了额外的功能。

新名词继续冒,什么是X Render extension?这个问题就回到了X Window的架构,Client/Server。这种架构在普通的图像描绘中很高效,例如,XClient通知XServer将一个窗口移动一个位置之类的,Client/Server之间传送很少量的数据。但是涉及到屏幕图像绘制,这种结构就很低效率,Client/Server之间需要传输图像数据。如果要实现透明图像/窗口,效率就更低,为什么呢?为了从XClient侧进行屏幕的透明图像合成,不仅需要Client往Server传送图像数据,还需要从Server往Client传送屏幕当前的图像数据。这个理解需要复习一下透明图像的合成算法,简单说来就是需要获取是屏幕当前的图像,才能在上面叠加透明图像。于是:有新的解决方法冒出来,避免双向的大量的数据传输,为什么不是XServer直接支持屏幕透明图像绘制?这就是X Render extension,维基百科中是这样描述的:The X Rendering Extension (Render or XRender ) is an X Window System extension to implement Porter-Duff image compositing in the X server. 这个 Porter-Duff image compositing 就是透明图像的Alpha compositing。

到此为止,就有一个问题了,Gtk+ 2.8版本使用Cairo进行图像绘制,用的是什么Cairo的什么BackEnd? 能不能直接用Glitz? 答案是否定的。Gtk+的GTK+ Reference Manual的Common Questions中明确的问答:

Can I improve the performance of my application by using the Glitz backend of cairo ?

No. The GDK X11 backend uses the cairo X backend (and the other GDK backends use their respective native cairo backends). The GTK+ developers believe that the best way to improving the GDK drawing performance is to optimize the cairo X backend and the relevant code paths in the X server that is uses (mostly the Render extension).

这段英文看得有点晕,仅用到了Cairo的X Backend?最后一句Gtk+的开发者认为提高GDK的绘图效率的最佳路径在于优化cairo X backend以及Xerver侧的X Render extension?

那么?GTK+程序如何才能使用得上GPU(Graphics processing unit)的图像处理能力呢?是否应该期待GTK+的新版本呢?


探索到这里就结束了,GTK+中使用Cairo还有一个问题,这里贴出来补上。

I have created a cairo context with gdk_cairo_create(), but when I later use it, my drawing does not show up. Why is that ?    

All drawing in GTK+ is normally done in an expose handler, and GTK+ creates a temporary pixmap for double-buffering the drawing. If you create a cairo context outside the expose handler, it is backed by the GDK window itself, not the double-buffering pixmap. Consequently, any drawing you do with that cairo context gets overwritten at the end of the expose handler, when the double-buffering pixmap is copied back.

Possible solutions to this problem are:

      Turn off double-buffering, with gtk_widget_set_double_buffered(). This is not ideal, since it can cause some flickering.

      Create the cairo context inside the expose handler. If you do this, gdk_create_cairo() arranges for it to be backed by the double-buffering pixmap. This is the preferred solution, and is used throughout GTK+ itself.