您的位置:首页 > 编程语言

[转] Nano-X显示系统的代码分析

2011-03-08 19:29 295 查看
microwindows作为一个轻量级的图形引擎,目前在很多应用中仍在使用,包括各种机顶盒,嵌入式播放器等。

虽然其目前开发状况非常缓慢,但其代码作为一个很好的图形引擎的范例,我们可以花些时间来仔细研究一下。

后续,本人会列出一系列的技术点,一一介绍microwindows。

先用实例说一下,使用到microwindows的应用环境:

带UI输出的嵌入式网络产品,可设置各种参数。主要使用microwindows的画图功能,鼠标和键盘未使用,键盘在上层应用来单独处理,相应按键后,将需要画的内容通过microwindows来输出。在两个平台中使用到了microwindows,一个是开发调试时使用的X11环境,在此环境中来验证程序的正确性,另一个是实际运行的嵌入式平台,使用framebuffer作为输出。

1、uclinux 2.4.22, arm no-mmu

2、framebuffer作为显示输出,32位带alpha blending效果

3、红外遥控、或键盘作为输入,此由上层应用处理

4、freetype字体

5、nano-x方式

6、软件包为microwindows-0.90.tar.gz

microwindows资源

microwindows论坛(中文):

http://microwindows.5d6d.com/

官方网站:

http://www.microwindows.org/

microwindows简介:

http://www.microwindows.org/MicrowindowsPaper.html

http://www.linuxdevices.com/links/LK4761626139.html

ftp下载:

http://www.cnblogs.com/newsfh/admin/ftp://microwindows.censoft.com/pub/microwindows/

1. microwindows CVS

2. Nano-X CVS Instructions:

3. 1. Set your CVSROOT environment variable

4. export CVSROOT=:pserver:anoncvs@cvs.microwindows.org:/usr/cvs

5. 2. Run "cvs login" and use a password of "guest"

6. 3. Run "cvs co microwin"

7. 4. Watch the source tree spill onto your hard drive

microwindows CVS

Nano-X CVS Instructions:

1. Set your CVSROOT environment variable

export CVSROOT=:pserver:anoncvs@cvs.microwindows.org:/usr/cvs

2. Run "cvs login" and use a password of "guest"

3. Run "cvs co microwin"

4. Watch the source tree spill onto your hard drive

(一)c/s模型的简化

在microwin的运行模式中,nano-x通常的使用方式是c/s模型的,这是类似于x-windows的方式的,好处是某个client端的异常不会影响到server对其他client提供的服务。

但是在很多嵌入式系统中,通常都是在一个单一的环境中使用,单独的server服务进程就不是那么必要。

为了避免在后台启动一个nano-x的服务进程,可以修改microwin的src/config:

其中改为:

LINK_APP_INTO_SERVER = Y

我们来看看这个标记对代码的影响:

1. 1、nanox/Makefile

2. # Nano-X server files

3. NANOXFILES = srvmain.o srvfunc.o srvutil.o srvevent.o srvclip.o

4. # Nano-X client files

5. OBJS = nxdraw.o nxutil.o nxtransform.o

6. ifeq ($(LINK_APP_INTO_SERVER), Y)

7. OBJS += $(NANOXFILES)

8. else

9. # Nano-X server files (network only)

10. NANOXFILES += srvnet.o

11. # Nano-X client files (network only)

12. OBJS += client.o nxproto.o error.o

13. ifeq ($(FRAMEBUFFER), Y)

14. OBJS += clientfb.o

15. else

16. ifeq ($(X11), Y)

17. OBJS += clientfb.o

18. endif

19. endif

20. 这里说明,有了这个标记,那么就只会增加srv对应的代码,而client的代码被排除在外了。

21.

22. 2、Makefile.rules

23. ifeq ($(LINK_APP_INTO_SERVER), Y)

24. DEFINES += -DNONETWORK=1

25. endif

1、nanox/Makefile

# Nano-X server files

NANOXFILES = srvmain.o srvfunc.o srvutil.o srvevent.o srvclip.o

