第4卷图形驱动程序设计指南 第1部分图形驱动程序 第2部分显示器及视频微端口驱动程序 第3部分打印机驱动程序及假脱机打印部件
1 第 4 卷 图形驱动程序设计指南 第 1 部分 图形驱动程序 第 2 部分 显示器及视频微端口驱动程序 第 3 部分 打印机驱动程序及假脱机打印部件
第1部分图形驱动程序 第1章图形系统概述 第2章GDI支持的图形驱动程序 第3章对DDI的支持 第1章图形系统概述 Microsoft windows nt@/ Windows2000提供了一个健壮的图形体系结构,使第三方 图形硬件公司能很容易地集成其视频显示器和打印设备。本书为编写有效的图形驱动程序提 供了设计指南。可分为以下几个部分: Part 1:图形驱动程序 Part1描述了图形驱动程序接口(GDI)和设备驱动程序接口(DI),讨论了显示器 和打印机驱动程序公共的设计和实现细节。 Part2:显示器和视频微端口驱动程序 Part2描述了 Windows nt/ Windows2000的视频显示器环境,为显示器和视频微端口 驱动程序编写者提供了设计和实现细节。 Part3:打印机驱动程序和假脱机打印部件 Part3描述了构成 Windows nt/ Windows2000打印环境的驱动程序和假脱机打印部件, 解释了如何提供驱动程序和假脱机打印部件的定制,以提供对新的打印机硬件和网络配置的 支持。 Part4:静态映像驱动程序 Part4可以在在线DK上找到,描述了用 Microsoft静态映像体系结构( Microsoft SITI)定义的COM接口,这对提供平板扫描仪和数字静态映像相机这些静态映像硬件的供应 商是有用的 图形驱动程序的术语表,在在线DDK上 Design Guide的结尾可以找到,对图形子系 统和驱动程序设计定义了详细的术语和缩略语。 图形驱动程序函数参考可以在在线DDK的 Graphics Driver Reference中找到 1.1文档约定 本书使用的字体约定和所有其他的 Microsoft Windows@2000DDK书中的约定是一样 的。这些约定在驱动程序编写者指南中描述 许多DK视频和打印机代码例子中使用了匈牙利命名规则。匈牙利命名规则在平台SDK 文档中描述
2 第 1 部分 图形驱动程序 第 1 章 图形系统概述 第 2 章 GDI 支持的图形驱动程序 第 3 章 对 DDI 的支持 第 1 章 图形系统概述 Microsoft Windows NT/Windows 2000 提供了一个健壮的图形体系结构,使第三方 图形硬件公司能很容易地集成其视频显示器和打印设备。本书为编写有效的图形驱动程序提 供了设计指南。可分为以下几个部分: ▪ Part 1:图形驱动程序 Part 1 描述了图形驱动程序接口(GDI)和设备驱动程序接口(DDI),讨论了显示器 和打印机驱动程序公共的设计和实现细节。 ▪ Part 2:显示器和视频微端口驱动程序 Part 2 描述了 Windows NT/Windows 2000 的视频显示器环境,为显示器和视频微端口 驱动程序编写者提供了设计和实现细节。 ▪ Part 3:打印机驱动程序和假脱机打印部件 Part 3 描述了构成 Windows NT/Windows 2000 打印环境的驱动程序和假脱机打印部件, 解释了如何提供驱动程序和假脱机打印部件的定制,以提供对新的打印机硬件和网络配置的 支持。 ▪ Part 4:静态映像驱动程序 Part 4 可以在在线 DDK 上找到,描述了用 Microsoft 静态映像体系结构(Microsoft STI)定义的 COM 接口,这对提供平板扫描仪和数字静态映像相机这些静态映像硬件的供应 商是有用的。 图形驱动程序的术语表,在在线 DDK 上 Design Guide 的结尾可以找到,对图形子系 统和驱动程序设计定义了详细的术语和缩略语。 图形驱动程序函数参考可以在在线 DDK 的 Graphics Driver Reference 中找到。 1.1 文档约定 本书使用的字体约定和所有其他的 Microsoft Windows 2000 DDK 书中的约定是一样 的。这些约定在驱动程序编写者指南中描述。 许多DDK视频和打印机代码例子中使用了匈牙利命名规则。匈牙利命名规则在平台SDK 文档中描述
第2章对图形驱动程序的GD支持 本章描述了 Microsoft Windows nt⑧/ Windows2000图形设备接口(GDI),详细说明 了GDI提供的对图形驱动程序的支持。 本书中术语“GDI”指的是核心模式GDI(也称作图形引擎);对 Microsoft@win32 DDI的引用是显式的。核心模式GDⅠ也称作图形引擎 在线 Windows2000 DDK Graphics Driver Reference中记录了GDI函数和结构参考 大多数GDI函数声明和结构定义在 window.h中。对于显示器驱动程序, DirectDraw堆管理 器函数在 dmemmgr.h中声明。这两个文件都和 Windows2000DK一起发布 2.1从驱动程序的观点看GDI GDI是 Windows nt@/ Windows@2000图形驱动程序和应用之间的中介支持。应用程序 调用Win32@GDⅠ函数进行图形输出请求,这个请求通过核心模式GDI发送。然后核心模式 GDI把这些请求发送到相应的图形驱动程序,如显示器驱动程序或打印机驱动程序。核心模 式GDⅠ是一个不能被替代的系统提供的模块。 GDⅠ通过一系列设备驱动程序接口(DDI)函数和图形驱动程序通信。这些函数用其前 缀Drv标识。信息通过这些入口点的输入/输出参数在GDI和驱动程序之间传递。驱动程序 必须支持某些Drvx函数用于GDI调用。在返回GDI之前,驱动程序通过执行在其相关硬 件上相应的操作来支持GDI请求 GDⅠ本身包括许多图形输出能力,去除驱动程序中支持这些能力的需求就能减小驱动 程序的大小。GDI也输出驱动程序能够调用的服务函数,进一步减小了驱动程序必须提供支 持的图形输出能力。GDI服务函数用其Bng前缀标识,而提供访问GDI维护的结构的函数用 YxxOBJ Xxx的形式命名。 图2.1显示了这个通信流 图2.1图形驱动程序和GDI的相互作用 2.1.1作为应用图形语言的GD Win32GDⅠ和图形引擎都是完全与设备无关的。因此,应用不需要直接访问硬件。基 于一个应用图形请求,GDI与设备无关的驱动程序一起工作,为一组图形设备提供高品质的 图形输出。打印和显示设备使用相同的GDI代码路径 2.1.2作为绘制引擎的GDI 对于绘图操作,驱动程序首先必须对每个已经有效的PDEV结构启用一个表面。PDEV 是一个物理设备的逻辑表示。如果硬件能够用GDI标准格式的位图建立,GDI就能用来进行
3 第 2 章 对图形驱动程序的 GDI 支持 本章描述了 Microsoft Windows NT/Windows 2000 图形设备接口(GDI),详细说明 了 GDI 提供的对图形驱动程序的支持。 本书中术语“GDI”指的是核心模式 GDI(也称作图形引擎);对 Microsoft Win32 DDI 的引用是显式的。核心模式 GDI 也称作图形引擎。 在线 Windows 2000 DDK Graphics Driver Reference 中记录了 GDI 函数和结构参考。 大多数 GDI 函数声明和结构定义在 winddi.h 中。对于显示器驱动程序,DirectDraw 堆管理 器函数在 dmemmgr.h 中声明。这两个文件都和 Windows 2000 DDK 一起发布。 2.1 从驱动程序的观点看 GDI GDI 是 Windows NT/Windows 2000 图形驱动程序和应用之间的中介支持。应用程序 调用 Win32 GDI 函数进行图形输出请求,这个请求通过核心模式 GDI 发送。然后核心模式 GDI 把这些请求发送到相应的图形驱动程序,如显示器驱动程序或打印机驱动程序。核心模 式 GDI 是一个不能被替代的系统提供的模块。 GDI 通过一系列设备驱动程序接口(DDI)函数和图形驱动程序通信。这些函数用其前 缀 Drv 标识。信息通过这些入口点的输入/输出参数在 GDI 和驱动程序之间传递。驱动程序 必须支持某些 DrvXxx 函数用于 GDI 调用。在返回 GDI 之前,驱动程序通过执行在其相关硬 件上相应的操作来支持 GDI 请求。 GDI 本身包括许多图形输出能力,去除驱动程序中支持这些能力的需求就能减小驱动 程序的大小。GDI 也输出驱动程序能够调用的服务函数,进一步减小了驱动程序必须提供支 持的图形输出能力。GDI 服务函数用其 Eng 前缀标识,而提供访问 GDI 维护的结构的函数用 XxxOBJ_Xxx 的形式命名。 图 2.1 显示了这个通信流。 图 2.1 图形驱动程序和 GDI 的相互作用 2.1.1 作为应用图形语言的 GDI Win32 GDI 和图形引擎都是完全与设备无关的。因此,应用不需要直接访问硬件。基 于一个应用图形请求,GDI 与设备无关的驱动程序一起工作,为一组图形设备提供高品质的 图形输出。打印和显示设备使用相同的 GDI 代码路径。 2.1.2 作为绘制引擎的 GDI 对于绘图操作,驱动程序首先必须对每个已经有效的 PDEV 结构启用一个表面。PDEV 是一个物理设备的逻辑表示。如果硬件能够用 GDI 标准格式的位图建立,GDI 就能用来进行
些或所有的位图表面的绘制。GDI也能处理高级的过渡调色技术。 对于启用PDE和表面的信息,参考图形驱动程序参考中的 Dryenablepdey和 Dry Enablesurface函数。 2.1.2.1GDI管理的位图 GDI全部用设备无关位图(DIB)格式管理位图,包括每个像素1位、4位、8位、16 位、24位和32位。在这些位图上,GDI能进行所有的绘制直线、填充、文本输出以及位块 传输( bitblt)操作。这使得驱动程序用GDI进行所有的图形绘制,或者使用实现函数都是 可能的,因为硬件提供了特别支持 如果设备在DIB格式中有帧缓冲区,GDⅠ能够直接把一些或所有的图形输出到帧缓冲 区,因而减小了驱动程序的大小。如果设备使用了非标准格式的帧缓冲区,驱动程序就必须 实现所有要求的绘图函数。GDI还能模拟大多数绘图函数,尽管提高了性能上的代价:像素 在被GDI操作之前必须拷贝到一个标准格式的位图中,并且在绘图完成后必须拷贝回原来的 格式 2.1.2.2GDI管理的直线和曲线 GD提供了改进的直线和曲线的定义。在 DEVICE坐标中直线端点的坐标不要求是整数, 就像 Windows3.x一样。这允许驱动程序不进行大致的取舍就传送图形对象。在GDI中基本 的曲线是贝塞尔曲线(立方体锯齿)而不是一个椭圆。所有的GDI内部操作是用贝塞尔曲线 处理的,它们被大多数高端的设备支持。对那些不处理贝塞尔曲线的设备,GDI在调用驱动 程序绘制它们之前把曲线分割成直线段。 GDⅠ能够下载用路径形式填充的区域,还有矩形的形式。驱动程序能够把路径分解成 梯形或区间进行填充 2.1.2.3cDI管理的属性:画刷 GDⅠ也管理所有的属性。GDI把属性作为画刷传递给驱动程序:驱动程序通过把画刷 转换成有用的内部格式来实现它们。GDI为驱动程序维护这些转换信息。GDI还维护画刷所 有的状态:包括范围、相关性、当前位置和线型。驱动程序能够缓存信息但不用来维护任何 状态。除了初始化和画刷实现,GDⅠ仅调用驱动程序在设备上绘图。在调用驱动程序之前, GDI关心转换、区域锁定以及指针与非操作 当驱动程序要求使用还未实现的画刷,就需要回调GDI。GDI为画刷分配存储器并调 用驱动程序来实现它,如果需要,可以进行抖动处理。 2.1.2.4GDI过渡调色功能 GDIⅠ的过渡调色功能产生了高品质的抖动或颜色过渡调色映像,提供给没有内置这些 功能的打印设备和显示设备。颜色过渡调色能提供
4 一些或所有的位图表面的绘制。GDI 也能处理高级的过渡调色技术。 对于启用 PDEV 和表面的信息,参考图形驱动程序参考中的 DrvEnablePDEV 和 DrvEnableSurface 函数。 2.1.2.1 GDI 管理的位图 GDI 全部用设备无关位图(DIB)格式管理位图,包括每个像素 1 位、4 位、8 位、16 位、24 位和 32 位。在这些位图上,GDI 能进行所有的绘制直线、填充、文本输出以及位块 传输(bitblt)操作。这使得驱动程序用 GDI 进行所有的图形绘制,或者使用实现函数都是 可能的,因为硬件提供了特别支持。 如果设备在 DIB 格式中有帧缓冲区,GDI 能够直接把一些或所有的图形输出到帧缓冲 区,因而减小了驱动程序的大小。如果设备使用了非标准格式的帧缓冲区,驱动程序就必须 实现所有要求的绘图函数。GDI 还能模拟大多数绘图函数,尽管提高了性能上的代价:像素 在被 GDI 操作之前必须拷贝到一个标准格式的位图中,并且在绘图完成后必须拷贝回原来的 格式。 2.1.2.2 GDI 管理的直线和曲线 GDI提供了改进的直线和曲线的定义。在DEVICE坐标中直线端点的坐标不要求是整数, 就像 Windows 3.x 一样。这允许驱动程序不进行大致的取舍就传送图形对象。在 GDI 中基本 的曲线是贝塞尔曲线(立方体锯齿)而不是一个椭圆。所有的 GDI 内部操作是用贝塞尔曲线 处理的,它们被大多数高端的设备支持。对那些不处理贝塞尔曲线的设备,GDI 在调用驱动 程序绘制它们之前把曲线分割成直线段。 GDI 能够下载用路径形式填充的区域,还有矩形的形式。驱动程序能够把路径分解成 梯形或区间进行填充。 2.1.2.3 GDI 管理的属性:画刷 GDI 也管理所有的属性。GDI 把属性作为画刷传递给驱动程序:驱动程序通过把画刷 转换成有用的内部格式来实现它们。GDI 为驱动程序维护这些转换信息。GDI 还维护画刷所 有的状态:包括范围、相关性、当前位置和线型。驱动程序能够缓存信息但不用来维护任何 状态。除了初始化和画刷实现,GDI 仅调用驱动程序在设备上绘图。在调用驱动程序之前, GDI 关心转换、区域锁定以及指针与非操作。 当驱动程序要求使用还未实现的画刷,就需要回调 GDI。GDI 为画刷分配存储器并调 用驱动程序来实现它,如果需要,可以进行抖动处理。 2.1.2.4 GDI 过渡调色功能 GDI 的过渡调色功能产生了高品质的抖动或颜色过渡调色映像,提供给没有内置这些 功能的打印设备和显示设备。颜色过渡调色能提供:
在给定的设备上提供最高品质的可再现的彩色和灰度级别 在一组有限的强度级别上提高可视分辨率 在不同的输出设备之间改进彩色相关性 传统的模拟过渡调色是一个使用过渡调色屏幕的单元过程。这个屏幕由相等大小的单 元组成,中心到中心是固定的单元间隔。固定单元间隔调节墨水的浓度,而点的尺寸可以改 变,用来产生连续色调的印记。 在计算机上大多数打印或屏幕阴影也使用固定单元的像素尺寸。为模拟点大小的变 化,用一束像素的组合来模拟过渡调色屏幕。在 Windows nt@/ Windows@2000中,GDI包 括提供一个好的第一近似的过渡调色缺省参数。额外的设备指定信息能加进系统以改进输 出 2.2GDI/驱动程序的分工 为了理解图形驱动程序设计,弄懂GDI和驱动程序的角色以及它们如何协调是重要的 具有增强能力的GDⅠ能够处理很多图形驱动程序预先要求的操作。GDI对于管理一些对图形 操作很关键的数据结构,例如表面,也是有效的,尽管每个图形驱动程序必须访问它们。 2.2.1GDI和驱动程序的通信 驱动程序对于GDI仅输出一个函数: DryEnableDriver。所有其他的驱动程序支持的 函数,包括 DrvDisableDriver函数,是GDI通过一个指针数组来输出的。GDI调用 DryEnableDriver初始化驱动程序并返回驱动程序支持的DDI函数列表。因为有一些驱动程 序必须支持的函数,所以GDI处理操作不包括在驱动程序的 Dry EnableDriver例程的函数表 中。当驱动程序被卸载时,GDI调用 DryDisabledriver。DDI函数在第3章“支持D/”中 深入讨论 GDI使大量的服务对于驱动程序是可用的。这些服务分为两类:用户对象和服务例程。 2.2.1.1GDI用户对象 GDⅠ保护重要的内部数据结构,但通过把它们作为用户对象传递使驱动程序能访问这 些结构的公共域。用户对象是中间数据结构,在GDI数据结构和需要访问这些结构内的信息 的驱动程序之间提供了接口。驱动程序能把指向用户对象的指针传递回GDI,用以询问消息 信息或请求各种服务。带有公共域的用户对象有下列优点 排除了直接访问内部GDI数据结构相关的问题 为驱动程序提供了一个空间保存GDⅠ数据。例如, PATHOBJ结构能保存计算一个 复杂对象(如路径)要求的所有额外数据 下列用户对象是可用的 对象 描述
5 ▪ 在给定的设备上提供最高品质的可再现的彩色和灰度级别 ▪ 在一组有限的强度级别上提高可视分辨率 ▪ 在不同的输出设备之间改进彩色相关性 传统的模拟过渡调色是一个使用过渡调色屏幕的单元过程。这个屏幕由相等大小的单 元组成,中心到中心是固定的单元间隔。固定单元间隔调节墨水的浓度,而点的尺寸可以改 变,用来产生连续色调的印记。 在计算机上大多数打印或屏幕阴影也使用固定单元的像素尺寸。为模拟点大小的变 化,用一束像素的组合来模拟过渡调色屏幕。在 Windows NT/Windows 2000 中,GDI 包 括提供一个好的第一近似的过渡调色缺省参数。额外的设备指定信息能加进系统以改进输 出。 2.2 GDI/驱动程序的分工 为了理解图形驱动程序设计,弄懂 GDI 和驱动程序的角色以及它们如何协调是重要的。 具有增强能力的 GDI 能够处理很多图形驱动程序预先要求的操作。GDI 对于管理一些对图形 操作很关键的数据结构,例如表面,也是有效的,尽管每个图形驱动程序必须访问它们。 2.2.1 GDI 和驱动程序的通信 驱动程序对于 GDI 仅输出一个函数:DrvEnableDriver。所有其他的驱动程序支持的 函数,包括 DrvDisableDriver 函数,是 GDI 通过一个指针数组来输出的。GDI 调用 DrvEnableDriver 初始化驱动程序并返回驱动程序支持的 DDI 函数列表。因为有一些驱动程 序必须支持的函数,所以 GDI 处理操作不包括在驱动程序的 DrvEnableDriver 例程的函数表 中。当驱动程序被卸载时,GDI 调用 DrvDisableDriver。DDI 函数在第 3 章“支持 DDI”中 深入讨论。 GDI 使大量的服务对于驱动程序是可用的。这些服务分为两类:用户对象和服务例程。 2.2.1.1 GDI 用户对象 GDI 保护重要的内部数据结构,但通过把它们作为用户对象传递使驱动程序能访问这 些结构的公共域。用户对象是中间数据结构,在 GDI 数据结构和需要访问这些结构内的信息 的驱动程序之间提供了接口。驱动程序能把指向用户对象的指针传递回 GDI,用以询问消息 信息或请求各种服务。带有公共域的用户对象有下列优点: ▪ 排除了直接访问内部 GDI 数据结构相关的问题。 ▪ 为驱动程序提供了一个空间保存 GDI 数据。例如,PATHOBJ 结构能保存计算一个 复杂对象(如路径)要求的所有额外数据。 下列用户对象是可用的: 对象 描述
BRUSHOBJ 为图形函数定义了画刷对象,输出直线、文本或填充 驱动程序能调用 BRUSHOBJ服务来实现画刷或找到GDI预先缓存的实现方 CLIPOBJ 为绘图或填充提供能访问裁剪区的驱动程序。这个区域能用一系列矩形计 算 FLOATOBJ 允许图形驱动程序模拟浮点操作。浮点操作不适用所有其他的核心模式驱 动程序。 FONTOBJ 使驱动程序访问字体的一个特别的实例(或实现)的信息。 PALOBJ 包含RGB调色板颜色的结构:通过 PALOBJ cGetColors和 DrySet palette 函数可以访问。 PATHOBJ 定义路径指定要绘制什么(直线或贝塞尔曲线)。 PATHOBJ结构传递给驱 动程序用以描述要绘制或填充的一系列直线和贝塞尔曲线。 STROBJ 为驱动程序计算轮廓处理和位置的列表,描述如何绘制文本字符串。 SURFOBJ 识别一个表面,它可以是GDI位图、设备相关位图或设备管理的表面。更 多的信息参见表面类型。 XFORMOBJ 描述一个任意的线性二维变换,如几何宽度直线( geometric wide line) XLATEOBJ 主义从源表面格式到目的表面格式转换像素所需要的变换 2.2.1.2GDI服务例程 GDI输出许多服务例程,其名字的形式是Engx。驱动程序动态地连接到win32k.sys 来直接访问这些例程。GDI服务例程包括表面管理、绘图模拟以及路径、调色板、字体和文 本服务。这些服务在CD支持的服务中详细讨论。 2.2.2PDEV协商 任何图形驱动程序的首要任务之一是在驱动程序初始化期间使PDV有效。PDEV是物 理设备的逻辑表现。这个表现由驱动程序定义,一般是私有的数据结构。启用PDEV的更多 的信息参考 Dry Enablepdev。 通过 DrvEnablepDev函数,驱动程序必须给GDI提供信息,描述请求的设备及其能力。 驱动程序给GDI的一条重要信息是 DEVINFO结构的f1 Graphics Caps和f1 Graphics Caps2成 员中的一组图形能力标志( GCAPS XXX和 GCAPS2Xxx标志)。 能力标志允许GDⅠ确定那些操作是PDE支持的。例如,GDI测试能力标志,指示在 GDI尝试用这些基本的类型调用 DryStrokePath函数来绘制路径之前,PDEV是否能处理贝塞 尔曲线和几何宽度直线。如果能力标志指示PDEV不能处理这些基本类型,GDI断开直线或 曲线,使GDI能简化对驱动程序的调用。 从驱动程序一侧来看,无论何时驱动程序从GDI获得一个高级的路径相关的调用,如 果路径或裁剪区对设备进行的处理过于复杂,它可返回 FALSE 当驱动程序处理一条装饰线( cosmetic line)时它不能从 DryStrokePath返回 FALSE 因为它必须为装饰线处理任意复杂的裁剪区或造型。然而,如果路径是贝塞尔曲线或几何直 线, DryStrokePath能够返回 FALSE。当这种情况出现时,GDI把调用分割成简单的调用 就像能力标志位没有置1一样。例如,如果当 DryStrokePath发送一个几何直线时返回 FALSE,GDI简化直线并调用 DryFillPath函数 如果 DryStrokePath被报告一个错误,它必须返回 DDI ERROR 6
6 BRUSHOBJ 为图形函数定义了画刷对象,输出直线、文本或填充。 驱动程序能调用 BRUSHOBJ 服务来实现画刷或找到 GDI 预先缓存的实现方 法。 CLIPOBJ 为绘图或填充提供能访问裁剪区的驱动程序。这个区域能用一系列矩形计 算。 FLOATOBJ 允许图形驱动程序模拟浮点操作。浮点操作不适用所有其他的核心模式驱 动程序。 FONTOBJ 使驱动程序访问字体的一个特别的实例(或实现)的信息。 PALOBJ 包含 RGB 调色板颜色的结构;通过 PALOBJ_cGetColors 和 DrvSetPalette 函数可以访问。 PATHOBJ 定义路径指定要绘制什么(直线或贝塞尔曲线)。PATHOBJ 结构传递给驱 动程序用以描述要绘制或填充的一系列直线和贝塞尔曲线。 STROBJ 为驱动程序计算轮廓处理和位置的列表,描述如何绘制文本字符串。 SURFOBJ 识别一个表面,它可以是 GDI 位图、设备相关位图或设备管理的表面。更 多的信息参见表面类型。 XFORMOBJ 描述一个任意的线性二维变换,如几何宽度直线(geometric wide line)。 XLATEOBJ 定义从源表面格式到目的表面格式转换像素所需要的变换。 2.2.1.2 GDI 服务例程 GDI 输出许多服务例程,其名字的形式是 EngXxx。驱动程序动态地连接到 win32k.sys 来直接访问这些例程。GDI 服务例程包括表面管理、绘图模拟以及路径、调色板、字体和文 本服务。这些服务在 GDI 支持的服务中详细讨论。 2.2.2 PDEV 协商 任何图形驱动程序的首要任务之一是在驱动程序初始化期间使 PDEV 有效。PDEV 是物 理设备的逻辑表现。这个表现由驱动程序定义,一般是私有的数据结构。启用 PDEV 的更多 的信息参考 DrvEnablePDEV。 通过 DrvEnablePDEV 函数,驱动程序必须给 GDI 提供信息,描述请求的设备及其能力。 驱动程序给 GDI 的一条重要信息是 DEVINFO 结构的 flGraphicsCaps 和 flGraphicsCaps2 成 员中的一组图形能力标志(GCAPS_Xxx 和 GCAPS2_Xxx 标志)。 能力标志允许 GDI 确定那些操作是 PDEV 支持的。例如,GDI 测试能力标志,指示在 GDI 尝试用这些基本的类型调用 DrvStrokePath 函数来绘制路径之前,PDEV 是否能处理贝塞 尔曲线和几何宽度直线。如果能力标志指示 PDEV 不能处理这些基本类型,GDI 断开直线或 曲线,使 GDI 能简化对驱动程序的调用。 从驱动程序一侧来看,无论何时驱动程序从 GDI 获得一个高级的路径相关的调用,如 果路径或裁剪区对设备进行的处理过于复杂,它可返回 FALSE。 当驱动程序处理一条装饰线(cosmetic line)时它不能从 DrvStrokePath 返回 FALSE, 因为它必须为装饰线处理任意复杂的裁剪区或造型。然而,如果路径是贝塞尔曲线或几何直 线,DrvStrokePath 能够返回 FALSE。当这种情况出现时,GDI 把调用分割成简单的调用。 就像能力标志位没有置 1 一样。例如,如果当 DrvStrokePath 发送一个几何直线时返回 FALSE,GDI 简化直线并调用 DrvFillPath 函数。 如果 DrvStrokePath 被报告一个错误,它必须返回 DDI_ERROR
在GDI和驱动程序之间的这种协商,对依赖于PDEV的函数,允许GDI和驱动程序产 生高质量的输出而无须过多的通信。 2.2.3表面协商 绘图和文本输出要求一个绘制的表面。这个表面由 Dry EnableSurface函数创建并称 作主表面( primary surface)。它也被称作屏幕上的表面(On- screen surface),因为它出 现在视频显示器上。每个PDEV只能启用一个主表面,尽管一个驱动程序能够支持几个PDEV 支持 DrvCreateDeviceBitmap函数的驱动程序能够创建和使用其他的表面。这些位图表面称 作次要表面( secondary surface)或屏慕外的表面(of- screen surface)。对任一种类型 的表面,驱动程序负责确定它支持的绘图操作的类型。 2.2.3.1表面坐标 设备表面是22*2像素数组的子集。这些像素是由一对28位的带符号数寻址的。设备 表面左上角的像素坐标是(0,0)。设备表面位于这个坐标空间的右下象限,两个坐标都是 非负的 2.2.3.2DC原点 应用程序要求在22*2像素的数组范围内保存其图形。设备空间在DDI级有其他的尺 寸,因为窗口管理器可能用一个带符号的27位的坐标即DC原点偏移应用程序的坐标。DC 原点对驱动程序是不可见的,驱动程序在偏移执行之后才识别图形坐标 2.2.3.3FIX坐标 DI使用分数坐标,能够在设备表面上1/16像素的范围内表示一个位置。(在矢量设 备上,分数坐标比设备分辨率精确16倍。)分数坐标用32位数字表示,是带符号的28.4 位FIX表示法。在这种表示法中,高28位表示坐标的整数部分,最低的4位表示分数部分 例如,0x000000C℃等于+3.7500,0 X FFFFFFE8等于-1.5000 FIX坐标表示直线和贝塞尔曲线的控制点。对某一对象,如矩形裁剪区,GDI用带符 号的32位整数表示坐标。因为坐标是28位数,整数坐标最高的5位或者全清0或者全置1。 2.2.3.4表面类型 表面类型在如何处理它们的上下文中可以看到。这些类型如下: 引擎管理的表面 设备管理的表面(标准格式位图) 设备管理的表面(非标准表面)
7 在 GDI 和驱动程序之间的这种协商,对依赖于 PDEV 的函数,允许 GDI 和驱动程序产 生高质量的输出而无须过多的通信。 2.2.3 表面协商 绘图和文本输出要求一个绘制的表面。这个表面由 DrvEnableSurface 函数创建并称 作主表面(primary surface)。它也被称作屏幕上的表面(on-screen surface),因为它出 现在视频显示器上。每个 PDEV 只能启用一个主表面,尽管一个驱动程序能够支持几个 PDEV。 支持 DrvCreateDeviceBitmap 函数的驱动程序能够创建和使用其他的表面。这些位图表面称 作次要表面(secondary surface)或屏幕外的表面(off-screen surface)。对任一种类型 的表面,驱动程序负责确定它支持的绘图操作的类型。 2.2.3.1 表面坐标 设备表面是 2 28*228 像素数组的子集。这些像素是由一对 28 位的带符号数寻址的。设备 表面左上角的像素坐标是(0,0)。设备表面位于这个坐标空间的右下象限,两个坐标都是 非负的。 2.2.3.2 DC 原点 应用程序要求在 2 27*227 像素的数组范围内保存其图形。设备空间在 DDI 级有其他的尺 寸,因为窗口管理器可能用一个带符号的 27 位的坐标即 DC 原点偏移应用程序的坐标。DC 原点对驱动程序是不可见的,驱动程序在偏移执行之后才识别图形坐标。 2.2.3.3 FIX 坐标 DDI 使用分数坐标,能够在设备表面上 1/16 像素的范围内表示一个位置。(在矢量设 备上,分数坐标比设备分辨率精确 16 倍。)分数坐标用 32 位数字表示,是带符号的 28.4 位 FIX 表示法。在这种表示法中,高 28 位表示坐标的整数部分,最低的 4 位表示分数部分。 例如,0x0000003C 等于+3.7500,0xFFFFFFE8 等于-1.5000。 FIX 坐标表示直线和贝塞尔曲线的控制点。对某一对象,如矩形裁剪区,GDI 用带符 号的 32 位整数表示坐标。因为坐标是 28 位数,整数坐标最高的 5 位或者全清 0 或者全置 1。 2.2.3.4 表面类型 表面类型在如何处理它们的上下文中可以看到。这些类型如下: ▪ 引擎管理的表面 ▪ 设备管理的表面(标准格式位图) ▪ 设备管理的表面(非标准表面)
引擎管理的表面 引擎管理的表面有以下特征: 由GDⅠ创建和管理 用一种标准的DIB格式作为DIB创建:从上至下,原点位于左上角,或者从底向 上,原点位于左下角 类型为 STYPE BITMAP 表面没有相应的设备句柄。 标准格式位图是单平面、压缩像素(每个像素的数据用连续的方式存储)格式的位图 位图的每条扫描线在4字节的边界排列 在 EngCreateBitmap函数中创建的位图是DB格式。为了使引擎能管理位图,必须是 DIB格式。 设备管理的表面(标准格式位图) 设备管理的表面有以下特征: 通过对设备驱动程序的 DrvCreateDeviceBitmap函数的调用创建。 有一个表面的相关设备句柄( DHSURF:参见在线 DDK Graphics Driver Reference 中的 SURFOBJ。) 可以是透明的或不透明的。 不透明的设备管理表面是一种GDI既没有任何有关位图格式的信息,也没有位图中位 的参考信息的表面。因为这些原因,驱动程序最少必须支持 DryBitBlt、 DryText0ut和 DryStockePath函数。这样的表面的类型是 STYPE DEVICE。 透明的设备管理表面是一种GDI含有有关位图格式的信息并知道位图中位的位置的表 面。因为这个原因,驱动程序不需要实现任何绘图操作,并使它们都服从GDI。这样的表面 的类型是 STYPE BITMAP。 驱动程序为了转换不透明的位图到透明的位图,它必须调用 EngModifySurface函数。 通过这一调用,驱动程序通知GDI位图格式和在存储器中位图的位置。 设备管理的DIB表面允许驱动程序回调GD使GD在表面绘图。管理其自身表面的驱 动程序,也能通过在其表面周围封装DIB(用 EngCreateBitmap创建)而引用到GDI的回调, 使用DB除外。 设备管理的表面(非标准格式位图) 通过调用 EngCreateDeviceSurface函数使GDI创建表面并返回一个句柄,驱动程序 可以启用一个设备管理的非DIB表面。GDⅠ依赖驱动程序访问和控制绘制到何处,并从设备 管理的表面读出。 设备相关位图(DDB),有时称作设备格式位图,是另一种类型的非DIB、设备管理的 表面。DDB支持某些驱动程序,如VGA驱动程序,实现快速的位图到屏幕的块传送。DDB也 允许驱动程序在屏幕外的显示存储器绘制非DIB位图。如果请求了DDB,驱动程序能支持 DrvCreateDeviceBitmap函数并调用 EngCreateDeviceBitmap函数使引擎返回一个到位图的 句柄 2.2.3.5GDI彩色空间转换
8 引擎管理的表面 引擎管理的表面有以下特征: ▪ 由 GDI 创建和管理。 ▪ 用一种标准的 DIB 格式作为 DIB 创建:从上至下,原点位于左上角,或者从底向 上,原点位于左下角。 ▪ 类型为 STYPE_BITMAP。 ▪ 表面没有相应的设备句柄。 标准格式位图是单平面、压缩像素(每个像素的数据用连续的方式存储)格式的位图。 位图的每条扫描线在 4 字节的边界排列。 在 EngCreateBitmap 函数中创建的位图是 DIB 格式。为了使引擎能管理位图,必须是 DIB 格式。 设备管理的表面(标准格式位图) 设备管理的表面有以下特征: ▪ 通过对设备驱动程序的 DrvCreateDeviceBitmap 函数的调用创建。 ▪ 有一个表面的相关设备句柄(DHSURF;参见在线 DDK Graphics Driver Reference 中的 SURFOBJ。) ▪ 可以是透明的或不透明的。 不透明的设备管理表面是一种 GDI 既没有任何有关位图格式的信息,也没有位图中位 的参考信息的表面。因为这些原因,驱动程序最少必须支持 DrvBitBlt、DrvTextOut 和 DrvStockePath 函数。这样的表面的类型是 STYPE_DEVICE。 透明的设备管理表面是一种 GDI 含有有关位图格式的信息并知道位图中位的位置的表 面。因为这个原因,驱动程序不需要实现任何绘图操作,并使它们都服从 GDI。这样的表面 的类型是 STYPE_BITMAP。 驱动程序为了转换不透明的位图到透明的位图,它必须调用 EngModifySurface 函数。 通过这一调用,驱动程序通知 GDI 位图格式和在存储器中位图的位置。 设备管理的 DIB 表面允许驱动程序回调 GDI 使 GDI 在表面绘图。管理其自身表面的驱 动程序,也能通过在其表面周围封装 DIB(用 EngCreateBitmap 创建)而引用到 GDI 的回调, 使用 DIB 除外。 设备管理的表面(非标准格式位图) 通过调用 EngCreateDeviceSurface 函数使 GDI 创建表面并返回一个句柄,驱动程序 可以启用一个设备管理的非 DIB 表面。GDI 依赖驱动程序访问和控制绘制到何处,并从设备 管理的表面读出。 设备相关位图(DDB),有时称作设备格式位图,是另一种类型的非 DIB、设备管理的 表面。DDB 支持某些驱动程序,如 VGA 驱动程序,实现快速的位图到屏幕的块传送。DDB 也 允许驱动程序在屏幕外的显示存储器绘制非 DIB 位图。如果请求了 DDB,驱动程序能支持 DrvCreateDeviceBitmap 函数并调用EngCreateDeviceBitmap 函数使引擎返回一个到位图的 句柄。 2.2.3.5 GDI 彩色空间转换
GDI使用三个RGB颜色空间描述它的位图。在每个颜色空间中,三个位域,或颜色通 道,在给定的颜色中分别用来指定红、绿、蓝使用的位的数量。为了能匹配GDI的位图能力, 显示器驱动程序必须能从一个RGB颜色空间转换到另一个。 GDI能识别下列的颜色空间。 5,5,5RGB:红、绿、蓝都是5位颜色通道。 5,6,5RGB:红色是5位颜色通道,绿色是6位颜色通道,蓝色是5位颜色通道。 8,8,8RGB:红、绿、蓝都是8位颜色通道 通常,当从一个多位的颜色通道向少位的颜色通道转换时,GDI丢弃掉低位。当从 个少位的颜色通道向多位的通道转换时,较小通道的所有位全部拷贝到较大的通道。为了填 充较大通道的剩余位,较小通道的某些位将再次拷贝到较大的通道。下表概述了GDI从一个 RGB颜色空间转换到另一个所使用的规则。在这个表中,转换过程中值发生改变的颜色通道 用黑体表示。 GDI颜色空间转换规则 From 规则 例子 5,5,55,6,5源的绿色通道的最高有效位(0x15,0x19,0x1D)变成 (MSB)加到目标的绿色通道(0x15,0x33,0x1D) 的低位最后 注意只有绿色通道改变。 源的5位通道的值是二进制 11001,转换成6位值, 110011 5,5,58,8,8对每个通道,源通道的3个(0x15,0x19,0x1D)变成 MSB加到目标通道的最低位的(0xAD,0xCE,0xEF 最后 在红色通道中,10101变成 10101101。类似的变化也出现 在绿色和蓝色通道。 5,5丢弃源绿色通道的最低有效(0x15,0x33,0x1D)变成 位(LSB)。 (0x15,0x19,0x1D)。 注意只有绿色通道改变。 丢弃110011的最低位,得到 5,6,58,8,8对源的5位通道(红色和蓝(0x15,0x33,0x1D)变成 色),从源通道拷贝3个MSB(0xAD,OxCE,OxEF) 加到目标通道的最低位的最在红色通道中 变成 后。对6位的绿色通道,从源10101101。在绿色通道中, 通道拷贝2个MSB加到目标通110011变成11001111蓝色 道的最低位的最后 通道的变化和红色通道类似 8,8,8 5,5丢弃源通道的3个最低有效(0xAB,0xCD,0xEF)变成 位(LSB)。 (0x15,0x19,0x1D)。 在红色通道中,10101101变 成10101。类似的变化也出现 在其他两个通道。 8,8,85,6,5丢弃红色和蓝色通道的3个(0xAB,0xCD,0xEF)变成 最低有效位(LSB)。丢弃绿色(0x15,0x33,0x1D) 通道的2个最低有效位在绿色通道中,11001101变 (LSB) 成110011。红色和蓝色通道 的变化与前面列出的变换相
9 GDI 使用三个 RGB 颜色空间描述它的位图。在每个颜色空间中,三个位域,或颜色通 道,在给定的颜色中分别用来指定红、绿、蓝使用的位的数量。为了能匹配 GDI 的位图能力, 显示器驱动程序必须能从一个 RGB 颜色空间转换到另一个。 GDI 能识别下列的颜色空间。 ▪ 5,5,5RGB:红、绿、蓝都是 5 位颜色通道。 ▪ 5,6,5RGB:红色是 5 位颜色通道,绿色是 6 位颜色通道,蓝色是 5 位颜色通道。 ▪ 8,8,8RGB:红、绿、蓝都是 8 位颜色通道。 通常,当从一个多位的颜色通道向少位的颜色通道转换时,GDI 丢弃掉低位。当从一 个少位的颜色通道向多位的通道转换时,较小通道的所有位全部拷贝到较大的通道。为了填 充较大通道的剩余位,较小通道的某些位将再次拷贝到较大的通道。下表概述了 GDI 从一个 RGB 颜色空间转换到另一个所使用的规则。在这个表中,转换过程中值发生改变的颜色通道 用黑体表示。 GDI 颜色空间转换规则 From To 规则 例子 5,5,5 5,6,5 源的绿色通道的最高有效位 (MSB)加到目标的绿色通道 的低位最后。 (0x15,0x19,0x1D)变成 (0x15,0x33,0x1D)。 注意只有绿色通道改变。 源的 5 位通道的值是二进制 11001 ,转换成 6 位值, 110011。 5,5,5 8,8,8 对每个通道,源通道的 3 个 MSB 加到目标通道的最低位的 最后。 (0x15,0x19,0x1D)变成 (0xAD,0xCE,0xEF)。 在红色通道中,10101 变成 10101101。类似的变化也出现 在绿色和蓝色通道。 5,6,5 5,5,5 丢弃源绿色通道的最低有效 位(LSB)。 (0x15,0x33,0x1D)变成 (0x15,0x19, 0x1D)。 注意只有绿色通道改变。 丢弃 110011 的最低位,得到 11001。 5,6,5 8,8,8 对源的 5 位通道(红色和蓝 色),从源通道拷贝 3 个 MSB 加到目标通道的最低位的最 后。对 6 位的绿色通道,从源 通道拷贝2个MSB加到目标通 道的最低位的最后。 (0x15,0x33,0x1D)变成 (0xAD,0xCE,0xEF)。 在红色通道中,10101 变成 10101101。在绿色通道中, 110011 变成 11001111。蓝色 通道的变化和红色通道类似。 8,8,8 5,5,5 丢弃源通道的 3 个最低有效 位(LSB)。 (0xAB,0xCD,0xEF)变成 (0x15,0x19,0x1D)。 在红色通道中,10101101 变 成 10101。类似的变化也出现 在其他两个通道。 8,8,8 5,6,5 丢弃红色和蓝色通道的 3 个 最低有效位(LSB)。丢弃绿色 通 道 的 2 个 最 低 有 效 位 (LSB)。 (0xAB,0xCD,0xEF)变成 (0x15,0x33,0x1D)。 在绿色通道中,11001101 变 成 110011。红色和蓝色通道 的变化与前面列出的变换相 同
2. 3. 6 Hooking A Punting 术语 poking和 Punting指的是驱动程序决定是否提供标准的位图绘画操作,或依赖 GDI提供这些操作。如果驱动程序实现了引擎管理的表面,GDI能处理所有的绘图操作。然 而,如果硬件能加速这些操作,驱动程序能提供一个或更多的绘图函数。通过实现,或 Hooking Drv Xxa函数来做到这一点 也许只想实现绘图操作的一个子集,实现一个特殊的DDI接口点。对它不支持的任何 操作,驱动程序能调用相应的GDI函数来实现。这称作 Punting到GDI。有一些情形是操作 必须在驱动程序内实现。例如,如果驱动程序实现了一个设备管理的表面,某些绘图函数必 须在显示器驱动程序内完成 ooking 缺省情况下,当绘图表面是引擎管理的表面时,ωDⅠ处理绘画(绘图)操作。驱动程 序利用硬件对一给定的表面,为一些或所有的绘图函数提供了加速,或者使用了特别的块传 送硬件,能够hook这些函数。对于hok调用,驱动程序把hook指定为 EngAssociateSurface 和 EngModifySurface函数 flOck参数的标记。 如果驱动程序指定了一个函数的hook标记,它必须提供在其支持DDI入口点的列表 中的函数。驱动程序能够优化具有硬件支持的操作。这样的驱动程序在一个hook调用中可 能只能处理某一种情况。例如,如果在一个hook调用中请求了复杂的图形,它可能还要更 有效地直接回调GDI,允许GDI处理操作 这里还有另一个例子,驱动程序选择是否处理hook调用。考虑应该支持硬件的驱动 程序,有能力用某些ROP处理位块传输调用。即使驱动程序能够独立地实现许多操作,其他 方面仅是一个缓冲区。这样的驱动程序将为帧缓冲区给位图表面返回一个句柄,就像为其 PDEV表面一样,但它将为自己 hook drybitblt调用。当GDI调用 DryBitblt时,驱动程序 能够检查R尸来看它是否是由硬件支持的一个函数。如果不是,驱动程序能通过对 Engbitblt 的一个调用把操作传递GDI。 支持设备管理表面的驱动程序必须向外hook一些绘图函数,名字是 DrvCopyBits、 DryTextout和 DryStrokepath。虽然GDI模拟能够处理其他绘图函数,因为性能上的原因推 荐这种类型的驱动程序hok其他函数,就像 DryBitB1t和 Drv Realizebrush函数,因为模 拟需要从或向表面绘图。 Punting Punting回调到GDI的意思是提交一个调用到相应的GDI模拟。通常,对每个Drvx 调用都有一个相应的 GDI Eng xx模拟调用,带有相同的参数。在驱动程序制作透明的位图 时,所有的参数都没有改变地传递到GDI模拟。对每个调用驱动程序punt回GDI,驱动程 序的大小缩减了(因为功能上的代码忽略了)。然而,因为引擎拥有调用,驱动程序在执行 速度上没有控制。对一些复杂的情况,在驱动程序中提供支持也许没有实际的优势 可以hook的GDI图形输出函数 驱动程序能够hook的图形输出函数和相应的GDI模拟在下表中列出 驱动程序图形输出函数 相应的GDI模拟 Drybitblt EngBitBlt DrvPlgblt EngPlgblt DryStretchBlt EngStretchBlt
10 2.2.3.6 Hooking 和 Punting 术语 Hooking 和 Punting 指的是驱动程序决定是否提供标准的位图绘画操作,或依赖 GDI 提供这些操作。如果驱动程序实现了引擎管理的表面,GDI 能处理所有的绘图操作。然 而,如果硬件能加速这些操作,驱动程序能提供一个或更多的绘图函数。通过实现,或 Hooking DrvXxx 函数来做到这一点。 也许只想实现绘图操作的一个子集,实现一个特殊的 DDI 接口点。对它不支持的任何 操作,驱动程序能调用相应的 GDI 函数来实现。这称作 Punting 到 GDI。有一些情形是操作 必须在驱动程序内实现。例如,如果驱动程序实现了一个设备管理的表面,某些绘图函数必 须在显示器驱动程序内完成。 Hooking 缺省情况下,当绘图表面是引擎管理的表面时,GDI 处理绘画(绘图)操作。驱动程 序利用硬件对一给定的表面,为一些或所有的绘图函数提供了加速,或者使用了特别的块传 送硬件,能够 hook 这些函数。对于 hook 调用,驱动程序把 hook 指定为 EngAssociateSurface 和 EngModifySurface 函数 flHook 参数的标记。 如果驱动程序指定了一个函数的 hook 标记,它必须提供在其支持 DDI 入口点的列表 中的函数。驱动程序能够优化具有硬件支持的操作。这样的驱动程序在一个 hook 调用中可 能只能处理某一种情况。例如,如果在一个 hook 调用中请求了复杂的图形,它可能还要更 有效地直接回调 GDI,允许 GDI 处理操作。 这里还有另一个例子,驱动程序选择是否处理 hook 调用。考虑应该支持硬件的驱动 程序,有能力用某些 ROP 处理位块传输调用。即使驱动程序能够独立地实现许多操作,其他 方面仅是一个缓冲区。这样的驱动程序将为帧缓冲区给位图表面返回一个句柄,就像为其 PDEV 表面一样,但它将为自己 hook DrvBitBlt 调用。当 GDI 调用 DrvBitBlt 时,驱动程序 能够检查 ROP 来看它是否是由硬件支持的一个函数。如果不是,驱动程序能通过对 EngBitBlt 的一个调用把操作传递 GDI。 支持设备管理表面的驱动程序必须向外 hook 一些绘图函数,名字是 DrvCopyBits、 DrvTextOut 和 DrvStrokePath。虽然 GDI 模拟能够处理其他绘图函数,因为性能上的原因推 荐这种类型的驱动程序 hook 其他函数,就像 DrvBitBlt 和 DrvRealizeBrush 函数,因为模 拟需要从或向表面绘图。 Punting Punting 回调到 GDI 的意思是提交一个调用到相应的 GDI 模拟。通常,对每个 DrvXxx 调用都有一个相应的 GDI EngXxx 模拟调用,带有相同的参数。在驱动程序制作透明的位图 时,所有的参数都没有改变地传递到 GDI 模拟。对每个调用驱动程序 punt 回 GDI,驱动程 序的大小缩减了(因为功能上的代码忽略了)。然而,因为引擎拥有调用,驱动程序在执行 速度上没有控制。对一些复杂的情况,在驱动程序中提供支持也许没有实际的优势。 可以 hook 的 GDI 图形输出函数 驱动程序能够 hook 的图形输出函数和相应的 GDI 模拟在下表中列出。 驱动程序图形输出函数 相应的 GDI 模拟 DrvBitBlt EngBitBlt DrvPlgBlt EngPlgBlt DrvStretchBlt EngStretchBlt