DirectFB-1.5.0移植及介绍

最近在自己看的android代码中,发现有这个DirectFB,找了点资料,了解个大概。


一.  DirectFB简介

            DirectFB是一个轻量级的提供硬件图形加速,输入设备处理和抽象的图形库,它集成了支持半透明的视窗系统以及在LinuxFramebuffer驱动之上的多层显示。它是一个用软件封装当前硬件无法支持的图形算法来完成硬件加速的层。DirectFB是为嵌入式系统而设计。它是以最小的资源开销来实现最高的硬件加速性能。

 

二. DirectFB移植准备

                     主机环境:32位Ubuntu 10.10

                     交叉编译工具:arm-linux-gcc-4.5.1

                                 下载地址:http://code.google.com/p/mini6410-debian/downloads/detail?name=arm-linux-gcc-4.5.1-v6-vfp-20101103.tar.gz&can=2&q=

                     DirectFB版本:DirectFB-1.5.0.tar.gz

                                  下载地址:http://www.directfb.org/index.php?path=Main%2FDownloads

                     DirectFB测试用例版本:DirectFB-examples-1.5.2.tar.gz

                                   下载地址:http://www.directfb.org/index.php?path=Main%2FDownloads&page=1

                     DirectFB依赖库:freetype-2.4.4.tar.gz,jpegsrc.v8c.tar.gz,libpng-1.2.44.tar.gz,zlib-1.2.5.tar.gz

                                    freetype-2.4.4.tar.gz下载地址:http://download.csdn.net/source/3214785

                                    jpegsrc.v8c.tar.gz下载地址:http://download.csdn.net/source/3567307

                                    libpng-1.2.44.tar.gz下载地址:http://download.csdn.net/source/3567317

                                    zlib-1.2.5.tar.gz下载地址:http://download.csdn.net/source/3567321

 

三. DirectFB移植步骤

环境变量配置:

             export  PREFIX=/usr                         

             export  DEST_DIR=/home                //以上两个环境变量的是移植后库生成的位置,最好是把以后有提到的库都存放到/home目录下

             export PATH=$PATH:/home/opt/FriendlyARM/toolschain/4.5.1/bin
             export CC=arm-none-linux-gnueabi-gcc
             export LDFLAGS=-L$DEST_DIR$PREFIX/lib
             export CFLAGS="-g -I$DEST_DIR$PREFIX/include"
             export PKG_CONFIG_PATH=$DEST_DIR$PREFIX/lib/pkgconfig
             export FREETYPE_CFLAGS="-I${DEST_DIR}${PREFIX}/include/freetype2 -I${DEST_DIR}${PREFIX}/include"
             export PKG_CONFIG_PATH=${DEST_DIR}${PREFIX}/lib/pkgconfig
             export PKG_CONFIG_LIBDIR=$PKG_CONFIG_PATH
             export CFLAGS="-I${DEST_DIR}${PREFIX}/include/"
             export LDFLAGS="-L${DEST_DIR}${PREFIX}/lib"
             export LIBPNG_CFLAGS="-I${DEST_DIR}${PREFIX}/include/libpng12"
             export LIBPNG_LIBS="-L${DEST_DIR}${PREFIX}/lib -lpng12"
             export FREETYPE_CFLAGS="-I${DEST_DIR}${PREFIX}/include/freetype2 -I${DEST_DIR}${PREFIX}/include"
             export DIRECTFB_CFLAGS="-I${DEST_DIR}${PREFIX}/include/directfb -I${DEST_DIR}${PREFIX}/include"
             export FREETYPE_LIBS="-L${DEST_DIR}${PREFIX}/lib -lfreetype"

 移植步骤:

             1.

                #Make zlib
               cd $ZLIB                     
               ./configure --prefix=$PREFIX
               make
               make DESTDIR=$DEST_DIR install

            2.

               cd $LIBPNG
               ./configure --prefix=$PREFIX --host=arm-none-linux-gnueabi

               make
               make DESTDIR=$DEST_DIR install

            3.
               cd $LIBJPEG
               ./configure --prefix=$PREFIX --host=arm-none-linux-gnueabi

               make
               make DESTDIR=$DEST_DIR install

            4.

               cd $FREETYPE
               ./configure --prefix=$PREFIX  --host=arm-none-linux-gnueabi
               make
               make DESTDIR=$DEST_DIR install

           5.

              cd $DFB
              ./configure --host=arm-none-linux-gnueabi  --prefix=$PREFIX --disable-x11 --with-gfxdrivers=none --enable-jpeg --enable-png --enable-freetype --with-inputdrivers=linuxinput
              make
              make DESTDIR=$DEST_DIR install

              错误及解决办法:

                               1. ../../lib/direct/atomic.h:188:70: error: expected ',' or '...' before 'new'

                                     解决办法:进入到atomic.h文件,把关键字 new 改成new_1等任意不是关键词。

                               2. ../../lib/direct/serial.h:112:14: error: invalid conversion from 'void*' to 'volatile int*'
                                   ../../lib/direct/serial.h:112:14: error:   initializing argument 2 of 'int _D__atomic_add_return(int, volatile int*)'

                                      解决办法:进入到atomic.h文件,把有这方面的调动, 通过强制转换把(void *) -> (volatile int *)

           6.

                cd $DFBEXAMPLE

                ./configure --prefix=$PREFIX --host=arm-none-linux-gnueabi
                 make  
                 make DESTDIR=$DEST_DIR install

           这样就完成了基本的DirectFB的移植,把/home/usr目录下的全部文件拷贝到开发板的/usr下,运行测试用例就知道成不成功了。

 

