DirectFB代码导读

 

DirectFB是一个庞大的系统,对它进行彻底分析要花不少时间。幸好多数情况下,只要弄清楚它的基本架构,再重点读一些关键的代码,也就差不多了。前几个月为了完善DFB的窗口管理器,我花了一些时间去研究DFB的架构。把其中一些经验写到这里,供有兴趣的朋友参考。

 

总的说来,DFB由以下几部分组成:

1.         基本库函数。这部分代码在lib目录下,它分为三个部分:

  • direct: 里面是一些公共函数,其中包括哈希表、链表、线程、调试信息、signal处理、优化过的memcpy和平台相关的一些函数。
  • fusion:它有两个版本,一个是针对单进程的,要求所有应用程序在一个进程中运行,这相对来说比较简单。另外一个是针对多进程的,应用程序可以在多个进程中运行。它实现了一些进程间通信机制,其中包括互斥、共享内存、共享内存中的vector实现、带引用计数的内核对象和reactor等。多进程版本还需要一个内核模块linux-fusion的支持。
  • voodoo: 不清楚(若那位高手知道,请补充一下,谢谢)。

 

2.         对第三方组件库的包装。这部分代码在interfaces目录下。Interfaces可能会引起别人的误解,因为它并不是DFB对外提供的接口,而是把第三方组件纳入DFB的接口。它包括三类:

  •    字体。字体有点阵字体和矢量字体之分,矢量字体又有诸如truetype之类几种格式。前者可能比较简单,而后者的处理相当复杂,要借助如freetype等第三方程序库来实现。DFB定义了IDirectFBFont接口来处理字体,在第三方字体程序库上加上一个adapter就可以在DFB中使用了。
  • 图片。图片格式的种类很多,像BMP之类的位图处理可能比较简单,而像JPG和PNG等的图片,采用了高级的压缩技术,解压算法比较复杂,通常需要第三方程序库的支持。DFB定义了IDirectFBImageProvider接口来处理图片,在第三方图片程序库上加上一个adapter就可以在DFB中使用了。
  • 视频。视频格式更多,解压算法也更复杂,自然也要借助第三方库来实现。DFB定义了IDirectFBVideoProvider接口来处理视频,在第三方视频程序库上加上一个adapter就可以在DFB中使用了。

3.         核心代码。这部分代码在src目录下。它可以分为两大类:

  • 核心组件。DFB的core由多个部分组成,每个部分称为一个core_part,都实现同一个接口CorePart。这个接口并不描述它们的功能,而是用于管理的。初看这些函数时,可能会感到有些奇怪。最好要先了解DFB采用的master/slave模型:第一个运行应用程序是master进程,后来运行的应用程序是slave进程。master进程负责初始化和~初始化arena,它只能在所有slave退出之后才能退出。而slave进程则可以随时加入arena,也可以随时退出arena。
  1. CoreInitialize: master进程初始化arena。
  2. CoreJoin: slave进程进入arena时的初始化。
  3. CoreShutdown: master进程~初始化arena。
  4. CoreLeave:slave进程离开arena时的~初始化。
  5. CoreSuspend:休眠,主要用于省电功能。
  6. CoreResume:唤醒,主要用于省电功能。

核心组件包括下面几个组件:

  1. dfb_core_clipboard: 剪切板。
  2. dfb_core_colorhash:调色板。
  3.   dfb_core_gfxcard:图形卡,主要完成基本的绘图功能,如绘直线、填充等等。
  4. dfb_core_input:输入设备。
  5. dfb_core_layers:分层功能,好像要硬件支持,通常都只有一个层。
  6. dfb_core_screens:逻辑屏幕(可能像X一样支持多个屏幕吧,不太清楚,有时间再研究)。
  7. dfb_core_system:显示输出,把gfxcard绘制后的图形数据输出到屏幕上,即可以通过fbdev输出到本机屏幕上,也可以通过sdl/x11/vnc输出到远程主机的屏幕上。对于像sdl/x11等,也包括对输入事件的处理。
  8. dfb_core_wm:窗口管理器。

