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

microwindows代码分析 (序)

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下载:

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的服务进程,可以修改microwinsrc/config

其中改为:

LINK_APP_INTO_SERVER     = Y

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

1.         1nanox/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.      2Makefile.rules   

23.      ifeq ($(LINK_APP_INTO_SERVER), Y)   

24.      DEFINES += -DNONETWORK=1   

25.      endif  

1nanox/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的代码被排除在外了。

 

2Makefile.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);

并发送requestsrv

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

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

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

由于microwinx11下,可以先对你的应用程序做好调试后,再转到嵌入系统中,所以我们可以先在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.cscr_fb.c两个部分。

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

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

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

这个结构里主要包括了具体的OpenCloseGetScreenInfoSetPaletteDrawPixelFillRectBlitStretchBlit等函数实体,如X11_open X11_closeX11_getscreeninfoX11_drawpixel等。

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

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

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

(三)screen driver显示驱动之X11

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

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

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

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_openX11_drawpixelX11_fillrectX11_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 colordirect color

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

二、X11_open

下面来看一下screen driveropen实现:X11_open

在这个函数里,会先调用X11的初始化函数来建立与X11 server的连接,x11_setup_display XOpenDisplay即根据display nameX11 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: 35map_entries: 256

在完成X11display初始化后,会XCreateColormap,还有XCreateWindow建立窗口,长宽也即你指定的x11_width x11_height,然后会再调用XDefaultDepth获得defaultdepth等,如下图: X11_open函数的后部,可以看到 savebits = *psd; 然后会调用到select_fb_subdriverfb.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.                 linear 32a _init,   

3.                 linear 32a _drawpixel,   

4.                 linear 32a _readpixel,   

5.                 linear 32a _drawhorzline,   

6.                 linear 32a _drawvertline,   

7.                 gen_fillrect,   

8.                 linear 32a _blit,   

9.                 linear 32a _drawarea,   

10.              linear 32a _stretchblit,   

11.              linear 32a _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 sreenbuffer,以及最后的输出,都是从这个savebits中来得到的。

savebits.addrmalloc出来的一个显示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 drvierDrawPixel函数,用pixel valuec来更新savebits里的addr的数据,然后调用update_from_savebitssavebits.addr的像素内容输出到X11上。

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

四、总结

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

 

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

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

1.         SCREENDEVICE    scrdev;  

SCREENDEVICE    scrdev;

其中就包含了需要为framebuffer而实现的接口函数,如fb_openfb_closegen_getscreeninfofb_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来和kernelframebuffer交互,得到FBIOGET_FSCREENINFOfixed),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
的作用是映射后,就不需要再去readwrite文件,这样就避免大量的寻址的开销,所以将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.cGdCreateFont代码中,会将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
会调用GdCreateFontscrdev中查找匹配的字体,并将字体保留在链表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位图分布格式的字体文件]

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值