SMDK2410 BSP(CE5.0,6.0中是DEVICEEMULATOR)已经实现了一个显示驱动,对应的GPE继承类是S3C2410DISP.
首先简单介绍下WinCE的显示驱动架构,然和分析了需要用户开发的显示驱动部分GPE(或者DDGPE)继承类.以下内容参考了MS帮助和<Windows CE工程实践完全解析>一书.
1.Windows CE显示驱动架构
Windows CE的显示设备驱动接口(DDI)是Windows NT DDI的一个子集.
显示驱动由Gwes.exe调用和加载,图形初级引擎 (GPE)用来处理默认的绘图工作,在驱动模型中扮演上层的模型设备驱动(MDD).用户需要开发的就是下层的平台相关驱动(PDD)和硬件相关的代码.
调用的依次顺序是Application,Coredll.dll,Gwes.exe,Ddi.dll,Hardware.
其中Ddi.dll就是默认的显示驱动名称.和大部分dll一样,Ddi.dll会导出相应的函数供上层调用.Ddi.dll只导出DrvEnableDriver函数,这个函数返回一个指向含有27个函数指针结构(DRVENABLEDATA)的指针.当GWES调用显示驱动,它就会相应调用这27个函数.开发显示驱动就包括开发这27个函数.其中3个和打印驱动相关,其余24个和显示驱动相关.
GPE类可以作为开发新显示驱动的基类,GPE处理与DDI的通信和进行默认的绘图,使用GPE可以减少开发时间和调试工作量.
SMDK2410 BSP中就是实现了一个GPE的继承类S3C2410DISP.
Windows CE的驱动分层架构如下.
2.注册表设置
通过如下的设置:
IF BSP_NODISPLAY !
[HKEY_LOCAL_MACHINE/Drivers/Display/S3C2410/CONFIG]
"DisplayDll"="s3c2410x_lcd.dll"
"LCDVirtualFrameBase"=dword:ac100000
"LCDPhysicalFrameBase"=dword:30100000
[HKEY_LOCAL_MACHINE/System/GDI/Drivers]
"Display"="s3c2410x_lcd.dll"
; GWES will pass this value to the LCD driver; the driver will open the
; key to which it points to read its configuration.
[HKEY_LOCAL_MACHINE/System/GDI/DisplayCandidates]
"Candidate10"="Drivers//Display//S3C2410//CONFIG"
ENDIF BSP_NODISPLAY !
; @CESYSGEN ENDIF CE_MODULES_DISPLAY
GWES 首先检查HKEY_LOCAL_MACHINE/System/GDI/DisplayCandidates注册表项,来获取是否有驱动程序在本机上初始化,如果有GWES就会使用第一个找到的驱动实例,否则加载Ddi.dll,这也是默认的驱动名称.
还可以通过CreateDC创建第二显示驱动(如"MyDDI.dll")
3.s3c2410x_lcd.dll
我们SMDK2410 BSP中实现的设备显示驱动动态链接库就是s3c2410x_lcd.dll,关于其在GEC2410平台上的移植可以参考之前的文章:
http://blog.csdn.net/shevsten/archive/2009/12/29/5099110.aspx
s3c2410x_lcd.dll导出2个函数DrvEnableDriver和DisplayInit,见s3c2410x_lcd.def.
在s3c2410x_lcd.cpp里实现了这两个函数,
DisplayInit是LCD驱动第一个执行的函数,来从注册表获取LCD驱动实例信息,如果失败则返回false,GWES会停止LCD驱动的初始化.代码如下:
// GWES will invoke this routine once prior to making any other calls into the driver. // This routine needs to save its instance path information and return TRUE. If it // returns FALSE, GWES will abort the display initialization. BOOL APIENTRY DisplayInit(LPCTSTR pszInstance, DWORD dwNumMonitors) { DWORD dwStatus; HKEY hkDisplay; BOOL fOk = FALSE; RETAILMSG(0, (_T("SALCD2: display instance '%s', num monitors %d/r/n"), pszInstance != NULL ? pszInstance : _T("<NULL>"), dwNumMonitors)); if(pszInstance != NULL) { _tcsncpy(gszBaseInstance, pszInstance, dim(gszBaseInstance)); } // sanity check the path by making sure it exists dwStatus = RegOpenKeyEx(HKEY_LOCAL_MACHINE, gszBaseInstance, 0, 0, &hkDisplay); if(dwStatus == ERROR_SUCCESS) { RegCloseKey(hkDisplay); fOk = TRUE; } else { RETAILMSG(0, (_T("SALCD2: DisplayInit: can't open '%s'/r/n"), gszBaseInstance)); } return fOk; }
另一个就是DrvEnableDriver,上面已经介绍过,DrvEnableDriver向GWES子系统提供了27个DDI函数指针.DrvEnableDriver函数是任何必不可少的,负责向GDI提供DDI函数指针.GDI是GWES的组成部分,它主要负责画简单的直线,矩形,圆等几何图形及实现矩形块传输和画线操作的硬件加速.DrvEnableDriver导出函数是GDI和DDI函数之间的中介桥梁.只有DrvEnableDriver函数名是不可改变的,由它负责导出的各DDI函数都只需要一个函数地址,操作系统不限制用户如何给它们命名.
DrvEnableDriver函数原型:
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data,
PENGCALLBACKS engineCallbacks);
在SMDK2410的LCD驱动程序中,DrvEnableDriver没有做实际的工作,只是直接将全部4个参数传递给函数GPEEnableDriver,这是个微软提供的公共代码函数.
BOOL APIENTRY DrvEnableDriver(ULONG engineVersion, ULONG cj, DRVENABLEDATA *data, PENGCALLBACKS engineCallbacks) { BOOL fOk = FALSE; // make sure we know where our registry configuration is if(gszBaseInstance[0] != 0) { fOk = GPEEnableDriver(engineVersion, cj, data, engineCallbacks); } return fOk; }
GPEEnableDriver函数实现在/WINCE500/PUBLIC/COMMON/OAK/DRIVERS/DISPLAY/GPE/ddi_if.cpp.
GPEEnableDriver函数首先保存由engineCallbacks参数传递而来的GDI回调函数指针集合.第二项主要任务是通过pded指针参数输出DDI函数指针阵列.
memcpy(pded, &pDrvFn, cj);
pDrvFn就是DRVENABLEDATA结构包含了所有的DDI函数的函数指针.结构如下:
const DRVENABLEDATA pDrvFn = { { DrvEnablePDEV }, { DrvDisablePDEV }, { DrvEnableSurface }, { DrvDisableSurface }, { DrvCreateDeviceBitmap }, { DrvDeleteDeviceBitmap }, { DrvRealizeBrush }, { DrvStrokePath }, { DrvFillPath }, { DrvPaint }, { DrvBitBlt }, { DrvCopyBits }, { DrvAnyBlt }, { DrvTransparentBlt }, { DrvSetPalette }, { DrvSetPointerShape }, { DrvMovePointer }, { DrvGetModes }, { DrvRealizeColor }, { DrvGetMasks }, { DrvUnrealizeColor }, { DrvContrastControl }, { DrvPowerHandler }, { NULL /* DrvEndDoc */ }, { NULL /* DrvStartDoc */ }, { NULL /* DrvStartPage */ }, { DrvEscape } };
具体含义为:
Function |
Description |
DisplayInit |
Passes instance information, which allows the driver to find PCI configuration information for its device. The PCI bus driver populates the information if the driver has a PCI template in the registry. This is the first display driver function called by GWES. |
DrvAnyBlt |
Performs bit block transfers, with stretching or transparency. |
DrvBitBlt |
Performs general bit block transfers, with clipping and masking. Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, PolyBezier, SetPixel, BitBlt, MaskBlt, Rectangle, ExtTextOut, DrawText, and ExtTextOut GDI functions. |
DrvCopyBits |
Sends a GDI-created print band to a printer driver. Maps to the SetDIBitsToDevice GDI function. |
DrvCreateDeviceBitmap |
Creates and manages bitmap files. |
DrvDeleteDeviceBitmap |
Deletes a device bitmap file. |
DrvDisableDriver |
Notifies the display driver that the GDI no longer needs it and is ready to unload the driver. |
DrvDisablePDEV |
Notifies the driver that the GDI no longer needs a particular display device. |
DrvDisableSurface |
Notifies the driver that the GDI no longer needs a particular drawing surface. |
DrvEnableDriver |
Returns pointers to DDI functions to GDI. The initial entry point that is exposed by the driver. The driver exposes the second entry point if DisplayInit is implemented. |
DrvEnablePDEV |
Returns a PDEV structure to the GDI. A PDEV structure is a logical representation of a physical display device. |
DrvEnableSurface |
Creates a drawing surface and associates it with PDEV. |
DrvEndDoc |
Sends any control information that is needed to finish printing a document. |
DrvEscape |
Retrieves information from a device that is not available in a device-independent DDI. This function operates the same as with Windows NT, except that Windows CE does not support the DrvDrawEscape function. |
DrvFillPath |
Fills a drawing path with a brush. Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions. |
DrvGetMasks |
Gets the color masks for the display device's current mode. |
DrvGetModes |
Lists the display modes that are supported by the display device. |
DrvMovePointer |
Moves the pointer with a guarantee that the GDI will not interfere with the operation. |
DrvPaint |
Paints a specified region with a brush. Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions. |
DrvPowerHandler |
Called to handle POWER_UP and POWER_DOWN notifications. |
DrvRealizeBrush |
Creates a brush with parameters that are specified by the GDI. |
DrvRealizeColor |
Maps an RGB color onto the closest available color that is supported by the device. |
DrvSetPalette |
Sets the display device's palette. |
DrvSetPointerShape |
Sets the pointer to a new shape and updates the display. |
DrvStartDoc |
Sends any control information that is needed to start printing a document. |
DrvStartPage |
Sends any control information that is needed to start printing a new page. |
DrvStrokePath |
Renders a drawing path. Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions. |
DrvStrokeAndFillPath |
Maps to the MoveToEx, Polygon, Polyline, Ellipse, Rectangle, and PolyBezier GDI functions. |
DrvTransparentBlt |
Bit block transfer, with transparency. |
DrvUnrealizeColor |
Maps a color in the display device's format onto an RGB value. |
在ddi_if.cpp中微软提供了这些的DDI函数实现代码.
需要向GWES导出DDI函数的显示设备驱动程序都必须定义宏DDI. 在source文件中你可以看到:
!IFDEF CLEARTYPE
CDEFINES=$(CDEFINES) -DDDI -DCLEARTYPE
!ELSE
CDEFINES=$(CDEFINES) -DDDI
!ENDIF
既然DDI函数都由微软实现了,那么需要用户开发的是哪些呢,就是GPE继承类(SMDK2410 BSP中就是S3C2410DISP).下一篇我们就来详细介绍这个类及其实现.