以上这些core_part,有的是直接实现的,比如clipboard。有的只是一层包装,具体的实现在一个独立的共享库中,在运行时通过参数来控制加载具体的实现,如system。

 

  •   对外接口。这主要是给上层应用程序使用的。其中包括:
  1. IDirectFBInputDevice: 输入设备
  2. IDirectFBScreen: 屏幕。
  3. IDirectFBSurface: 绘图表面。
  4. IDirectFBPalette: 调色板。
  5. IDirectFBFont: 字体
  6. IDirectFBImageProvider:图片
  7. IDirectFBVideoProvider:视频
  8. IDirectFBWindow:窗口
  9. DirectFBEventBuffer: 事件缓冲

4.         窗口管理器。这部分代码在wm目录下。DFB实现了两个窗口管理器。

  • default:实现了基本的窗口管理功能,支持一些快捷键。
  • unique:功能也很弱,不过架构还可以,加入自己的功能很方便。

 

5.         输入设备。这部分代码在inputdrivers目录下。其实这些代码并不是真正的驱动,只是一个adapter层,它把从linux设备文件读到的事件,转换成DFB自己的事件格式,然后调用dfb_input_dispatch把事件分发出去。

 

6.         输出设备。这部分代码在system目录下。这也是一个adapter层,主要对显示设备的抽象,有的也包括对输入事件的处理。其中包括:

  • fbdev: 输出到frame buffer。
  • osx:   输出到mac os上。
  • vnc: 输出到Virtual Network Computing(类似于微软远程桌面的一个协议)。
  • x11: 输出到X Window上,在0.9.24仍然有问题,建议使用SDL。
  • sdl:  输出到Simple DirectMedia Layer。

7.         值得注意的几个问题:

  •   master/slave模型。master/slave是DFB的基本模型,一定要先了解它,否则很难了解DFB的基本架构。
  • reactor模式。DFB中的消息,无论是进程内的,还是进程间的,都是通过reactor来传递的。这是一种简单的发布-订阅机制,谁关心谁就注册。不先弄清楚reactor的机制,很容易就被消息的流向搞糊涂了。
  • 加锁术语。加锁/解锁动作常用lock/unlook、acquire/release、 wait/release等术语,而DFB里使用skirmish_prevail/skirmish_dismiss。
  • 引用计数术语。增加/减少引用计数常用ref/unref、addref/release等术语。DFB里使用了ref/unref,同时增加了几个动作:link/unlink用于增加和减少全局引用计数,ref增加的计数,只要应用程序退出,fusion自动释放这个引用计数。而link增加的引用计数非要用unlink减少才行,应用程序退出时不会自动减少。inherit: 继承另外一个对象的引用计数,即把被继承的对象的引用计数加到继承者身来,不但如此,当被继承的对象的引用计数增减时,自动增减继承者的引用计数。
  • 注册/注销术语。注册/注销常用register/unregister等术语,DFB使用了attach/detatch。
  • 内核对象的宏。DFB用宏FUSION_OBJECT_METHODS去实现一个fusion object的子类,FUSION_OBJECT_METHODS是在object.h里定义的。像CoreWindow和CoreSurface等内核对象,都调用这个宏去实现自己的方法。
  • CorePart的宏。DFB用宏DFB_CORE_PART去实现一个core part,DFB_CORE_PART是在core_parts.h定义的。
  • 动态模块的加载。DFB并不要求动态加载模块实现特定的接口函数,而当模块被加载时(dlopen时),把自己安装到框架中。模块使用了gcc的__attribute__((constructor))扩展,模块被加载时,该函数自动执行,然后调用direct_modules_register注册自己。
  • cardstate:我开始被blit函数弄糊涂了,并不像WIN32下那样要求指明源和目标。后来才知道它是调用另外的函数去设置源和目标,而不是通过参数来指定。

 

在研究DFB时,我的主要精力放在DFB的架构、窗口管理器、输入设备驱动和fusion上,其它地方花的时间比较少,特别是对gfx只有一个模糊的概念,抱歉不能在这些方面提供更多信息。我对图形算法不太熟悉,大家可以问我某个流程是怎么走的,某个对象与另外一个对象是怎么交互的,但不要问我某个算法是怎么实现的。


你可能感兴趣的:(DirectFB代码导读)