四. DirectFB的硬件加速配置

             环境说明:这么加速你有移植成功了DirectFB,且你的开发板支持硬件加速功能。不同的硬件平台有不同的配置,我这里就说说我的配置。这里所说的目录都是/home/usr下。

 

步骤:

             编译你的硬件加速模块,会生成相应的库文件。把生成的所有库放到/home/usr/lib下。

             在/home/usr/lib/directfb-1.5-0目录下,创建目录gfxdrivers,并把编译硬件模块的有关DirectFB的库放到此目录下,我这里的库文件是libdirectfb_gal.so.

             在/home/usr目录下,创建目录etc

             进入到/home/usr目录下,在终端输入:no-software>>directfbrc

            

             完成以上步骤后DirectFB就可以支持相应的硬件加速了。


1. 概述

   ================   
   本文主要研究DirectFB及其向上向下的接口,顺带讲一下QT搭配DirectFB使用的一些笔记。
   其他,如DirectFB的内部结构、Qt的内部结构、及其他GUI系统如android不在本文讨论范围内。
   本文会设计一些DirectFB的2D加速函数介绍,3D加速不再本文讨论范围内。

   ================   

   桌面GUI系统涉及很多图像运算,比如画点、画线、填充、透明度处理、平滑度处理、层的叠加、字体处理、贴图等等。如果这些运算都由CPU来处理,那这将是对CPU的一个很大的负载。在QT的文档中曾说到,假如一个图形运算让加速设备来做需要1到2个CLK,同样的图形运算让CPU来算则至少需要20个CLK,而且,对于嵌入式SoC来说,CPU的频率和SDRAM/DRAM的带宽始终是图形运算的瓶颈。所以这些芯片的图形加速能力有无、高低,最终决定其目标GUI的质量。

   近两年嵌入式设备主芯片越来越多的嵌入了2D/3D加速功能,由此软件可以搭建越来越复杂、炫酷、先进的桌面系统,如Qt/Android等。这些加速硬件,通常也因其是否拥有私有内存、是否支持3D、加速接口是否可编程等特性而分为三六九等。硬件的加速功能如果要在目标GUI系统中跑起来,还得需要一些软件中间层为不同的硬件加速提供同一的接口,并且为上层GUI提供服务。DirectFB就是这样一个软件中间层,它主要为上层提供2D加速服务。OpenGL/ES 主要为上层提供3D加速服务。

   DirectFB是一个专门针对Linux图形库设计的图形加速中间层。它的上层直接面向图形库比如QT,提供如显示、画图、输入设备控制等服务,他的下层直接面向GFX加速硬件,要求硬件驱动实现全部或部分预定的画图函数。


DirectFB-1.5.0移植及介绍_第1张图片


