WINCE6.0显示驱动模型介绍
********************************LoongEmbedded*****************
作者:LoongEmbedded(kandi)
时间:2011.06.4
类别:WINCE驱动开发
********************************LoongEmbedded*****************
关键字
DDGPE的DD是指DirectDraw,Graphics Primitive Engine (GPE)
GDI:Graphics Device Interface
DDI:Display Device Interface
在WinCE6.0中,Display驱动由GWES模块来管理(GWES.dll)。WinCE提供了两种架构的Display驱动模型,可以满足不同的硬件需求。一种是基于WinCE DDI的Display驱动模型,另一种是基于DirectDraw的Display驱动模型。
1. WINCE6.0显示驱动模型
图1
1.1 DDI显示驱动模型
图2
本文是基于DDI的模型来学习的,但此6410D的BSP是基于基类DDGPE来实现对目标硬件的控制的。
1.2 DDRAW显示驱动模型
图3
DirectDraw提供了独立于硬件的直接访问显示设备的能力。它可以通过直接访问硬件抽象层(HAL)中的一些函数来达到直接操作显示设备的目的,在这个过程中,不再需要图形设备接口(GDI)的转换。这种直接的方法可以使图像更加连贯,也提高了显示的性能。为了实现这样的功能,需要在显示驱动上扩展能够直接访问相关硬件的函数。这些函数会被DirectDraw模块调用,并形成DirectDraw的硬件抽象层(DDHAL)。
DirectDraw的真正实现代码都驻在gwes.dll模块中,应用程序只是连接了一个小的客户端,被称为DDRAW.dll代理,该代理主要负责用户进程与系统之间的远程DirectDraw COM接口连接。这样,用户请求会被传送到内核的GWES模块中。针对DirectDraw,WinCE提供了一个名为DirectDraw的GPE库(DDGPE),它是从GPE类上面继承而来的。实际上,DirectDraw显示驱动是由DDGPE和DDHAL组成,而DDGPE中已经包含了DDHAL的功能。用户需要从DDGPE类继承并实现相关函数即可。GWES.dll模块中包含GDI和DDRAW两个组件,这两个组件会调用驱动中的DDGPE的相关接口完成对硬件的操作。
在上述两种架构中,用户可以根据自己的硬件情况选择相应的架构。第一种架构是基于GPE类继承来实现的,第二种架构是基于DDGPE类继承来实现的,而第二种架构的DDGPE类又是从第一种架构的GPE类继承而来。关于两种类的具体定义,可参见” /WINCE600/PUBLIC/COMMON/OAK/INC”路径下的gpe.h和ddgpe.h文件。
2. 显示驱动的文件结构
图4
我们先来看看DISPLAY_DRV目录下的sources文件的下面部分:
图5
从图3可知s3c6410_disp.dll要调用这两个dll提供的函数接口来实现自己的功能。接下来看看VIDEO_DRV目录下的sources文件的下面部分:
图6
从图3可知s3c6410_Video.dll要调用这些lib提供的函数接口来实现自己的功能。为了搞清楚s3c6410_disp.dll和s3c6410_Video.dll之间的关系,我们看DISPLAY_DRV目录下的display_main.cpp(也就是s3c6410_disp.cpp)下的函数调用:S3C6410Disp::S3C6410Disp()->S3C6410Disp::AllocResource(),就来看此函数的相关部分:
图7
从图5可以知道s3c6410_Video.dll还是为s3c6410_disp.dll提供服务的。总结这些dll和lib之间的关系如下面的逻辑框图所示:
图8
3. 显示驱动的具体实现
3.1显示驱动的加载
在GWES.dl被加载后,在加载驱动的过程中,GWES将根据注册表键HKEY_LOCAL_MACHINE/System/GDI/DisplayCandidates下面的项来找显示驱动,如果找到,则正常加载显示驱动,见platform.reg中相关部分:
图9
根据图9的注册表信息,GWES找到s3c6410_disp.dll并且加载,并且把s3c6410_disp.dll作为一项写到HKEY_LOCAL_MACHINE/System/GDI/Drivers键下面:
“MainDisplay”=“s3c6410_disp.dl”
3.2 s3c6410_disp.dll的导出函数
WINCE系统的设备驱动程序要实现自身的功能,不外乎导出函数和启动IST这两种办法来实现,而显示设备指示向显示屏输出显示的数据,不处理异步的输入数据,所以显示驱动不需要启动IST线程来实现,那么显示驱动就只能是以导出函数的方式来实现了,其导出文件的内容如下:
LIBRARY DDI
EXPORTS
DrvEnableDriver
HALInit
3.2.1 DrvEnableDriver函数
DrvEnableDriver函数向GWES.dll返回DDI函数指针并且借用GWES.dll的GDI的一些回调函数来简化自己的实现。见图3可知GDI是GWES的组成部分,它主要负责画简单的直线、矩形、圆等几何图像及实现矩形块传输和画线的硬件加速。DrvEnableDriver函数导出是DDI函数指针在/PUBLIC/COMMON/OAK/INC/Winddi.h中定义,如下所示:
图10
那么DDI上面的函数指针是如何彻底给GDI呢?GWES加载显示驱动的时候,会调用DrvEnableDriver函数,下面来看其函数体:
图11
DrvEnableDriver函数只是直接将4个参数传递给GPEEnableDriver函数处理,下面来学习者几个参数:
engineVersion:输入参数,是DDI的版本号,GWES提供的参数值为DDI_DRIVER_VERSION =0x00040001。
Cj:输入参数,DRVENABLEDATA结构体的大小,以字节为单位,指示输出参数指针pded所指向存储区域的大小。
Pded:输出参数,指向包含着DDI函数指针的DRVENABLEDATA结构体的数据。
engineCallbacks:输入参数,GWES使用PENGCALLBACKS结构体类型指针数据向显示驱动传递可用的GDI回调函数以便于帮助用户实现DDI函数。
接着看GPEEnableDriver()的实现,在PUBLIC/COMMON/OAK/DRIVERS/DISPLAY/GPE/ddi_if.cpp下定义:
图12
DRVENABLEDATA 结构体在/PUBLIC/COMMON/OAK/INC/Winddi.h中定义:
图13
GWES.dll的GDI获取到DDI函数指针后,应用程序就可以通过GDI来调用DDI函数来对显示设备进行操作了。
3.2.2 HALInit函数
HAL单元的导出函数是HALInit函数,根据图1可知HAL单元及WINCE自带的以软件模拟的方式提供对DirectDraw功能支持的HEL单元为DirectDraw服务。GDI和DirectDraw都是WINCE的GWES.dll的组成部分,后者可以画复杂的二维图案和更高级的硬件加速。
该函数没有直接被显示驱动调用,而是在显示驱动初始化阶段和模式切换阶段被DirectDraw内部调用,该函数负责构造一个为DirectDraw提供功能支持信息的DDHALINFO结构体。
图14
因为显示驱动中使用DDGPE模型,所以HALInit函数就已经作为DDGPE的一部分被写入到DirectDraw,我们只需要在显示驱动中导出这个函数就可以了。
4.