转载时请表明原文出处(http://blog.sina.com.cn/wyw1976)及作者邮箱(wyw1976@gmail.com)
DirectFB就是一个全能系统,麻雀虽小五脏俱全。DirecttFB源码,可以了解很多方面的技术, 包括Framebuffer, Graphics Accelerate Card,鼠标及键盘等外设的事件处理,Font, Graphics Drawing等,例外还可以看到一下很有用的编程技巧,例如C++思想在C语言中的运用,动态加载链接库,双buffer的具体实现,进程通信,多进程的控制和管理等。
对于任何一个DirectFB程序,头两句有关DirectFB的函数调用一定是:
DirectFBInit( &argc, &argv );
DirectFBCreate( &dfb );
它的作用是初始化整个DirectFB库,为后面的画图等实际操作做好准备,那DirectFB是如何完成初始化的呢?它的初始工作包括那些呢?现在我们就从这两个函数开始,进入DirectFB源代码。
(一)
DirectFBInit()定义在【src\Directfb.c】中,主要是读取系统的和用户定义的configuration、处理命令行,读取环境变量等,我们暂且跳过这个函数,但是由于它的重要性,我们会在以后专为此开一个专题。
DirectFBCreate()也定义在【src\Directfb.c】中,从用户的角度看,这个函数的作用就是返回一个类型为IDirectFB的指针,而这个指针是在后续API调用中必须的,例如CreateSurface() , CreateFont()等。从DirectFB本省来说,这个函数完成一系列的初始化,并将各种需要的信息保存在IDirectFB指向的数据结构中。它主要会调用三个函数:
·
·
·
dfb_core_create() 主要完成directfb各个子系统的初始化,完事以后,所有的信息都会保存在一个CoreDFB的数据结构中,它是IDirectFB的一部分。
另外,DirectFB 是支持多进程的,由于其中涉及的内容多而杂,因此我们先研究单进程的情况,所有涉及的对线程的代码我们都先忽略,后面会单独开辟专题研究多进程是如何工作的。
(二)
现在我们就看看dfb_core_create()是如何工作的:
它依次调用下面的几个函数:
·
·
·
·
·
我们现在逐一分析后四个函数。
dfb_system_lookup( ) [src\core\System.c]是搜寻是否存在system的实现,在DirectFB中,system 概念特指graphics system, 不同的系统意味着显示输出设备和接口是不同的。例如:
· fbdev: 输出到frame buffer。
· osx: 输出到mac os上。
· vnc: 输出到Virtual Network Computing(类似于微软远程桌面的一个协议)
· x11: 输出到X Window上。
· sdl: 输出到Simple DirectMedia Layer。
为了统一各个graphics system 之间的差异,DirectFB定义了一套统一的接口,也就是说各个graphics system必须实现这些接口,才能使DirectFB运行在其上。这些接口实际上就是一些API, 具体定义在【src\core\Core_system.h】:
static CoreSystemFuncs system_funcs = {
.GetSystemInfo = system_get_info,
.Initialize = system_initialize,
.Join = system_join,
.Shutdown = system_shutdown,
.Leave = system_leave,
.Suspend = system_suspend,
.Resume = system_resume,
.GetModes = system_get_modes,
.GetCurrentMode = system_get_current_mode,
.ThreadInit = system_thread_init,
.InputFilter = system_input_filter,
.MapMMIO = system_map_mmio,
.UnmapMMIO = system_unmap_mmio,
.GetAccelerator = system_get_accelerator,
.VideoMemoryPhysical = system_video_memory_physical,
.VideoMemoryVirtual = system_video_memory_virtual,
.VideoRamLength = system_videoram_length,
.AuxMemoryPhysical = system_aux_memory_physical,
.AuxMemoryVirtual = system_aux_memory_virtual,
.AuxRamLength = system_auxram_length,
.GetBusID = system_get_busid,
.GetDeviceID = system_get_deviceid
};
上面这些函数包括:系统初始化,系统memory map, 系统退出等。注意这个结构是在定义的同时复制的,用的是圆点, 可以对一部分成员变量赋值。
DirectFB本身自带了fbDev、x11等多个graphics system 的实现,每个实现就是一个动态链接库。
这些动态链接库很可能同时存在的,只有在运行时才会根据实际情况自动加载(用户可以在config file中指定, system=<system>,或者缺省的就是fbDev)。在运行时,这些动态链接库必须放在特定的目录中,例如directfb/lib/directfb/systems, 该目录在编译的时候指定的。
动态链接库的名字有一定的约定, 以libdirectfb_开头,以.so 结尾的,例如libdirectfb_devmem.so,libdirectfb_fbdev.so等。
dfb_system_lookup() 调用的第一个函数是direct_modules_explore_directory(),这个函数我们还会经常接触,它的作用就是在指定的目录中,搜索modules(一般是动态链接库的形式存在),打开这是module,调用module中初始化函数完成初始化工作,最后把所有满足条件的module加入到一个链表中。
在看direct_modules_explore_directory()代码之前,我们先看看它的输入参数dfb_core_systems,这是一个全局变量,它是连接DirectFB与各个不同的graphics system 具体实现之间的桥梁。它的定义在DEFINE_MODULE_DIRECTORY中,展开这个宏定义可见,dfb_core_systems实际上是DirectModuleDir的结构,
struct __D_DirectModuleDir {
pthread_mutex_t lock;
const char *path;
unsigned int abi_version;
DirectLink *entries;
DirectModuleEntry *loading;
};
其中:
path是moduel所在的路径
entries就是包含所有graphics system 实现的链表。
那么这种连接是如何建立起来的呢?
首先dfb_core_systems是以宏的形式定义在directfb core 中的【src\core\System.c】, 而在<core/system.h>中dfb_core_systems定义为一个外部变量【extern】, 这个头文件实际为各个graphics system实现所包含<core/system.h>。这样core中定义的变量就可以为各个动态库所使用。下一章,我们就具体分析direct_modules_explore_directory()的代码。