2. DirectFB给上层图形库提供的接口调用


   2.1 主要接口


    DirectFB由超级接口IDirectFB为上层提供接口调用,其他所有接口都由此接口生成,这些接口内容包括:

    =========================
    . IDirectFBScreen
    . IDirectbFBDisplayLayer
    . IDirectFBSurface

    =========================

    显示屏幕、显示层、显示表面,三者之间的关系可这样表述:

    显示屏幕<-Output(connector)<-IDirectFBScreen<-(mixer)-DisplayLayers <-DisplayLayer's IDirectFBSurface<-gfx Accelarator <--显卡/或CPU运算画图

    首先,用户在显示屏幕上看到一个Screen的输出,这个Screen由多个画面组成(比如同时包含:背景图片,前景视频/字幕/图片)。组成Screen的每个画面,都由一个单独的DisplayLayer来处理。多个DisplayLayers由Mixer来决定叠加的顺序/位置/以及透明度等。单独一个显示层DisplayLayer,可自由控制输出大小(放大/缩小)、背景颜色、翻转等。DisplayLayer所显示的数据(比如解析JPEG产生的RGB数据),则需要在DisplayLayer上生成一个Surface来显示,Surface控制实际的贴图操作,比如:画点/线/框/填充/变换位数、色深、分辨率,等等, Surface可直接和硬件加速打交道(gfxcard)。

    以上描述的DisplayLayers和Surface都是Screen的后端,Screen的前端(就是输出部分),还有Encoder,Output等概念。Encoder着重描述输出信号的编码参数,Output着重描述输出接口. 它们有以下重要成员:
     Standards  :配置输出制式(标清/高清/PAL/NTSC/>>扩展<<)
     Signals    :配置输出信号(VGA/YC/CVBS/RGB/YCBCR/HDMI/656/>>扩展<<)
     Connectors :配置输出接口(VGA/SCART/YC/CVBS/SCART2/COMPONENT/HDMI/>>扩展<<)
     Resolution :配置输出分辨率(directfb.h中所列举的常见分辨率/>>扩展<<)
    从Screen到Encoder,再从Encoder到Output的connector,最后到显示屏幕,DirectFB的底层实现者需要做的就是根据目标硬件的特性,实现这条路线中各条通路,DirectFB的使用者需要做的就是通过Screen的成员函数配置、使用这些通路。

    以上表述中,关于每个节点功能的详细表述可能有误,但其所处的位置和大概的介绍应该是对的。笔者曾参与SigmaDesigns系列解码芯片和PNX8735系列的研发工作,发现DFB的这种结构设计非常接近于这类芯片已有的硬件设计。    
    这部分代码主要分布在子目录“src/display”下。


    =========================
    IDirectFBImageProvider
    IDirectFBVideoProvider
    IDirectFBFont

    =========================

    参见源代码:idirectfbimageprovider_dfiff.c / idirectfbimageprovider_gif.c / idirectfbimageprovider_jpeg.c / idirectfbimageprovider_png.c 

    DFB对dfiff/gif/jpeg(libjpeg.a)/png(libpng.a)第三方软件解码库做了简单封装,以在DFB的框架内在恰当的时候去解码或贴图。
    在子目录“interfaces/IDirectFBImageProvider”下有具体图片格式的实现,具体是否生效取决于configure参数。

    举例JPEG通过imageprovider解码和贴图的过程,具体参见以下代码:
  • tests/dfbtest_scale.c
  • lib/direct/interface.c
  • lib/direct/interface_implementation.h
  • interfaces/IDirectFBImageProvider/idirectfbimageprovider_jpeg.c

    1. idirectfbimageprovider_jpeg.c会把自己的'funcs'注册到interface链表中,注意,Register的调用是通过GNU的__attribute__((constructor))实现的,即进入main函数之前已经注册,没有显式调用注册函数。

    2. 测试代码通过CreateImageProvider调用创建provider,此函数会定位到interface.c::DirectGetInterface()中。DirectGetInterface函数遍历interface链表,首先匹配provider类型,再通过具体implementation的Probe函数回调挨个匹配,Probe函数有的是通过文件扩展名匹配,有的需要读取文件内容进行匹配(这里JPEG是通过文件扩展名匹配的)。与某种类型的provider完全匹配后,返回provider,调用其Construct函数. test程序再调用GetSurfaceDescription获取图片的参数,再用此参数通过函数CreateSurface创建目标显示表面,再通过provider的RenderTo函数往目标Surface贴图。
    视频采集与显示IDirectFBVideoProvider, VideoProvider分两种:
  • idirectfbvideoprovider_v4l.c: 直接从v4l设备读取yuv数据,软件贴图显示视频。
  • idirectfbvideoprovider_gif.c: 封装gif第三方库,软件显示gif动画。
    字体点阵的解码贴图IDirectFBFont,FontProvider分两种:
  • idirectfbfont_ft2.c: 软件封装freetype2库,软件解析贴图字体矩阵。
  • idirectfbfont_dgiff.c: 封装dgiff.c库.

    每种类型的provider,其贴图/播放控制函数都位于其结构定义IDirectFBXXXProvider(其中XXX=Image/Video),或者IDirectFBFont中。


    =========================
    IDirectFBEventBuffer
    IDirectFBDataBuffer
    IDirectFBInputDevice

    =========================

    IDirectFBEventBuffer: 事件同步机制,一端接入产生事件的设备,使用PostEvent之类的接口递交事件,另一端使用WaitForEvent之类的接口等待事件,使用GetEvent之类的接口获取事件。
    常用与输入设备

    IDirectFBDataBuffer: 数据DataBuffer缓冲,提供同步等待功能,并提供CreateXXXProvider(XXX=Image/Video)功能,在原代码中被广泛使用.

    IDirectFBInputDevice: 输入设备接口
    

   2.2. QT与DirectFB之间的关系

       QT从4.3版本开始尝试加入DirectFB,直到4.6版本以后才稳定下来。DirectFB至今也到了1.5.0版本(201106),给图形库提供的硬件加速接口也在不断的扩充。
       需要说明,DirectFB并不包含QT的所有画图函数的实现,这一点在QT的文档中有表述。
       QT中调用的DirectFB代码,主要分布在子目录"src/plugins/gfxdrivers/directfb/"下,上面提到的几乎所有接口都有涉及。

    笔者移植QT+DirectFB过程中,使用了QT的Configure选项:
        ./configure -embedded mips -qt-gfx-directfb -little-endian -prefix /tftpboot/install -prefix-install -v
    运行时敲入命令:
        ./browser -qws -display directfb
        

