DirectFB 代码导读

DirectFB 代码导读

 

转载时请注明出处和作者联系方式
作者联系方式:李先静 <xianjimli at hotmail dot com>

 

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 代码导读)