作者: JIURL
邮箱: thejiurl@gmail.com
主页: http://jiurl.blogsome.com/
http://jiurl.yeah.net/
[前言]
这篇文章是以前写给自己备忘的一个研究文档的节选。
[gdi 显卡驱动]
显卡驱动将讨论,显卡驱动中支持 gdi 实现的部分。
如果是一个纯 frame buffer 的话,显卡不作任何加速,所有 gdi 的实现都是 win32k 中的代码软件实现,gdi 把 frame buffer 当作一个位图,直接访问,进行相应的绘制。当然,这种情况除非特意设计,否则的话,是不会出现的。
不是纯 frame buffer 的情况,gdi 不直接访问 frame buffer,
显卡硬件实现了某些硬件加速,可能实现了某些 gdi 需要的硬件加速。gdi 中,有硬件加速的,就交给显卡驱动来完成,没有硬件加速的,gdi 软件实现,然后把结果交给显卡驱动来完成显示。
显卡驱动至少需要实现,DrvCopyBits, DrvTextOut 和 DrvStrokePath,其他 gdi 函数可以软件实现,最终调用这几个驱动实现的函数,来把结果写入 frame buffer。
显卡驱动可以实现的 gdi 的功能:
DrvBitBlt
DrvPlgBlt
DrvStretchBlt
DrvStretchBltROP
DrvTextOut
DrvStrokePath
DrvFillPath
DrvStrokeAndFillPath
DrvLineTo
DrvCopyBits
DrvAlphaBlend
DrvGradientFill
DrvTransparentBlt
更多细节可以参考关于 SURFACE, HDC 等的讨论。
[显卡驱动]
显卡驱动(支持gdi部分)相关内容主要在下面的4个文件中:
win32k.sys
VideoPort.sys
disp 驱动 (.dll) (如 vga.dll)
mini port 驱动 (.sys) (如 vga.sys)
win32k.sys 和 VideoPort.sys 是系统文件。
disp 驱动 (.dll) 和 mini port 驱动 (.sys) 是显卡驱动。
[win32k.sys]
gdi 就是在 win32k.sys 中实现的。EngXxx 是在 win32k.sys 中实现的。
[VideoPort.sys]
mini port 驱动 将会调用 VideoPort.sys 导出的函数。
VideoPort.sys 导出的函数,例如:
VideoPortWritePortUlong
VideoPortZeroMemory
VideoPortInitialize
只是做了个简单封装,这样逻辑性更好一些,也使得 mini port 驱动的代码和 平台(体系结构)无关。
比如 VideoPortWritePortUlong,对x86,基本上也就是一条 out 指令。
[mini port 驱动 (.sys)]
查询显卡支持的所有可用的模式,查询和设置当前的显示模式(比如,1280*1024 16位色 刷新率60hz)。
大致也就是完成,对显卡初始化,对显卡的状态进行查询和设置,将寄存器映射到虚拟地址空间,等工作。
也就是一些对应 IOCTL_VIDEO_XXX 的实现的工作。
在 DriverEntry 中,调用 VideoPortInitiaze,设置 DRIVER_OBJECT 的 MajorFunction[],IoCreateDevice 创建 DEVICE_OBJECT。
[disp 驱动 (.dll)]
显卡驱动中最重要的部分。显卡驱动的主要工作在 “disp 驱动 (.dll)” 中完成。
它知道显卡硬件的细节,知道如何向显卡发命令,来让显卡硬件完成某个工作。
它将直接访问显卡的寄存器,来向显卡发命令,或者读取显卡的情况。可能显卡的一块寄存器最终映射到虚拟地址空间的话,那么驱动中就直接访问这部分虚拟地址空间。也可能还需要访问 io 端口。
DrvXxx 函数就是由 “disp 驱动 (.dll)” 提供的。
“disp 驱动 (.dll)” 中会调用 EngXxx。比如 EngCreateDeviceSurface,EngDeviceIoControl。也可能调用 EngXxx 来帮助完成某项绘制功能。
注意:disp 驱动 (.dll) 的入口点为 DrvEnableDriver。它将被载入系统地址空间。