3. DirectFB给底层硬件提供的接口。

   3.1 输入设备接口: InputDrivers  

   输入设备的管理位于核心代码src/core/input.c,输入设备的接口定义位于src/core/input_driver.h。 DFB对输入设备的管理、使用,只是简单的对输入设备的设备文件进行封装,并没有真正的去驱动某种输入设备。
   要添加一个输入设备,首先要在DFBROOT目录下的子目录"inputdrivers/"下添加一个源文件,或者是在"inputdrivers/"目录下修改一个已有的源文件。 "inputdrivers"的名称来自于“src/core/input.c”头上的DEFINE_MODULE_DIRECTORY定义,所以不同DFB版本对应的目录名称可能不同。 其次,要在你的源文件中引用头文件'core/input_driver.h'并实现InputDriverFuncs所定义的函数:
  • driver_get_info(): 用于获取driver的vendor/name/version等信息。
  • driver_get_available(): 用于判断设备是否可用,返回值表示当前driver可驱动的设备数量。
  • driver_open_device(): 打开输入设备文件,并开启线程监听设备输入。
  • driver_get_keymap_entry(): 键值修复/更改/映射函数,好像只有keyboard才用,用于处理组合键/大小写/小键盘等键值。
  • driver_close_device: 关闭监听线程,关闭设备文件

    这些函数的具体调用路径如下:
  • 涉及源文件: src/core/input.c,  src/core/input_driver.h, src/core/core.c,例子inputdrivers/keyboard/keyboard.c
  • Core初始化->InputCore初始化->input.c:init_devices():
  • 遍历inputdrivers下所有输入设备驱动: 调用driver_get_info()获取驱动信息,调用driver_get_available()判断当前设备是否可用,调用driver_open_device()打开并监听设备
  • Core关闭/Suspend: 调用driver_close_device()关闭所有已打开设备,然后清空事件缓冲。
  • Core Resume: 再次调用driver_open_device()打开Suspend之前处于开启状态的设备。Suspend/Resume由IDirectFB.Suspend/Resume接入,由用户控制可用于休眠操作。
  • driver_open_device()中会打开一个线程监听设备输入,输入键值通过dfb_input_dispatch()分发,调用堆栈包括driver_get_keymap_entry()用于重新映射键值。键值最终通过fusion_reactor_dispatch()向上层分发事件。

    如果你是新添加的一个.c文件,可能你还需要修改configure文件和Makefile.XXX文件。


    3.2 硬件加速gfxcard.
    
    * 涉及源代码src/core/graphics_driver.h, src/core/gfxcard.h, src/core/gfxcard.c, 举例:gfxdrivers/pxa3xx/

    这一章很复杂,笔者也只能泛泛而谈。
    个人认为,DirectFB最重要的功能就是能够统一不同的硬件显示加速设备的各种加速功能为上层图形库所用。
    
    gfx加速在DFB中分两层概念:
  • graphics driver : 需要实现gfxcard.h::GraphicsDriverFuncs所定义的所有函数。
  • graphics device : 按需实现gfxcard.h::GraphicsDeviceFuncs所定义的函数。

    graphics_driver是core的一个模块,它的函数调用堆栈跟InputDriver很像,依次为:
    GraphicsDriverFuncs的调用堆栈:
    src/core/gfxcard.c: dfb_graphics_core_initialize()->

    dfb_gfxcard_find_driver()   
     {Driver.Probe()&Driver.GetDriverInfo()}->
    Driver.InitDevice() -> 
    Device.EngineReset()   

    真正实现加速功能的,是graphics device的函数调用。先看看DirectFB是如何把用户的画图动作,转化为gfxcard的硬件实现的。
    前面讲过Surface控制实际的贴图操作,所以下面的调用堆栈跟踪都从IDirectFBSurface开始。
    上层用户可通过IDirectFBSurface.GetAccelerationMask()的返回值判断所需画图动作是否可以加速,具体调用堆栈如下:

    src/display/idirectfbsurface.c:IDirectFBSurface_Construct() -> IDirectFBSurface_GetAccelerationMask() -> src/core/gfxcard.c:dfb_gfxcard_state_check()
    -> gfxdrivers/pxa3xx/pxa3xx.c & gfxdrivers/pxa3xx/pxa3xx_blt.c: pxa3xxCheckState()

    即: Device的CheckState()函数,是用于判断所需加速功能是否可用的。

    一次具体的画图操作(比如:填充矩形),调用堆栈如下:
    src/display/idirectfbsurface.c:IDirectFBSurface_FillRectangle()    -> src/core/gfxcard.c: dfb_gfxcard_fillrectangles()

          dfb_gfxcard_state_check( state, DFXL_FILLRECTANGLE )      ->          gfxdrivers/pxa3xx/pxa3xx_blt.c: pxa3xxCheckState()
          dfb_gfxcard_state_acquire( state, DFXL_FILLRECTANGLE )    ->        gfxdrivers/pxa3xx/pxa3xx_blt.c: pxa3xxSetState()
      card->funcs.FillRectangle( driver_data, device_data, &rect )     ->         gfxdrivers/pxa3xx/pxa3xx_blt.c: pxa3xxFillRectangle()

    即: Surface在调用每一个加速画图函数之前,都会先调用Device.CheckState()判断所需函数是否可达,再调用Device.SetState()告知具体device即将使用此类加速函数(pxaxxx是在SetState()中确定接下来该使用哪个加速函数来实现当前画图功能),然后调用Device的具体加速函数画图。

    了解了画图加速函数的调用堆栈,再来看看gfxcard支持哪些加速函数,(参考源代码src/core/gfxcard.h):

        FillRectangle     :        填充矩形
        DrawRectangle     :        画矩形
        DrawLine          :        画线
        FillTriangle      :        填充三角形
        Blit              :        位块传送(内存拷贝/移动?)
        Blit2             :        位块传送2(支持源坐标)
        StretchBlit       :        位块传送并拉伸
        TextureTriangles  :        ?

     可以看出,列举的函数都是2D加速函数。


