分享
 
 
 

输入抽象层及NativeEngine的实现二

王朝other·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

3 Native 图形引擎的实现

Native 图形引擎的图形驱动程序已经提供了基于Linux内核提供FrameBuffer之上的驱动,目前包括对线性 2 bpp、4bpp、8bpp和 16bpp 显示模式的支持。前面已经看到,GAL提供的接口函数大多数与图形相关,它们主要就是通过调用图形驱动程序来完成任务的。图形驱动程序屏蔽了底层驱动的细节,完成底层驱动相关的功能,而不是那么硬件相关的一些功能,如一些画圆,画线的GDI 函数。

下面基于已经实现的基于FrameBuffer 的驱动程序,讲一些实现上的细节。首先列出的核心数据结构 SCREENDEVICE。这里主要是为了讲解方便,所以删除了一些次要的变量或者函数。

清单 5

Native 图形引擎的核心数据结构

typedef struct _screendevice {

int xres;

/* X screen res (real) */

int yres;

/* Y screen res (real) */

int planes;

/* # planes*/

int bpp;

/* # bits per pixel*/

int linelen;

/* line length in bytes for bpp 1,2,4,8, line length in pixels for bpp 16, 24, 32*/

int size;

/* size of memory allocated*/

gfx_pixel gr_foreground;

/* current foreground color */

gfx_pixel gr_background;

/* current background color */

int

gr_mode;

int flags;

/* device flags*/

void *

addr;

/* address of memory allocated (memdc or fb)*/

PSD (*Open)(PSD psd);

void

(*Close)(PSD psd);

void

(*SetPalette)(PSD psd,int first,int count,gfx_color *cmap);

void

(*GetPalette)(PSD psd,int first,int count,gfx_color *cmap);

PSD (*AllocateMemGC)(PSD psd);

BOOL

(*MapMemGC)(PSD mempsd,int w,int h,int planes,int bpp, int linelen,int size,void *addr);

void

(*FreeMemGC)(PSD mempsd);

void

(*FillRect)(PSD psd,int x,int y,int w,int h,gfx_pixel c);

void

(*DrawPixel)(PSD psd, int x, int y, gfx_pixel c);

gfx_pixel (*ReadPixel)(PSD psd, int x, int y);

void

(*DrawHLine)(PSD psd, int x, int y, int w, gfx_pixel c);

void

(*PutHLine) (GAL gal, int x, int y, int w, void* buf);

void

(*GetHLine) (GAL gal, int x, int y, int w, void* buf);

void

(*DrawVLine)(PSD psd, int x, int y, int w, gfx_pixel c);

void

(*PutVLine) (GAL gal, int x, int y, int w, void* buf);

void

(*GetVLine) (GAL gal, int x, int y, int w, void* buf);

void (*Blit)(PSD dstpsd, int dstx, int dsty, int w, int h, PSD srcpsd, int srcx, int srcy);

void

(*PutBox)( GAL gal, int x, int y, int w, int h, void* buf );

void

(*GetBox)( GAL gal, int x, int y, int w, int h, void* buf );

void

(*PutBoxMask)( GAL gal, int x, int y, int w, int h, void *buf);

void

(*CopyBox)(PSD psd,int x1, int y1, int w, int h, int x2, int y2);

} SCREENDEVICE;

上面PSD 是 SCREENDEVICE 的指针,GAL 是GAL 接口的数据结构。

我们知道,图形显示有个显示模式的概念,一个像素可以用一位比特表示,也可以用2,4,8,15,16,24,32个比特表示,另外,VGA16标准模式使用平面图形模式,而VESA2.0使用的是线性图形模式。所以即使是同样基于Framebuffer 的驱动,不同的模式也要使用不同的驱动函数:画一个1比特的单色点和画一个24位的真彩点显然是不一样的。

所以图形驱动程序使用了子驱动程序的概念来支持各种不同的显示模式,事实上,它们才是最终的功能函数。为了保持数据结构在层次上不至于很复杂,我们通过图形驱动程序的初始函数Open直接将子驱动程序的各功能函数赋到图形驱动程序的接口函数指针,从而初始化结束就使用一个简单的图形驱动接口。下面是子图形驱动程序接口(清单 6)。

清单 6

Native 图形引擎的子驱动程序接口