# Nano-X client files

OBJS = nxdraw.o nxutil.o nxtransform.o

ifeq ($(LINK_APP_INTO_SERVER), Y)

OBJS += $(NANOXFILES)

else

# Nano-X server files (network only)

NANOXFILES += srvnet.o

# Nano-X client files (network only)

OBJS += client.o nxproto.o error.o

ifeq ($(FRAMEBUFFER), Y)

OBJS += clientfb.o

else

ifeq ($(X11), Y)

OBJS += clientfb.o

endif

endif

这里说明,有了这个标记,那么就只会增加srv对应的代码,而client的代码被排除在外了。

2、Makefile.rules

ifeq ($(LINK_APP_INTO_SERVER), Y)

DEFINES += -DNONETWORK=1

endif

如果这个标记为N的话,那么当你的应用程序使用编译出来的nano-x库时,使用的将是microwindows-0.90/src/nanox/client.c的代码,即GrOpen是会尝试与srv建立连接:

ret = connect(nxSocket, (struct sockaddr *) &name, size);

并发送request给srv:

nxWriteSocket((char *)&req,sizeof(req));

而如果这个标记为Y的话,那么你的应用使用的代码GrOpen是nanox/srvmain.c中的,即直接运行srv的代码,其中就有初始化graphics的内容GsInitialize()。

这样就实现了对microwin的c/s模型的一个简化,这样更加适合于在嵌入系统中来使用和调试。

由于microwin在x11下,可以先对你的应用程序做好调试后,再转到嵌入系统中,所以我们可以先在x11下验证基本的代码功能,加快开发和调试的速度。

这里记录一下实验用的x11下的config中的一些标记:

1. ARCH = LINUX-NATIVE

2. MICROWIN = N

3. NANOX = Y

4. SHAREDLIBS = N

5. NANOWM = N

6. SCREEN_PIXTYPE = MWPF_TRUECOLOR8888

7. X11 = Y

8. NOMOUSE = Y

9. NOKBD = Y

10. HAVE_FREETYPE_SUPPORT=N

ARCH = LINUX-NATIVE

MICROWIN = N

NANOX = Y

SHAREDLIBS = N

NANOWM = N

SCREEN_PIXTYPE = MWPF_TRUECOLOR8888

X11 = Y

NOMOUSE = Y

NOKBD = Y

HAVE_FREETYPE_SUPPORT=N

(二)screen driver显示驱动的架构

在microwin的代码中,很重要的一个部分就是screen driver显示驱动的部分,它的功能就是负责屏幕输出。

此部分代码是在drivers目录下,并以scr_为开头,我们比较感兴趣的一般是scr_x11.c和scr_fb.c两个部分。

一个是用来在x86 pc上使用的,一个是可以在嵌入系统中使用的。

在microwin的显示驱动的drivers/Makefile中,会根据外部config的设置来只选择使用一个驱动,如X11=Y的话,那么就只会编译scr_x11.c。

在具体每个screen driver中都定义一个SCREENDEVICE scrdev,它也就是microwin要使用到的一个全局的screen driver。

这个结构里主要包括了具体的Open,Close,GetScreenInfo,SetPalette,DrawPixel,FillRect,Blit,StretchBlit等函数实体,如X11_open, X11_close,X11_getscreeninfo,X11_drawpixel等。

同理,对framebuffer,drivers/scr_fb.c,它有一些具体的实现,如fb_open, fb_close, gen_getscreeninfo等。

所以,你自己如果需要增加一个自己的显示驱动的话,就类似上面的内容,写出自己的具体实现函数,从而就能很容易地将microwin porting到你的hardware平台上。

结构上,使用上面的SCREENDEVICE scrdev全局变量的一个好处就是各个具体实现分离,在上层调用上来说只需要关心统一的 SCREENDEVICE 接口即可。

(三)screen driver显示驱动之X11

在microwindows的嵌入式开发中,为了简化调试和check memory leak,那么最好是先将应用程序在X11下做好验证,保证function已经完成并且不会出现内存泄露的问题。这样就会用到microwindows的X11 screen driver显示驱动,我们在这里详细分析一下。

