【zz】DirectFB

http://blog.chinaunix.net/u/30686/showart.php?id=1946188

DirectFB在Davinci平台上的应用分析报告

1.概述

根据目前STB的媒体表现形式不足和将来的功能扩展需求,需要有一套稳定、灵活的显示设备、输入设备适配层。 DirectFB(以下简称DFB)是针对嵌入式系统资源和性能特点而设计的一套图形库。我们在这里对DFB在Davinci平台上的可用性做一次分析。

分析的主要内容有:

1)      代码的编译选项

2)      图形库主要特性

3)      典型应用程序启动、画图显示过程分析

4)      分析DFB在Davinci平台上应用的可行性

2.编译选项

./configure CC=arm_v5t_le-gcc CXX=arm_v5t_le-g++ AR=arm_v5t_le-ar RANLIB=arm_v5t_le-ranlib LD=arm_v5t_le-ld CFLAGS="-O2 -ffast-math -pipe" CPPFLAGS=-I/home/cnc/devkit/arm/v5t_le/target/usr/include   LDFLAGS="-L/home/cnc/devkit/arm/v5t_le/target/lib -L/home/cnc/devkit/arm/v5t_le/target/usr/lib" –host=arm-linux –build=i386 –prefix=/home/cnc/root-nfs/usr/local –exec-prefix=/usr/local –enable-debug –enable-trace    –enable-static –enable-multi –enable-fbdev –without-tools   –with-gfxdrivers=davinci

上面的编译选项中:   

–enable-multi 允许多进程间共享显示设备(下面的分析都是基于此编译条件)
       –enable-debug 允许调试信息与断言
       –enable-trace 允许运行时堆栈跟踪

当DFB图形库编译安装成功后,我们需要编写DFB在目标系统上的运行配置。

directfbrc是DFB图形库启动的配置文件,配置方式分为:

系统级配置:a system-wide one stored in /etc/directfbrc

用户级配置:a per-user $HOME/.directfbrc which may override system settings.

也可以通过应用程序(basename of argv[0]))传入:/etc/directfbrc.$0 或$HOME/.directfbrc.$0

下面是配置文件的具体示例,更详细的配置方式请参阅文档Man page of DIRECTFBRC.mht:

system=fbdev

fbdev=/dev/fb0

mode=720x576

depth=16

pixelformat=RGB16

systems指定显示系统接口,目前可选接口有:

dvevm:直接操作硬件地址空间适配层代码

fbdev: 输出到frame buffer。

osx:   输出到mac os上。

vnc: 输出到Virtual Network Computing(类似于微软远程桌面的一个协议)。

x11: 输出到X Window上

sdl: 输出到Simple DirectMedia Layer。

这里我们使用framebuffer接口。

mode指定显示设备的分辨率;

depth为像素位数;

pixelformat指定显示设备像素格式。

3.DFB图形库关键模块-fusion

在介绍DFB之前先介绍一下DFB多进程共享同一显示资源的核心模块fusion。在传统的DFB应用中,所有的应用程序都在一个进程中,在性能上,有一些优势,然而一个应用程序不稳定会造成整个系统的不稳定。若采用C/S模型,无疑是重蹈X Widnow的覆辙,会丧失性能上的优势。所以DirectFB采用了另外一种方式,与C/S相区别,称之为主从模型(Master/Slave)。它加了一个称之为fusion的内核模块。Fusion是熔化的意思,多个应用程序在不同的进程空间里,通过这个内核模块通信,在这里,一切都溶为一体。Master应用程序负责初始化一个称为竟技场(Arena)的东西,其它Slave应用程序可以加入(join)或者退出(leave)竟技场。当Master退出时,则其它所有Slave都必须退出。Fusion里采用了Reactor模式,每个应用程序可以通过ioctl向reactor注册事件处理器,当有事件发生时,reactor会把事件写入到所注册了的应用程序的fusion文件描述符时,之后应用程序可以从fusion文件描述符里读取到事件数据。当然,应用程序也可以通过ioctl发送事件给其它应用程序,reactor也会把事件分发给其它应用程序。

/关于fusion的调用函数定义都是通过FUSION_OBJECT_METHODS这个宏定义实现的/

消息分发线程的创建

DirectFBCreate

fusion_enter>>>Master应用程序初始化或join Arena,挂在/dev/fusionN

direct_thread_create( DTT_MESSAGING, fusion_dispatch_loop, world, "Fusion Dispatch" );

fusion_dispatch_loop>>>启动消息分发线程

以注册Surface对象的Flip事件为例说明fusion注册事件流程

IDirectFB_CreateSurface>>>创建一个surface对象

IDirectFBSurface_Construct>>>

dfb_surface_attach( surface,IDirectFBSurface_listener, thiz, &data->reaction ); >>注册surface

                                                                                                       listener

fusion_reactor_attach>>注册surface 相关的回调函数

ioctl( _fusion_fd( reactor->shared ), FUSION_REACTOR_ATTACH, &attach )

发送Surface Flip事件

dfb_surface_flip( data->surface, false );>>> 改变surface buffer index

dfb_surface_notify( surface, CSNF_FLIP );>>>

dfb_surface_dispatch( surface, &notification, dfb_surface_globals );>>> 通过fusion通知进行surface_listener flip操作

下面以触摸屏为例介绍笔点事件的过程:

1)初始化时,driver_open_device创建一个进程,挂在/dev/input/event0上,等待笔点事件。

2)初始化时,应用程序创建另外一个线程,挂在/dev/fusionN(不同的应用程序N值不同)上。

3) 当有笔点事件时,通过函数调用dfb_input_dispatch–>fusion_reactor_dispatch->ioctl (FUSION_REACTOR_DISPATCH)把消息丢给内核模块。

4) 内核模块中的Reactor把事件数据写入到各个所注册的事件处理器的/dev/fusionN里。

5) 应用程序从/dev/fusionN文件中取得事件数据,并调用应用程序内部的reactor处理函数,一般是IDirectFBEventBuffer_InputReact/IDirectFBEventBuffer_WindowReact两个函数。

6) 然后,在IDirectFBEventBuffer_InputReact/IDirectFBEventBuffer_WindowReact两个函数中,调用IDirectFBEventBuffer_AddItem把事件加入到窗口的事件队列中。

7) 在应用程序的主线程中,就可以通过调用窗口的GetEvent函数从事件队列中获取事件了,最后,把获取的事件分发到各个窗口事件处理函数中。



更多内容,请参见原文链接






end