X Window研究笔记(5)
转载时请注明出处和作者联系方式
作者联系方式:李先静 <xianjimli at hotmail dot com>
5.显示设备(TinyX)
显示设备曾一度是性能的瓶颈,尽管有些显示标准存在,但各厂家为了提高市场竞争力,增强显示设备的性能,加入了各种加速功能和其它一些专有特性,各OS提供的接口也各不相同,X Window为了保持可移植性,又要充分发挥硬件特性,所以显示设备驱动接口看起来有点复杂。幸运的是,对TinyX来说,这块相对比较简单。
显示设备初始化过程。
- X Server在初始化时会调用InitOutput函数初始化显示设备。
- InitOutput调用KdInitOutput完成TinyX显示设备的初始化。
- 在KdInitOutput中:首先调用InitCard把所有Card放到一个链表中,对于fbdev来说,就是调用KdCardInfoAdd把fbdevFuncs注册到kdCardInfo里。再为最后一个Card增加一个KdScreenInfo,并初始化它(实际上TinyX假设的是单Card和单Screen)。
- 在KdInitOutput中:接下来调用card->cfuncs->cardinit初始化链表中的Card,调用KdInitScreen初始化Card中的KdScreenInfo。
- 最后通过KdInitScreen,再经过AddScreen把所有Card中的所有Screen加入到screenInfo.screens的全局的数组中,完成显示设备的初始化。
KdScreenInit是真正初始化Screen(不是前面的ScreenInfo)的函数,初始化完成之后DIX看到的是ScreenPtr这样的抽象对象。
KdCardFuncs的结构描述
typedef struct _KdCardFuncs {
Bool (*cardinit) (KdCardInfo *); /* detect and map device */
Bool (*scrinit) (KdScreenInfo *);/* initialize screen information */
Bool (*initScreen) (ScreenPtr); /* initialize ScreenRec */
void (*preserve) (KdCardInfo *); /* save graphics card state */
Bool (*enable) (ScreenPtr); /* set up for rendering */
Bool (*dpms) (ScreenPtr, int); /* set DPMS screen saver */
void (*disable) (ScreenPtr); /* turn off rendering */
void (*restore) (KdCardInfo *); /* restore graphics card state */
void (*scrfini) (KdScreenInfo *);/* close down screen */
void (*cardfini) (KdCardInfo *); /* close down */
Bool (*initCursor) (ScreenPtr); /* detect and map cursor */
void (*enableCursor) (ScreenPtr); /* enable cursor */
void (*disableCursor) (ScreenPtr); /* disable cursor */
void (*finiCursor) (ScreenPtr); /* close down */
void (*recolorCursor) (ScreenPtr, int, xColorItem *);
Bool (*initAccel) (ScreenPtr);
void (*enableAccel) (ScreenPtr);
void (*syncAccel) (ScreenPtr);
void (*disableAccel) (ScreenPtr);
void (*finiAccel) (ScreenPtr);
void (*getColors) (ScreenPtr, int, int, xColorItem *);
void (*putColors) (ScreenPtr, int, int, xColorItem *);
Bool (*finishInitScreen) (ScreenPtr pScreen);
} KdCardFuncs;
Bool (*cardinit) (KdCardInfo *); /* detect and map device */
Bool (*scrinit) (KdScreenInfo *);/* initialize screen information */
Bool (*initScreen) (ScreenPtr); /* initialize ScreenRec */
void (*preserve) (KdCardInfo *); /* save graphics card state */
Bool (*enable) (ScreenPtr); /* set up for rendering */
Bool (*dpms) (ScreenPtr, int); /* set DPMS screen saver */
void (*disable) (ScreenPtr); /* turn off rendering */
void (*restore) (KdCardInfo *); /* restore graphics card state */
void (*scrfini) (KdScreenInfo *);/* close down screen */
void (*cardfini) (KdCardInfo *); /* close down */
Bool (*initCursor) (ScreenPtr); /* detect and map cursor */
void (*enableCursor) (ScreenPtr); /* enable cursor */
void (*disableCursor) (ScreenPtr); /* disable cursor */
void (*finiCursor) (ScreenPtr); /* close down */
void (*recolorCursor) (ScreenPtr, int, xColorItem *);
Bool (*initAccel) (ScreenPtr);
void (*enableAccel) (ScreenPtr);
void (*syncAccel) (ScreenPtr);
void (*disableAccel) (ScreenPtr);
void (*finiAccel) (ScreenPtr);
void (*getColors) (ScreenPtr, int, int, xColorItem *);
void (*putColors) (ScreenPtr, int, int, xColorItem *);
Bool (*finishInitScreen) (ScreenPtr pScreen);
} KdCardFuncs;
Fbdev是基于FrameBuffer实现的显示设备驱动,前面的KdCardFuncs定义了很多接口函数,由下面的fbdev的初始化,我们可以看出,很多接口函数并不是必须的。
KdCardFuncs fbdevFuncs = {
fbdevCardInit, /* cardinit */
fbdevScreenInit, /* scrinit */
fbdevInitScreen, /* initScreen */
fbdevPreserve, /* preserve */
fbdevEnable, /* enable */
fbdevDPMS, /* dpms */
fbdevDisable, /* disable */
fbdevRestore, /* restore */
fbdevScreenFini, /* scrfini */
fbdevCardFini, /* cardfini */
0, /* initCursor */
0, /* enableCursor */
0, /* disableCursor */
0, /* finiCursor */
0, /* recolorCursor */
0, /* initAccel */
0, /* enableAccel */
0, /* syncAccel */
0, /* disableAccel */
0, /* finiAccel */
fbdevGetColors, /* getColors */
fbdevPutColors, /* putColors */
};
fbdevCardInit, /* cardinit */
fbdevScreenInit, /* scrinit */
fbdevInitScreen, /* initScreen */
fbdevPreserve, /* preserve */
fbdevEnable, /* enable */
fbdevDPMS, /* dpms */
fbdevDisable, /* disable */
fbdevRestore, /* restore */
fbdevScreenFini, /* scrfini */
fbdevCardFini, /* cardfini */
0, /* initCursor */
0, /* enableCursor */
0, /* disableCursor */
0, /* finiCursor */
0, /* recolorCursor */
0, /* initAccel */
0, /* enableAccel */
0, /* syncAccel */
0, /* disableAccel */
0, /* finiAccel */
fbdevGetColors, /* getColors */
fbdevPutColors, /* putColors */
};
- FbdevCardInit 创建FbdevPriv结构,打开/dev/fb0设备文件,获取framebuffer信息,并映射显存到用户空间。
- FbdevScreenInit 根据framebuffer的信息初始化ScreenInfo。
- FbdevInitScreen 初始化Screen的信息和虚函数表。
- FbdevPreserve 空函数。
- FbdevEnable 激活framebuffer并设置调色板。
- FbdevDPMS 显示器电源管理,通过ioctl控制framebuffer的电源模式。
- FbdevDisable 空函数。
- FbdevRestore 空函数。
- FbdevScreenFini 空函数。
- FbdevCardFini unmap显存,并关闭framebuffer设备文件。
- FbdevGetColors 得到调色板信息。
- FbdevPutColors 设置调色板信息。
Screen的初始化并不是在Tinyx/Fbdev中完成的,原因是framebuffer的操作是公共的,非Tinyx下也可以使用,所以这些函数的实现是放在Xserver/fb中,由fbSetupScreen来初始化的。
(待续)