在我们讨论的microwindows的应用中,目前只涉及到microwindows的screen driver,并不涉及到鼠标和键盘的driver。也就是说,使用的microwindows只用到它的画图功能。

在编译X11 screen driver方式的microwindows时,会进入到drivers/Makefile,其中X11为Y,那么就会编译到

1. OBJS += genmem.o fb.o scr_x11.o \

2. fblin1.o fblin2.o fblin4.o fblin8.o fblin16.o fblin24.o fblin32.o \

3. fblin32alpha.o mou_x11.o

OBJS += genmem.o fb.o scr_x11.o \

fblin1.o fblin2.o fblin4.o fblin8.o fblin16.o fblin24.o fblin32.o \

fblin32alpha.o mou_x11.o

其中scr_x11.o就是x11接口的screen driver的实现,它里面会调用到X11 lib的一系列函数,实现draw pixel。

另外,可以看到有一系列的fblinXXX开头的代码也被编译了进来,这个内容主要是对应不同的pixel type,来做一些pixel的叠加运算等。它是作为sub driver来被scr_x11所使用的,因为scr_x11中主要是将X11 lib做一个包装,从而将运算好了的pixel输出到X11 output,而fblinXXX是一个sub driver,来根据不同的pixel type处理需要输出的pixel,如alpha blending混合。 而且fblinXXX在其他screen driver的情况下也是一样公用的,如framebuffer,也即fblinXXX也会被指定为sub driver。所以看到X11方式的screen driver会用到fb开头的内容,也不用奇怪。

下面来看drivers/scr_x11.c的具体内容。

scr文件名前缀就是screen driver的含义。

在这个screen driver中,定义了一个x11方式的SCREENDEVICE scrdev,这个变量的名字,在各个screen driver的实现中都是同一个名字,只是一个编译只使用一个具体的scrdev,在我们这里,就是X11方式的scrdev。

这个scrdev定义了X11方式的各个函数,如X11_open,X11_drawpixel,X11_fillrect,X11_blit等。

一、变量

在代码中,定义一些全局的涉及到X11显示操作的变量,如:

1. /* called from keyboard/mouse/screen */

2. Display *x11_dpy;

3. int x11_scr;

4. Visual *x11_vis;

5. Colormap x11_colormap;

6. Window x11_win;

7. GC x11_gc;

8. unsigned int x11_event_mask;

9. static int x11_width, x11_height;

10. static int x11_depth; /* Screen depth in bpp */

/* called from keyboard/mouse/screen */

Display *x11_dpy;

int x11_scr;

Visual *x11_vis;

Colormap x11_colormap;

Window x11_win;

GC x11_gc;

unsigned int x11_event_mask;

static int x11_width, x11_height;

static int x11_depth; /* Screen depth in bpp */

在这里,x11_dpy是一个与x11 server所建立的connection;

x11_vis是记录视觉类型的变量;

x11_colormap是色彩映射;

在我们的应用中,如果是使用32位的无符号整数来表示颜色,也就是一般说的像素值,即pixel value,但这个像素值,在显示到输出时,会受到很多因素的影响,如

1、色彩深度

2、色彩映射,colormap,也就是含有R/G/B的强度值的表

3、视觉类型,visual type,指明表如何来表示颜色

视觉分类里有如下几种类型:

view plaincopy to clipboardprint?

1. char *classnm[] = { "StaticGray", "GrayScale", "StaticColor",

2. "PseudoColor", "TrueColor", "DirectColor"

3. };

char *classnm[] = { "StaticGray", "GrayScale", "StaticColor",

"PseudoColor", "TrueColor", "DirectColor"

};

其中X11 server支持的主要是true color和direct color。

true color是直接根据rgb值,来得到像素值,而direct color是将rgb拿来到表里做一个查询后再转到像素值的。

二、X11_open

下面来看一下screen driver的open实现:X11_open