4. DirectFB移植事项
   
   DirectFB是一个软件中间层,它为底层的硬件驱动和上层的GUI提供了统一的接口调用,但它不做任何实际画图操作。要移植DirectFB到目标嵌入式硬件上,为了最大限度利用硬件的加速功能,移植的过程中要考虑以下问题:
  • 首先要实现DirectFB的显示路径。以Screen为切入点,根据目标硬件的特性,向前实现各种Encoder->Output的显示通路,向后实现Screen的各种显示Layer->Surface。
  • 如果目标硬件支持JPEG/PNG/GIF的硬件解码,那么你可能需要实现对应的ImageProvider以代替软件解码。
  • 如果目标硬件支持多种Video格式的硬件解码,那么你可能需要实现对应的VideoProvider以实现硬件解码播放的功能。
  • 如果目标设备具有自己的输入小键盘(GPIO扩展、或者其他特殊输入设备),那么你可能需要实现自己的InputDriver。
  • 如果目标硬件具有GFX加速引擎,那么你可能需要实现对应的gfxdriver以及实现gfxdevice中的各种画图函数。

   DirectFB移植的过程中,因尽量保证idirectb(各种接口结构、函数)不能变,可适当扩展其宏定义。



在上一篇文章中启动好了framebuffer,现在可以用这样一个简单的例子来检验下效果。

