首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Qt/Embedded在嵌入式Linux系统中的应用 02

Qt/Embedded在嵌入式Linux系统中的应用 02

 1.1 Qt/Embedded的图形引擎实现基础  Qt/Embedded 的底层图形引擎基于framebuffer。Framebuffer是在Linux内核架构版本2.2以后推出的标准显示设备驱动接口。采用mmap系统调用,可以将framebuffer的显示缓存映射为可连续访问的一段内存储针。由于目前比较高级的arm体系的嵌入式CPU中大多集成了LCD控制模块,LCD控制模块一般采用双DMA控制器组成的专用DMA通道。其中一个DMA可以自动从一个数据结构队列中取出并装入新的参数,直到整个队列中的 DMA操作都已完成为止。另外一个DMA与画面缓冲区相关,这部分由两个DMA控制器交替执行,并每次都自动按照预定的规则改变参数。虽然使用了双 DMA,但这两个DMA控制器的交替使用对于CPU来说是不可见的。CPU所获得的只是由两个DMA组成的一个“通道”而已。
 Framebuffer 驱动程序的实现分为两个方面:一方面是对LCD及其相关部分的初始化,包括画在缓冲区的创建和对DMA通道的设置;另外一方面是对画面缓冲区的读写,具体到代码为read、write、lseek等系统调用接口。至于将画面缓冲区的内容输出到LCD显示屏上,则由硬件自动完成。对于软件来说是透明的。当对于DMA通道和画面缓冲区设置完成后,DMA开始正常工作,并将缓冲区中的内容不断发送到LCD上。这个过程是基于DMA对于LCD的不断刷新的。基于该特性,framebuffer驱动程序必须将画面缓冲区的存储空间(物理空间)重新映射到一个不加高缓存和写缓存的虚拟地址区间中,这样能才保证应用程序通过mmap将该缓存映射到用户空间后,对于该画面缓存的写操作能够实时的体现在LCD上。
  在Qt/Embedded 中,Qscreen类为抽象出的底层显示设备基类,其中声明了对于显示设备的基本描述和操作方式,如打开、关闭、获得显示能力、创建GFX操作对象等。另外一个重要的基类是QGfx类。该类抽象出对于显示设备的具体操作接口(图形设备环境),如选择画刷、画线、画矩形、alpha操作等。以上两个基类是 Qt/Embedded图形引擎的底层抽象。其中所有具体函数基本都是虚函数,Qt/Embedded对于具体的显示设备,如Linux的 framebuffer、Qt Virtual Framebuffer做的抽象接口类全都由此继承并重载基类中的虚函数实现。图2为Qt/Embedded中底层图形引擎实现结构。



在图2中,对于基本的framebuffer设备,Qt/Embedded用 QlinuxFbScreen来处理。针对具体显示硬件(如Mach卡、Voodoo卡)的加速特性,Qt/Embedded从 QlinuxFbScreen和图形设备环境模板类QgfxRaster继承出相应子类,并针对相应硬件重载相关虚函数。
  
Qt/Embedded 在体系上为C/S结构,任何一个Qt/Embedded程序都可以作为系统中唯一的一个GUI Server存在。当应用程序首次以系统GUI Server的方式加载时,将建立QWSServer实体。此时调用QWSServer:penDisplay()函数创建窗体,在 QWSServer:penDisplay()中对QWSDisplay::Data中的init()加以调用;根据 QgfxDriverFactory实体中的定义(QLinuxFbScreen)设置关键的Qscreen指针qt_screen并调用connect ()打开显示设备(dev/fb0)。在QWSServer中所有对于显示设备的调用都由qt_screen发起。至此完成了Qt/Embedded中 QWSServer的图形发生引擎的创建。当系统中建立好GUI Server后,其它需要运行的Qt/Embedded程序在加载后采用共享内存及有名管道的进程通信方式,以同步访问模式获得对共享资源 framebuffer设备的访问权。
  1.2 Qt/Embedded的事件驱动基础
  Qt/Embedded 中与用户输入事件相关的信号,是建立在对底层输入设备的接口调用之上的。Qt/Embedded中的输入设备,分为鼠标类与键盘类。以3.x版本系列为例,其中鼠标设备的抽象基类为QWSMouse Handler,从该类又重新派生出一些具体的鼠标类设备的实现类。该版本系列的Qt/Embedded中,鼠标类设备的派生结构如图3所示。
  与图形发生引擎加载方式类似的,在系统加载构造QWSServer时,调用QWSServer:penMouse与QWSServer:: openKeyboard函数。这两个函数分别调用QmouseDriverFactory::create()与 QkbdDriverFactory::create()函数。这时会根据Linux系统的环境变量QWS_MOUSE_PROTO与 QWS_KEYBOARD获得鼠标类设备和键盘类设备的设备类型和设备节点。打开相应设备并返回相应设备的基类句柄指针给系统,系统通过将该基类指令强制转换为对应的具体子类设备指针,获得对具体鼠标类设备和键盘类设备的调用操作。
值得注意的是,虽然几乎鼠标类设备的功能上基本一致,但由于触摸屏和鼠标底层接口并不一样,会造成对上层接口的不一致。举例来讲,从鼠标驱动接口中几乎不会得到绝对位置信息,一般只会读到相对移动量。另外,鼠标的移动速度也需要考虑在内,而触摸屏接口则几乎是清一色的绝对位置信息和压力信息。针对此类差别, Qt/Embedded将同一类设备的接口部分也给予区别和抽象,具体实现在QmouseDriverInterface类中。键盘类设备也存在类似问题,同样引入了QkbdDriver Inteface来解决。具体实现此处暂不多述。
  2 Qt/Embedded的移植与应用
  针对Qt/Embedded的实现特点,移植该嵌入式GUI系统一般分为以下几个步骤:
  ①设计硬件开发平台,并移植Linux操作系统;
  ②采用静态链接进Linux内核的方式,根据该平台显示设备的显示能力,开发framebuffer驱动程序;
  ③开发针对该平台的鼠标类设备驱动程序,一般为触摸屏或USB鼠标;
  ④开发针对该平台的键盘类设备驱动程序,一般为板载按钮或USB键盘(该部分可选);
  ⑤根据framebuffer驱动程序接口,选择并修改Qt/Embedded中的QlinuxFbScreen和QgfxRaster类;
  ⑥根据鼠标类设备驱动程序,实现该类设备在Qt/Embedded中的操作接口;
  ⑦根据键盘类设备驱动程序,实现该类设备在Qt/Embedded中的操作接口(该部分可选);
  ⑧根据需要选择Qt/Embedded的配置选项,交叉编译Qt/Embedded的动态库;
  ⑨交叉编译Qt/Embedded中的Example测试程序,在目标平台上运行测试。
  Framebuffer 设备驱动程序提供出的接口是标准的,除了注意endian问题外,配置Qt/Embedded时选择相应的色彩深度支持即可,因此该部分的移植难点就在于 framebuffer驱动程序的实现。Qt/Embedded部分的QWSServer打开/dev/中的framebuffer设备后读出相应的显示能力(屏幕尺寸、显示色彩深度),模板QgfxRaster将根据色彩深度在用户空间设备创建出与显示缓存同样大小的缓冲作为双缓冲,并采用正确方式进行显示。
返回列表