在这个函数里,会先调用X11的初始化函数来建立与X11 server的连接,x11_setup_display: XOpenDisplay即根据display name与X11 server建立了一个connenction; 然后获得一个default screen; 再调用select_visual时,它会列出screen的不同depth的所对应的visual 类型。

1. XDefaultVisual:

2. Visual class: TrueColor (4)

3. id: 35

4. bits_per_rgb: 8

5. map_entries: 256

6. red_mask: 0x00ff0000

7. green_mask: 0x0000ff00

8. blue_mask: 0x000000ff

9. Screen RootDepth: 24

10. Screen RootVisual

11. Visual class: TrueColor (4)

12. id: 35

13. bits_per_rgb: 8

14. map_entries: 256

15. red_mask: 0x00ff0000

16. green_mask: 0x0000ff00

17. blue_mask: 0x000000ff

18. screen->ndepths: 7

19. Depth: 24

20. dp->nvisuals: 8

21. Visual: 0

22. Visual class: TrueColor (4)

23. id: 35

24. bits_per_rgb: 8

25. map_entries: 256

26. red_mask: 0x00ff0000

27. green_mask: 0x0000ff00

28. blue_mask: 0x000000ff

29. Visual: 1

30. Visual class: TrueColor (4)

31. id: 36

32. bits_per_rgb: 8

33. map_entries: 256

34. red_mask: 0x00ff0000

35. green_mask: 0x0000ff00

36. blue_mask: 0x000000ff

37. Visual: 2

38. Visual class: TrueColor (4)

39. id: 37

40. bits_per_rgb: 8

41. map_entries: 256

42. red_mask: 0x00ff0000

43. green_mask: 0x0000ff00

44. blue_mask: 0x000000ff

45. Visual: 3

46. Visual class: TrueColor (4)

47. id: 38

48. bits_per_rgb: 8

49. map_entries: 256

50. red_mask: 0x00ff0000

51. green_mask: 0x0000ff00

52. blue_mask: 0x000000ff

53. Visual: 4

54. Visual class: DirectColor (5)

55. id: 39

56. bits_per_rgb: 8

57. map_entries: 256

58. red_mask: 0x00ff0000

59. green_mask: 0x0000ff00

60. blue_mask: 0x000000ff

61. Visual: 5

62. Visual class: DirectColor (5)

63. id: 40

64. bits_per_rgb: 8

65. map_entries: 256

66. red_mask: 0x00ff0000

67. green_mask: 0x0000ff00

68. blue_mask: 0x000000ff

69. Visual: 6

70. Visual class: DirectColor (5)

71. id: 41

72. bits_per_rgb: 8

73. map_entries: 256

74. red_mask: 0x00ff0000

75. green_mask: 0x0000ff00

76. blue_mask: 0x000000ff

77. Visual: 7

78. Visual class: DirectColor (5)

79. id: 42

80. bits_per_rgb: 8

81. map_entries: 256

82. red_mask: 0x00ff0000

83. green_mask: 0x0000ff00

84. blue_mask: 0x000000ff

85. Depth: 1

86. dp->nvisuals: 0

87. Depth: 4

88. dp->nvisuals: 0

89. Depth: 8

90. dp->nvisuals: 0

91. Depth: 15

92. dp->nvisuals: 0

93. Depth: 16

94. dp->nvisuals: 0

95. Depth: 32

96. dp->nvisuals: 1

97. Visual: 0

98. Visual class: TrueColor (4)

99. id: 100

100. bits_per_rgb: 8

101. map_entries: 256

102. red_mask: 0x00ff0000

103. green_mask: 0x0000ff00

104. blue_mask: 0x000000ff

105. Selected Visual:

106. Visual class: TrueColor (4)

107. id: 35

108. bits_per_rgb: 8

109. map_entries: 256

110. red_mask: 0x00ff0000

111. green_mask: 0x0000ff00

112. blue_mask: 0x000000ff

XDefaultVisual:

Visual class: TrueColor (4)

id: 35

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Screen RootDepth: 24

Screen RootVisual