来自DirectFB官方网站的简单程序,在屏幕上画一条线。

 
编译后,执行 成功了。

 

Simple fullscreen application that draws a horizontal line.

代码如下:

#include <stdio.h>

#include <unistd.h>

#include <directfb.h>

 

static IDirectFB *dfb = NULL;

static IDirectFBSurface *primary = NULL;

static int screen_width = 0;

static int screen_height = 0;

 

#define DFBCHECK(x...)                                                  /

{                                                                       /

DFBResult err = x;                                              /

/

if (err != DFB_OK)                                              /

{                                                               /

fprintf( stderr, "%s <%d>:/n/t", __FILE__, __LINE__ );  /

DirectFBErrorFatal( #x, err );                          /

}                                                               /

}

 

int main(int argc, char **argv)

{

DFBSurfaceDescription dsc;

 

DFBCHECK (DirectFBInit (&argc, &argv));

DFBCHECK (DirectFBCreate (&dfb));

 

DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));

dsc.flags = DSDESC_CAPS;

dsc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;

 

DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));

DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));

DFBCHECK (primary->FillRectangle (primary, 00, screen_width, screen_height));

 

DFBCHECK (primary->SetColor (primary, 0x800x800xff0xff));

DFBCHECK (primary->DrawLine (primary,

0, screen_height / 2,

screen_width - 1, screen_height / 2));

DFBCHECK (primary->Flip (primary, NULL, 0));

sleep(5);

 

primary->Release(primary);

dfb->Release(dfb);

return 23;

}

下面我们来看这个程序,前三行:

#include <stdio.h>

#include <unistd.h>

#include <directfb.h>

为头文件包含。第5到第8行:

static IDirectFB *dfb = NULL;

static IDirectFBSurface *primary = NULL;

static int screen_width = 0;

static int screen_height = 0;

为全局变量定义。第10到第19行为出错处理宏:

#define DFBCHECK(x...)                                                  /

{                                                                       /

DFBResult err = x;                                              /

/

if (err != DFB_OK)                                              /

{                                                               /

fprintf( stderr, "%s <%d>:/n/t", __FILE__, __LINE__ );  /

DirectFBErrorFatal( #x, err );                          /

}                                                               /

}

此宏定义在官方给的程序中很常见,确实也挺好用。第21到46行为主程序代码段。

 

其中,第23行:

DFBSurfaceDescription dsc;

为局部变量定义,dsc为平面属性描述变量,用以创建与其相匹配的平面。

 

第25到26行:

DFBCHECK (DirectFBInit (&argc, &argv));

DFBCHECK (DirectFBCreate (&dfb));

为DirectFB初始化函数,第25行用以初始化命令行参数,而第26行用以创建DirectFB的主接口。

 

第28到30行对平面属性进行了初始化,其中第28行:

DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));

设置了DirectFB的主接口的同步等级,DFSCL_FULLSCREEN与DFSCL_EXCLUSIVE相同,均为非共享的同步等级,在总接口使用CreateSurface方法创建平面时,将创建全屏平面。

 

第29到30行:

dsc.flags = DSDESC_CAPS;

dsc.caps = DSCAPS_PRIMARY | DSCAPS_FLIPPING;

说明了即将创建的平面的属性,在本例中,我们要创建一个可flip的主平面。

 

第32到34行:

DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));

DFBCHECK (primary->GetSize (primary, &screen_width, &screen_height));

DFBCHECK (primary->FillRectangle (primary, 0, 0, screen_width, screen_height));

