基于win2k写的,又是一本古老的书,甚至书上好多例子使用的库已经改头换面了,调试也没法做了。不过,在市面上还真找不到其他深入讲述系统图形内部原理的书,真是鸡肋。书中内容很多,而且相对抽象,学习了差不多一个月,只学了几章,苦于很多东西没法调试——书上讲的和系统已经搭配不上了。现在只是把一些重点梳理一下,打下一点理论基础。
操作系统的图形和多媒体系统是分层的系统,最上面的应用程序通过Win32API和一套32位用户模式系统DLL接口实现功能。系统DLL层包括类似的DLL,如GDI32.dll,USER32.dll,KERNEL32.dll。系统DLL层的大多数模块是由操作系统提供的,但是这一层的组件依赖于硬件销售商提供的用户模式驱动程序。在这下面是系统服务调用入口,它激活由操作系统的内核模式中的系统服务例程提供的系统调用。在内核地址空间中的WindowsNt/2000执行体提供图形引擎、IO管理器、视频端口驱动程序等来支持图形和多媒体系统。
在用户模式层,图形设备界面(GDI)和图像颜色管理(ICM)为应用程序提供与设备无关的图形编程界面。
DirectX为Win32系统DLL加入一套比较新的对DirectXCOM界面操作的DLL,它执行DirectXCOM界面。对于实际与内核地址空间中DirectX执行的接口,DirectX则是通过GDI来完成的。
一、GDI体系结构
GDI提供几百个Windows程序中可以调用的函数。这些函数大多是从Win32的子系统DLL——GDI32.dll中导出的。窗口管理模块USER32.dll是使用GDI函数的大用户,它用GDI函数来绘制菜单、图标、滚动条、标题栏和每个窗口的框架等细节内容。有一些绘图函数从USER32.dll导出,提供给应用程序。windows2000提供543个入口点——win7提供714个入口点。
这些函数按功能分为17类,至今的win7的MSDN上的说明还是这种分类:
- Bitmaps
- Brushes
- Clipping
- Colors
- Coordinate Spaces and Transformations
- Device Contexts
- Filled Shapes
- Fonts and Text
- Lines and Curves
- Metafiles
- Multiple Display Monitors
- Painting and Drawing
- Paths
- Pens
- Printing and Print Spooler
- Rectangles
- Regions
在Win32子系统DLL中,GDI32.dll是相对较少的模块。GDI通过windowsNT/2000系统调用或本地API调用GDI图形引擎来实现其大部分功能。Win32子系统 DLLGDI32.dll通过把Win32API调用变成系统服务调用实现Win32GDIAPI,系统服务调用是win32k.sys中的GDI图形引擎实现的。而像元文件、增强型元文件和EMF打印卸载确实是GDI32.dll提供的新功能,这些新功能没有依靠GDI引擎的直接帮助。
书上有介绍DirectX的体系结构,都是使用COM技术建立在GDI和其他OS服务上面的,这里不展开了。需要展开的是DirectX中的一个部分:DirectDraw体系结构。
二、DirectDraw体系结构
DirectDraw可以看作是GDI的特殊化。特殊化的第一步是把它的上村限制在计算机显示卡而不是其他设备上。第二步是减少GDI支持的功能。最后一步是实现硬件加速的有限功能,并添加对高性能游戏和多媒体编程至关重要的功能。
DirectDraw体系结构包括用户模式和内核模式组件。DirectDraw的用户模式组件是ddraw.dll,它与gdi32.dll和mcd.dll(OpenGL)相关。实际上,DirectDrawAPI是由DDRAW.dll实现的,而DDRAW.dll通过GDI32.dll与GDI引擎交互,进而与DirectDraw设备驱动程序交互。
DirectDraw分几层实现。最上面的层支持DirectDraw COM接口、标准COM导出函数(DllGetClassObject等)及特殊DirectDraw创建例程(DirectDrawCreate等)。中间层是硬件仿真层(HEL),它模仿硬件不支持的所有或部分DirectDraw功能。底层叫做硬件抽象层(HAL),直接和显示硬件对话。DirectDrawAPI和HEL都是用户模式的,不能直接访问DirectDrawHAL,DirectDrawHAL在windowsNT/2k中是内核模式的。
三、图形引擎
windowsNT/2k图形引擎是GDI的支柱,是通往图形设备驱动程序的大门,也是其他驱动程序是基石。图形引擎在一个内核模式DLL中,这个DLL还实现操作系统窗口管理的功能——即WIN32K.SYS。WIN32K.SYS可以看做内核支柱,实现Windows操作系统中的两个重要模块:USER32.dll和GDI32.dll。WIN32K.SYS本身就是一个很大的DLL。
图形引擎系统服务一般是NtGdi开头。窗口管理服务一般以NtUser开头。
图形绘制引擎(GraphicsRenderEngine),图形引擎自己和图形引擎驱动程序都使用GRE。GREAPI和Win32GDIAPI有很大不同。GRE和图形引擎使用的一些主要概念列表如下:GDI管理的位图,坐标空间,表面,钩入和踢回,绘制图元。
图形引擎将WIN32GDI绘图调用合并、分解成一些图元绘制命令,它们是GRE支持的绘图调用,下面是简单总结:
*EngLineTo和EngStmkePath绘制所有的直线和曲线
*EngFillPath和EngPaint用画刷填充闭合面
*EngStoke和FillPath用画刷填充闭合面,用画笔一点一点地绘制其边界
*EngBltBlt,EngPlgBlt,EngStretchBlt,EngStretchBltROP,EngCopyBits,EngAlphaBlend,EngTransparenBlt实现位图绘制API。
*EngGradientFill完成面渐变填充
*EngTestOut处理所有文本绘图调用
除简化的绘制图元外,GRE使用一套全新的数据结构。这里不是指GDI句柄,实际上GRE在GDI句柄层下面或者后面。
图元变换。GDI API层负责把Win32API调用变成GRE图元。
*坐标系统。Win32API提供多种坐标系统,可以完成视口到窗口转换、映射模式和世界变换。而GRE/DDI使用设备坐标,设备坐标的大小是由绘图表面的大小决定的。WinewAPI调用中的坐标要转换成实际绘图表面设备坐标。
*椭圆曲线。GRE/DDI接口不支持椭圆曲线,像圆、弧、或者椭圆。它们需要被转化成贝赛尔曲线。
*曲线到路径。DDI接口只支持直线和路径,因此曲线图需要在内部黑鬼成路径对象。图形引擎有丰富的路径对象控制函数集。