Visual class: TrueColor (4)

id: 35

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

screen->ndepths: 7

Depth: 24

dp->nvisuals: 8

Visual: 0

Visual class: TrueColor (4)

id: 35

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 1

Visual class: TrueColor (4)

id: 36

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 2

Visual class: TrueColor (4)

id: 37

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 3

Visual class: TrueColor (4)

id: 38

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 4

Visual class: DirectColor (5)

id: 39

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 5

Visual class: DirectColor (5)

id: 40

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 6

Visual class: DirectColor (5)

id: 41

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Visual: 7

Visual class: DirectColor (5)

id: 42

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Depth: 1

dp->nvisuals: 0

Depth: 4

dp->nvisuals: 0

Depth: 8

dp->nvisuals: 0

Depth: 15

dp->nvisuals: 0

Depth: 16

dp->nvisuals: 0

Depth: 32

dp->nvisuals: 1

Visual: 0

Visual class: TrueColor (4)

id: 100

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

Selected Visual:

Visual class: TrueColor (4)

id: 35

bits_per_rgb: 8

map_entries: 256

red_mask: 0x00ff0000

green_mask: 0x0000ff00

blue_mask: 0x000000ff

而我们的应用中,实际使用的visual也就是XDefaultVisual的值。即Visual class: TrueColor (4),id: 35,map_entries: 256。

在完成X11的display初始化后,会XCreateColormap,还有XCreateWindow建立窗口,长宽也即你指定的x11_width, x11_height,然后会再调用XDefaultDepth获得default的depth等,如下图: 在X11_open函数的后部,可以看到 savebits = *psd; 然后会调用到select_fb_subdriver(fb.c中),来根据planes和 bpp选择sub driver,如我们的应用中使用的是MWPF_TRUECOLOR8888,那么就会选用fblinear32alpha作为sub driver。然后会调用:

1. static SCREENDEVICE savebits; /* permanent offscreen drawing buffer */

2. set_subdriver(&savebits, subdriver, TRUE);

3. savebits.addr = malloc(size);

4. /* set X11 psd to savebits memaddr for screen->offscreen blits... */

5. psd->addr = savebits.addr;

static SCREENDEVICE savebits; /* permanent offscreen drawing buffer */

set_subdriver(&savebits, subdriver, TRUE);

savebits.addr = malloc(size);

/* set X11 psd to savebits memaddr for screen->offscreen blits... */

psd->addr = savebits.addr;

这个部分是一个很重要的内容。 它会将savebits的操作函数做一个更新,即设置到sub driver上,也即drivers/fblin32alpha.c中:

1. SUBDRIVER fblinear32alpha = {

2. linear32a_init,

3. linear32a_drawpixel,

4. linear32a_readpixel,

5. linear32a_drawhorzline,

6. linear32a_drawvertline,

7. gen_fillrect,

8. linear32a_blit,

9. linear32a_drawarea,

10. linear32a_stretchblit,

11. linear32a_stretchblitex,

12. };

SUBDRIVER fblinear32alpha = {

linear32a_init,

linear32a_drawpixel,

linear32a_readpixel,

linear32a_drawhorzline,

linear32a_drawvertline,

gen_fillrect,

linear32a_blit,

linear32a_drawarea,

linear32a_stretchblit,

linear32a_stretchblitex,

};

这个savebits是保存的off sreen的buffer,以及最后的输出,都是从这个savebits中来得到的。

savebits.addr即malloc出来的一个显示buffer缓冲,是最后送到X11输出前保存各个pixel的地方。

psd->addr也则是对应的这个地址,但它是给上层的microwindows所使用的一个地址。各个不同的screen driver也都需要定义这个psd->addr。

三、draw pixel

我们再来看X11_drawpixel:

1. static void

2. X11_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c)

3. {

4. /* draw savebits for readpixel or blit */

5. savebits.DrawPixel(&savebits, x, y, c);

6. if (gr_mode == MWMODE_COPY) {

7. set_color(c);

8. set_mode(gr_mode);

9. XDrawPoint(x11_dpy, x11_win, x11_gc, x, y);

10. } else {

11. update_from_savebits(x, y, 1, 1);

12. }

13. }