typedef struct {

int

(*Init)(PSD psd);

void

(*DrawPixel)(PSD psd, int x, int y, gfx_pixel c);

gfx_pixel (*ReadPixel)(PSD psd, int x, int y);

void

(*DrawHLine)(PSD psd, int x, int y, int w, gfx_pixel c);

void

(*PutHLine) (GAL gal, int x, int y, int w, void* buf);

void

(*GetHLine) (GAL gal, int x, int y, int w, void* buf);

void

(*DrawVLine)(PSD psd, int x, int y, int w, gfx_pixel c);

void

(*PutVLine) (GAL gal, int x, int y, int w, void* buf);

void

(*GetVLine) (GAL gal, int x, int y, int w, void* buf);

void (*Blit)(PSD dstpsd, int dstx, int dsty, int w, int h, PSD srcpsd, int srcx, int srcy);

void

(*PutBox)( GAL gal, int x, int y, int w, int h, void* buf );

void

(*GetBox)( GAL gal, int x, int y, int w, int h, void* buf );

void

(*PutBoxMask)( GAL gal, int x, int y, int w, int h, void *buf);

void

(*CopyBox)(PSD psd,int x1, int y1, int w, int h, int x2, int y2);

} SUBDRIVER, *PSUBDRIVER;

可以看到,该接口中除了 Init 函数指针外,其他的函数指针都与图形驱动程序接口中的函数指针一样。这里的Init 函数主要用来完成图形驱动部分与显示模式相关的初始化任务。

下面介绍SCREENDEVICE数据结构,这样基本上就可以清楚图形引擎了。

一个SCREENDEVICE代表一个屏幕设备,它即可以对应物理屏幕设备,也可以对应一个内存屏幕设备,内存屏幕设备的存在主要是为了提高GDI 质量,比如我们先在内存生成一幅位图,再画到屏幕上,这样给用户的视觉效果就比较好。

首先介绍几个变量。

xres 表示屏幕的宽 (以像素为单位);

yres 表示屏幕的高 (以像素为单位);

planes :当处于平面显示模式时,planes 用于记录所使用的平面数,如平面模式相对的时线性模式,此时该变量没有意义。通常将其置为0。

bpp :表示每个像素所使用的比特数,可以为1,2,4,8,15,16,24,32。

linelen :对与1,2,4,8比特每像素模式,它表示一行像素使用的字节数,对于大于8比特每像素模式,它表示一行的像素总数。

size :表示该显示模式下该设备使用的内存数。linelen 和 size 的存在主要是为了方便为内存屏幕设备分配内存。

gr_foreground 和 gr_background :表示该内存屏幕的前景颜色和背景颜色,主要被一些GDI 函数使用。

gr_mode :说明如何将像素画到屏幕上,可选值为:MODE_SET MODE_XOR MODE_OR MODE_AND MODE_MAX,比较常用的是MODE_SET和MODE_XOR

flags :该屏幕设备的一些选项,比较重要的是 PSF_MEMORY 标志,表示该屏幕设备代表物理屏幕设备还是一个内存屏幕设备。

addr :每个屏幕设备都有一块内存空间用来作为存储像素。addr 变量记录了这个空间的起始地址。

下面介绍各接口函数:

Open,Close

基本的初始化和终结函数。前面已经提到,在 Open 函数里要选择子图形驱动程序,将其实现的函数赋给本 PSD 结构的函数指针。这里我讲讲基于Frambebuffer 的图形引擎的初始化。

fb_open 首先打开Framebuffer的设备文件 /dev/fb0,然后利用 ioctl 读出当前Framebuffer的各种信息。填充到PSD 结构中。并且根据这些信息选出子驱动程序。程序当前支持fbvga16,fblin16,fblin8,即VGA16 标准模式,VESA线性16位模式,VESA线性8位模式。然后将当前终端模式置于图形模式。并保存当前的一些系统信息如调色板信息。最后,系统利用mmap 将 /dev/fb0 映射到内存地址。以后程序访问 /dev/fb0 就像访问一个数组一样简单。当然,这是对线性模式而言的,如果是平面模式,问题要复杂的多。光从代码来看,平面模式的代码是线性模式的实现的将近一倍。后面的难点分析里将讲解这个问题。

SetPalette,GetPalette

当使用8位或以下的图形模式时,要使用系统调色板。这里是调色板处理函数,它们和Windows API 中的概念类似,linux 系统利用 ioctl 提供了处理调色板的接口。

AllocateMemGC,MapMemGC,FreeMemGC

前面屡次提到内存屏幕的概念,内存屏幕是一个伪屏幕,在对屏幕图形操作过程中,比如移动窗口,我们先生成一个内存屏幕,将物理屏幕的一个区域拷贝到内存屏幕,再拷贝到物理屏幕的新位置,这样就减少了屏幕直接拷贝的延时。AllocateMemGC 用于给内存屏幕分配空间,MapMemGC 做一些初始化工作,而FreeMemGC 则释放内存屏幕。

DrawPixel,ReadPixel,DrawHLine,DrawVLine,FillRect

这些是底层图形函数。分别是画点,读点,画水平线,画竖直线,画一个实心矩形。之所以在底层实现这么多函数,是为了提高效率。图形函数支持多种画图模式,常用的有直接设置,亦或,Alpha混合模式,从而可以支持各种图形效果。

PutHLine,GetHLine,PutVLine,GetVLine,PutBox,GetBox

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有