创建了一个平面,并对此平面作了相应的初始化操作。第33行获取了此平面(全屏主平面)的宽高值,第34行在平面上画了一个黑色(DirectFB系统默认颜色)的屏幕大小矩形,此函数是受stb225平台硬件加速支持的。

 

第36到41行:

DFBCHECK (primary->SetColor (primary, 0x80, 0x80, 0xff, 0xff));

DFBCHECK (primary->DrawLine (primary,

0, screen_height / 2,

screen_width - 1, screen_height / 2));

DFBCHECK (primary->Flip (primary, NULL, 0));

sleep(5);

的功能为在屏幕正中心画一条横线,并显示5秒钟。第36行设置了线的颜色,第37到39行进行画线操作,将36行所设置颜色的线画到primary平面上,第40行将画有横线的平面显示出来,第41行,程序休眼5秒,即此线在屏幕上显示5秒。

 

第43到45行:

primary->Release(primary);

dfb->Release(dfb);

return 23;

程序作了相应的清理操作,而后退出。

 

DirectFB程序中,如果定义了接口,则一定需要使用相应的Release方法将此接口进行释放,否则可能引起内存泄漏问题,甚至可能破坏程序的稳定性。






from:http://blog.csdn.net/wangjijian/article/details/6161889

由于第一次搞嵌入式,交叉编译DirectFB费了一些周折。

 

首先记录下编译的过程

 

 

1 准备源文件包,下载freetype2.4.4和DirectFB-1.4.11.tar.gz,解压。

 

2 交叉编译安装freetype

 

 export CC=arm-none-linux-gnueabi-gcc

 

 指定交叉编译器。(我用的交叉编译器来自source G++) 

 

 ./configure --host=arm-linux --prefix=/opt/freetype/

 make

 make install

 

freetype安装完毕

 

3 交叉编译directfb

 

 export LDFLAGS=-L/opt/freetype/lib
 export CFLAGS="-g -I/opt/freetype/include"
 ./configure --host=arm-linux --prefix=$PREFIX --with-gfxdrivers=none --with-inputdrivers=all --disable-png --disable-jpeg --disable-zlib --enable-sdl=no --enable-gif=no --disable-x11
 make
 make install

 交叉编译directfb完毕。

 

4 修改/etc/bash.bashrc 把新安装的库的路径,LD_LIBRARY_PATH ,PKG_CONFIG_PATH , PATH 设置完毕。

 

   source /etc/bash.bashrc 使路径生效。

 

5 交叉编译自己的程序。

 

 arm-none-linux-gnueabi-gcc `pkg-config --cflags --libs directfb`fb.c -o fb

 

 交叉编译成功 。

 

总结:期间遇到的一些问题

1 要交叉编译自己的程序,需要先交叉编译所依赖的库

 

2 如何交叉编译库

  在网上查找学习后,通过如下命令并不成功

 ./configure --host=arm-linux --prefix=$PREFIX --with-gfxdrivers=none --with-inputdrivers=all --disable-png --disable-jpeg --disable-zlib --enable-sdl=no --enable-gif=no --disable-x11

 原因:在执行configure时 指定了 --host=arm-linux 但是没有指定交叉编译器,系统没有找到交叉编译器,貌似就用了gcc编译,最后并未生成arm-linux的库,在编译后续的库时链接会找不到合适的库。需要先

 

 export CC=arm-none-linux-gnueabi-gcc

 

 指定交叉编译器。

 

3 交叉编译好库之后 设置好路径后就可以交叉编译程序了。

 

 

 

 

下面引用一篇关于交叉编译链接库配置的文章

 

 

 