static void

X11_drawpixel(PSD psd, MWCOORD x, MWCOORD y, MWPIXELVAL c)

{

/* draw savebits for readpixel or blit */

savebits.DrawPixel(&savebits, x, y, c);

if (gr_mode == MWMODE_COPY) {

set_color(c);

set_mode(gr_mode);

XDrawPoint(x11_dpy, x11_win, x11_gc, x, y);

} else {

update_from_savebits(x, y, 1, 1);

}

}

在其中,即会先调用sub drvier的DrawPixel函数,用pixel value值c来更新savebits里的addr的数据,然后调用update_from_savebits将savebits.addr的像素内容输出到X11上。

其他的X11_xxx也都是类似如此的像素操作,即都是先调用sub driver的操作函数,然后X11的接口负责输出到X11 display上。

四、总结

总体来说,scr_x11是负责像素pixel在X11上输出的,在它里面是不涉及到图像的叠加等操作的。它所操作的内容主要是将运算过的像素pixel输出到X11上,从而实现了microwindows在X11上的运行。

(四)screen driver显示驱动之framebuffer
关键字:microwindows, microwin, 代码, 分析, framebuffer
在microwindows的显示驱动中,一个很重要的部分就是framebuffer的驱动,framebuffer已经在大量的嵌入式设备中都被支持,所以有了framebuffer,microwindows就可被移植到很多的嵌入式设备中了。
framebuffer的驱动代码是放在了drivers/scr_fb.c里。在drivers/Makefile中,如果FRAMEBUFFER=Y,那么scr_fb.o会被编译到microwindows的driver代码中。

和X11方式的类似,scr_fb.c也定义了一个全局变量:

1. SCREENDEVICE scrdev;

SCREENDEVICE scrdev;

其中就包含了需要为framebuffer而实现的接口函数,如fb_open,fb_close,gen_getscreeninfo,fb_mapmemgc等。这些都是SCREENDEVICE结构中各个函数的具体实现,从而给上层的microwindows画图函数提供了统一的函数接口。

现在我们来看一下fb有关的函数。
在fb_open中,会现从环境变量中读取FRAMEBUFFER的内容,看是否外部已经有所指定:

1. if(!(env = getenv("FRAMEBUFFER")))

2. env = "/dev/fb0";

3. fb = open(env, O_RDWR);

if(!(env = getenv("FRAMEBUFFER")))

env = "/dev/fb0";

fb = open(env, O_RDWR);

然后会用open打开这个fd。
然后会使用ioctl来和kernel的framebuffer交互,得到FBIOGET_FSCREENINFO(fixed),FBIOGET_VSCREENINFO (variable)设备信息,即固定的屏幕信息,还有可变的屏幕信息。
第一个固定的屏幕信息,它由硬件和驱动的能力决定。
第二个是可变的屏幕信息,它由硬件的当前状态决定,它是可以让用户空间的程序调用ioctl来改变的。

1. struct fb_fix_screeninfo fb_fix;

2. struct fb_var_screeninfo fb_var;

struct fb_fix_screeninfo fb_fix;

struct fb_var_screeninfo fb_var;

大家可以查看上面的两个结构,来获得其中的详细定义。

它里面比较有用的信息,就是

1. fb_fix.type; --- 表示planes类型,如0为象素

2. fb_fix.visual; --- 表示视觉类型,如真彩2,伪彩3

3. fb_var.bits_per_pixel; --- 表示bpp

4. fb_fix.line_length; --- 表示每行长度

fb_fix.type; --- 表示planes类型,如0为象素

fb_fix.visual; --- 表示视觉类型,如真彩2,伪彩3

fb_var.bits_per_pixel; --- 表示bpp

fb_fix.line_length; --- 表示每行长度

然后在后面的代码,也会出新要设置 sub driver的内容:

1. subdriver = select_fb_subdriver(psd);

2. set_subdriver(psd, subdriver, TRUE)

subdriver = select_fb_subdriver(psd);

set_subdriver(psd, subdriver, TRUE)

这里是对psd来设置sub driver的,所以在sub driver中的各种draw pixel就会将之前的函数所覆盖。也即scr_fb的很多pixel相关函数,会转到sub driver中。

下面的部分就是要做一个framebuffer到内存地址的映射,即mmap:

1. /* mmap framebuffer into this address space*/

2. psd->size = (psd->size + getpagesize () - 1)

3. / getpagesize () * getpagesize ();

4. psd->addr = mmap(NULL, psd->size, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);

/* mmap framebuffer into this address space*/

psd->size = (psd->size + getpagesize () - 1)

/ getpagesize () * getpagesize ();

psd->addr = mmap(NULL, psd->size, PROT_READ|PROT_WRITE,MAP_SHARED,fb,0);

在这里,psd->size做了一个按page对齐的转换。
mmap的作用是映射后,就不需要再去read,write文件,这样就避免大量的寻址的开销,所以将framebuffer映射到一个内存上,这样应用直接访问内存效率会高很多。
mmap并不分配空间,只是将文件映射到调用进程的地址空间里。

1. void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

mmap的第四个变量表示这个内存和其他进程的共享情况
需要特别指出的是,在uclinux系统中,这里不能使用MAP_SHARED,而只能使用

1. #define MAP_FIXED 0x10 /* Interpret addr exactly. */

#define MAP_FIXED 0x10 /* Interpret addr exactly. */

即如果参数start所指的地址无法成功建立映射时,则放弃映射,不对地址做修正。
因为uclinux是无MMU管理的,内存的访问是直接访问物理地址的,所以它是不能与其他进程共享一个内存的。

fb_open即完成了主要的工作,其他部分的内容,主要是处理一些特殊情况的framebuffer的操作。

(五)font字体之builtin字体
在microwindows中,可以使用各种字体,包括点阵字体,和truetype字体等。在drivers/scr_x11.c中有定义SCREENDEVICE scrdev,其中一个参数就是
PMWCOREFONT builtin_fonts;
这个参数,就是用来保存font字体的一个结构,实体例子为:drivers/genfont.c中的gen_fonts,它是一个字体结构数组,用户可以对这个内容进行修改,加入自己需要的字体。

1. /* first font is default font*/

2. MWCOREFONT gen_fonts[NUMBER_FONTS] = {

3. {&fontprocs, 0, 0, 0, MWFONT_SYSTEM_VAR, &font_winFreeSansSerif11x13},

4. {&fontprocs, 0, 0, 0, MWFONT_SYSTEM_FIXED, &font_X6x13},

5. /* deprecated redirections for the time being*/

6. {&fontprocs, 0, 0, 0, "Helvetica", &font_winFreeSansSerif11x13}, /* redirect*/

7. {&fontprocs, 0, 0, 0, "Terminal", &font_X6x13} /* redirect*/

8. };

/* first font is default font*/

MWCOREFONT gen_fonts[NUMBER_FONTS] = {

{&fontprocs, 0, 0, 0, MWFONT_SYSTEM_VAR, &font_winFreeSansSerif11x13},

{&fontprocs, 0, 0, 0, MWFONT_SYSTEM_FIXED, &font_X6x13},

/* deprecated redirections for the time being*/

{&fontprocs, 0, 0, 0, "Helvetica", &font_winFreeSansSerif11x13}, /* redirect*/

{&fontprocs, 0, 0, 0, "Terminal", &font_X6x13} /* redirect*/

};

这个数组中,第一个实例会作为缺省的字体。

一、screen driver中的字体
下面来看一下启动过程中字体是如何设置的。
在GrOpen->GsInitialize->GdOpenScreen,即在open screen driver时,会调用

1. GdSetFont(GdCreateFont(psd, NULL, 0, NULL));

GdSetFont(GdCreateFont(psd, NULL, 0, NULL));