交叉编译的时候不能使用本地(i686机器,即PC机器,研发机器)机器上的库,但是在做编译链接的时候默认的是使用本地库,即/usr/lib,/lib两个目录。因此,在交叉编译的时候,要采取一些方法使得在编译链接的时候找到需要的库。
首先,要知道:编译的时候只需要头文档,真正实际的库文档在链接的时候用到。 (这是我的理解,假如有不对的地方,敬请网上各位大侠指教) 然后,讲讲如何在交叉编译链接的时候找到需要的库。
(1)、交叉编译时候直接使用-L和-I参数指定搜索非标准的库文档和头文档的路径。例如:
arm-linux-gcc test.c -L/usr/local/arm/2.95.3/arm-linux/lib -I/usr/local/arm/2.95.3/arm-linux/include
(2)、使用ld.so.conf文档,将用到的库所在文档目录添加到此文档中,然后使用ldconfig命令刷新缓存。
(3)、使用如下命令:
$ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/arm/2.95.3/arm-linux-lib
参见《ld.so.conf 文档和PKG_CONFIG_PATH变量》这篇文章。
通过环境变量LD_LIBRARY_PATH指定动态库搜索路径(!)。
通过设定环境变量LD_LIBRARY_PATH也可以指定动态库搜索路径。当通过该环境变量指定多个动态库搜索路径时,路径之间用冒号":"分隔。
不过LD_LIBRARY_PATH的设定作用是全局的,过多的使用可能会影响到其他应用程序的运行,所以多用在调试。(LD_LIBRARY_PATH 的缺陷和使用准则,可以参考《Why LD_LIBRARY_PATH is bad》 )。通常情况下推荐还是使用gcc的-R或-rpath选项来在编译时就指定库的查找路径,并且该库的路径信息保存在可执行文件中,运行时它会直接到该路 径查找库,避免了使用LD_LIBRARY_PATH环境变量查找。
(4)、交叉编译时使用软件的configure参数。例如我编译minigui-1.3.3,使用如下配置:
#!/bin/bash
rm -f config.cache config.status
./configure --build=i686-linux --host=arm-linux --target=arm-linux /
CFLAGS=-I/usr/local/arm/2.95.3/arm-linux/include /
LDFLAGS=-L/usr/local/arm/2.95.3/arm-linux/lib /
--prefix=/usr/local/arm/2.95.3/arm-linux /
--enable-lite /
--disable-galqvfb /
--disable-qvfbial /
--disable-vbfsupport /
--disable-ttfsupport /
--disable-type1support /
--disable-imegb2312py /
--enable-extfullgif /
--enable-extskin /
--disable-videoqvfb /
--disable-videoecoslcd
这里我配置了CFLAGS和LDFLAGS参数,这样一来,我就不用去修改每个Makefile里-L和-I参数了,也不用再去配置LD_LIBRARY_PATH或改写ld.so.conf文档了。

Linux下动态库使用小结
1. 静态库和动态库的基本概念
静态库,是在可执行程序连接时就已经加入到执行码中,在物理上成为执行程序的一部分;使用静态库编译的程序运行时无需该库文件支持,哪里都可以用,但是生成的可执行文件较大。动态库,是在可执行程序启动时加载到执行程序中,可以被多个可执行程序共享使用。使用动态库编译生成的程序相对较小,但运行时需要库文件支持,如果机器里没有这些库文件就不能运行。
2. 如何使用动态库
如何程序在连接时使用了共享库,就必须在运行的时候能够找到共享库的位置。linux的可执行程序在执行的时候默认是先搜索/lib和/usr/lib这两个目录

 

 

 

 

Makefile预定义变量
  含义
  $*
  不包含扩展名的目标文件名称。
  $+
  所有的依赖文件,以空格分开,并以出现的先后为序,可能包含重复的依赖文件。
  $<
  第一个依赖文件的名称。
  $?
  所有的依赖文件,以空格分开,这些依赖文件的修改日期比目标的创建日期晚。
  $@
  目标的完整名称。
  $^
  所有的依赖文件,以空格分开,不包含重复的依赖文件。
  $%
  如果目标是归档成员,则该变量表示目标的归档成员名称。例如,如果目标名称为
  mytarget.so(image.o),则 $@ 为 mytarget.so,而 $% 为 image.o。
  AR
  归档维护程序的名称,默认值为 ar。
  ARFLAGS
  归档维护程序的选项。
  AS
  汇编程序的名称,默认值为 as。
  ASFLAGS
  汇编程序的选项。
  CC
  C 编译器的名称,默认值为 cc。
  CFLAGS
  C 编译器的选项。
  CPP
  C 预编译器的名称,默认值为 $(CC) -E。
  CPPFLAGS
  C 预编译的选项。
  CXX
  C++ 编译器的名称,默认值为 g++。
  CXXFLAGS
  C++ 编译器的选项。
  FC
  FORTRAN 编译器的名称,默认值为 f77。
  FFLAGS
  FORTRAN 编译器的选项。


你可能感兴趣的:(DirectFB-1.5.0移植及介绍)