其中,GdCreateFont的第二个参数为NULL,那么在engine/devfont.c的GdCreateFont代码中,会将psd->builtin_fonts的第一个实体参数传给fontname,在后面的循环查找中for(i = 0; i < scrinfo.fonts; ++i),当一个个查询到name相同时,就会立即返回所找到的字体结构,这里即第一个实体的内容了。
GdSetFont则会将这个字体赋值给全局的gr_pfont:

1. /*** The current font.*/

2. static PMWFONT gr_pfont;

/*** The current font.*/

static PMWFONT gr_pfont;

二、 设置stdfont字体
在GsInitialize中,GdOpenScreen结束后,会再去设置全局变量stdfont

1. stdfont = GdCreateFont(psd, MWFONT_SYSTEM_VAR, 0, NULL);

2. #define MWFONT_SYSTEM_VAR "System" /* winFreeSansSerif 11x13 (ansi)*/

stdfont = GdCreateFont(psd, MWFONT_SYSTEM_VAR, 0, NULL);

#define MWFONT_SYSTEM_VAR "System" /* winFreeSansSerif 11x13 (ansi)*/

这里的第二个参数是使用name: MWFONT_SYSTEM_VAR,即为"System"。

这个stdfont主要是在GsPrepareDrawing准备时使用到:

1. fontp = GsFindFont(gcp->fontid);

2. pf = fontp? fontp->pfont: stdfont;

fontp = GsFindFont(gcp->fontid);

pf = fontp? fontp->pfont: stdfont;

在可能未设置gc font的时候,就使用stdfont。

三、设置其他字体
在应用中,可以使用GrCreateFont来设置具体的字体,如arial等。
GrCreateFont会调用GdCreateFont去scrdev中查找匹配的字体,并将字体保留在链表listfontp中。

四、builtin 字体
缺省的builtin字体为

1. {&fontprocs, 0, 0, 0, MWFONT_SYSTEM_VAR, &font_winFreeSansSerif11x13},

{&fontprocs, 0, 0, 0, MWFONT_SYSTEM_VAR, &font_winFreeSansSerif11x13},

它是使用的fonts/winFreeSansSerif11x13.c文件。
在文件的头部有写明:

1. /* Generated by convfnt.exe, modified removed offset array*/

2. #include "device.h"

3.

4. /* Windows FreeSansSerif 11x13 Font */

5.

6. /*

7. * #FONTRES 100,96,96:Free Sans Serif 8

8. * Distributed under the MPL (c) 1999 darran@rimron.co.uk v0.3

9. * Free Sans Serif

10. */

/* Generated by convfnt.exe, modified removed offset array*/

#include "device.h"

/* Windows FreeSansSerif 11x13 Font */

/*

* #FONTRES 100,96,96:Free Sans Serif 8

* Distributed under the MPL (c) 1999 darran@rimron.co.uk v0.3

* Free Sans Serif

*/

表示是用工具生成的。

这个builtin就是指的在外部用工具将字体文件转换成.c文件后,直接在microwindows代码中,使用转换在.c中的变量即可。

1. /* Exported structure definition. */

2. MWCFONT font_winFreeSansSerif11x13 = {

3. "winFreeSansSerif11x13",

4. 11,

5. 13,

6. 11,

7. 32,

8. 224,

9. winFreeSansSerif11x13_bits,

10. 0 /*winFreeSansSerif11x13_offset*/,

11. winFreeSansSerif11x13_width,

12. };

/* Exported structure definition. */

MWCFONT font_winFreeSansSerif11x13 = {

"winFreeSansSerif11x13",

11,

13,

11,

32,

224,

winFreeSansSerif11x13_bits,

0 /*winFreeSansSerif11x13_offset*/,

winFreeSansSerif11x13_width,

};

这个builtin字体,开发人员还可以自己来增加,如各种点阵字体bdf文件,使用convbdf.c即可转换为.c文件,来添加到builtin字体中。[备注:BDF: Bitmap Distribution Format位图分布格式的字体文件]

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/bisword/archive/2008/07/31/2746750.aspx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: