图形驱动程序资料_第1页
图形驱动程序资料_第2页
图形驱动程序资料_第3页
图形驱动程序资料_第4页
图形驱动程序资料_第5页
已阅读5页,还剩339页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

.z.第4卷图形驱动程序设计指南第1局部图形驱动程序第2局部显示器及视频微端口驱动程序第3局部打印机驱动程序及假脱机打印部件第1局部图形驱动程序第1章图形系统概述第2章GDI支持的图形驱动程序第3章对DDI的支持第1章图形系统概述MicrosoftWindowsNT/Windows2000提供了一个强健的图形体系构造,使第三方图形硬件公司能很容易地集成其视频显示器和打印设备。本书为编写有效的图形驱动程序提供了设计指南。可分为以下几个局部:Part1:图形驱动程序Part1描述了图形驱动程序接口〔GDI〕和设备驱动程序接口〔DDI〕,讨论了显示器和打印机驱动程序公共的设计和实现细节。Part2:显示器和视频微端口驱动程序Part2描述了WindowsNT/Windows2000的视频显示器环境,为显示器和视频微端口驱动程序编写者提供了设计和实现细节。Part3:打印机驱动程序和假脱机打印部件Part3描述了构成WindowsNT/Windows2000打印环境的驱动程序和假脱机打印部件,解释了如何提供驱动程序和假脱机打印部件的定制,以提供对新的打印机硬件和网络配置的支持。Part4:静态映像驱动程序Part4可以在在线DDK上找到,描述了用Microsoft静态映像体系构造〔MicrosoftSTI〕定义的接口,这对提供平板扫描仪和数字静态映像相机这些静态映像硬件的供给商是有用的。图形驱动程序的术语表,在在线DDK上DesignGuide的结尾可以找到,对图形子系统和驱动程序设计定义了详细的术语和缩略语。图形驱动程序函数参考可以在在线DDK的GraphicsDriverReference中找到。1.1文档约定本书使用的字体约定和所有其他的MicrosoftWindows2000DDK书中的约定是一样的。这些约定在驱动程序编写者指南中描述。许多DDK视频和打印机代码例子中使用了匈牙利命名规则。匈牙利命名规则在平台SDK文档中描述。第2章对图形驱动程序的GDI支持本章描述了MicrosoftWindowsNT/Windows2000图形设备接口〔GDI〕,详细说明了GDI提供的对图形驱动程序的支持。本书中术语"GDI〞指的是核心模式GDI〔也称作图形引擎〕;对MicrosoftWin32DDI的引用是显式的。核心模式GDI也称作图形引擎。在线Windows2000DDKGraphicsDriverReference中记录了GDI函数和构造参考。大多数GDI函数声明和构造定义在winddi.h中。对于显示器驱动程序,DirectDraw堆管理器函数在dmemmgr.h中声明。这两个文件都和Windows2000DDK一起发布。2.1从驱动程序的观点看GDIGDI是WindowsNT/Windows2000图形驱动程序和应用之间的中介支持。应用程序调用Win32GDI函数进展图形输出请求,这个请求通过核心模式GDI发送。然后核心模式GDI把这些请求发送到相应的图形驱动程序,如显示器驱动程序或打印机驱动程序。核心模式GDI是一个不能被替代的系统提供的模块。GDI通过一系列设备驱动程序接口〔DDI〕函数和图形驱动程序通信。这些函数用其前缀Drv标识。信息通过这些入口点的输入/输出参数在GDI和驱动程序之间传递。驱动程序必须支持*些Drv***函数用于GDI调用。在返回GDI之前,驱动程序通过执行在其相关硬件上相应的操作来支持GDI请求。GDI本身包括许多图形输出能力,去除驱动程序中支持这些能力的需求就能减小驱动程序的大小。GDI也输出驱动程序能够调用的效劳函数,进一步减小了驱动程序必须提供支持的图形输出能力。GDI效劳函数用其Eng前缀标识,而提供GDI维护的构造的函数用***OBJ_***的形式命名。图2.1显示了这个通信流。图2.1图形驱动程序和GDI的相互作用2.1.1作为应用图形语言的GDIWin32GDI和图形引擎都是完全与设备无关的。因此,应用不需要直接硬件。基于一个应用图形请求,GDI与设备无关的驱动程序一起工作,为一组图形设备提供高品质的图形输出。打印和显示设备使用一样的GDI代码路径。2.1.2作为绘制引擎的GDI对于绘图操作,驱动程序首先必须对每个已经有效的PDEV构造启用一个外表。PDEV是一个物理设备的逻辑表示。如果硬件能够用GDI标准格式的位图建立,GDI就能用来进展一些或所有的位图外表的绘制。GDI也能处理高级的过渡调色技术。对于启用PDEV和外表的信息,参考图形驱动程序参考中的DrvEnablePDEV和DrvEnableSurface函数。GDI管理的位图GDI全部用设备无关位图〔DIB〕格式管理位图,包括每个像素1位、4位、8位、16位、24位和32位。在这些位图上,GDI能进展所有的绘制直线、填充、文本输出以及位块传输〔bitblt〕操作。这使得驱动程序用GDI进展所有的图形绘制,或者使用实现函数都是可能的,因为硬件提供了特别支持。如果设备在DIB格式中有帧缓冲区,GDI能够直接把一些或所有的图形输出到帧缓冲区,因而减小了驱动程序的大小。如果设备使用了非标准格式的帧缓冲区,驱动程序就必须实现所有要求的绘图函数。GDI还能模拟大多数绘图函数,尽管提高了性能上的代价:像素在被GDI操作之前必须拷贝到一个标准格式的位图中,并且在绘图完成后必须拷贝回原来的格式。GDI管理的直线和曲线GDI提供了改良的直线和曲线的定义。在DEVICE坐标中直线端点的坐标不要求是整数,就像Windows3.*一样。这允许驱动程序不进展大致的取舍就传送图形对象。在GDI中根本的曲线是贝塞尔曲线〔立方体锯齿〕而不是一个椭圆。所有的GDI内部操作是用贝塞尔曲线处理的,它们被大多数高端的设备支持。对那些不处理贝塞尔曲线的设备,GDI在调用驱动程序绘制它们之前把曲线分割成直线段。GDI能够下载用路径形式填充的区域,还有矩形的形式。驱动程序能够把路径分解成梯形或区间进展填充。GDI管理的属性:画刷GDI也管理所有的属性。GDI把属性作为画刷传递给驱动程序:驱动程序通过把画刷转换成有用的内部格式来实现它们。GDI为驱动程序维护这些转换信息。GDI还维护画刷所有的状态:包括范围、相关性、当前位置和线型。驱动程序能够缓存信息但不用来维护任何状态。除了初始化和画刷实现,GDI仅调用驱动程序在设备上绘图。在调用驱动程序之前,GDI关心转换、区域锁定以及指针与非操作。当驱动程序要求使用还未实现的画刷,就需要回调GDI。GDI为画刷分配存储器并调用驱动程序来实现它,如果需要,可以进展抖动处理。GDI过渡调色功能GDI的过渡调色功能产生了高品质的抖动或颜色过渡调色映像,提供给没有内置这些功能的打印设备和显示设备。颜色过渡调色能提供:在给定的设备上提供最高品质的可再现的彩色和灰度级别在一组有限的强度级别上提高可视分辨率在不同的输出设备之间改良彩色相关性传统的模拟过渡调色是一个使用过渡调色屏幕的单元过程。这个屏幕由相等大小的单元组成,中心到中心是固定的单元间隔。固定单元间隔调节墨水的浓度,而点的尺寸可以改变,用来产生连续色调的印记。在计算机上大多数打印或屏幕阴影也使用固定单元的像素尺寸。为模拟点大小的变化,用一束像素的组合来模拟过渡调色屏幕。在WindowsNT/Windows2000中,GDI包括提供一个好的第一近似的过渡调色缺省参数。额外的设备指定信息能加进系统以改良输出。2.2GDI/驱动程序的分工为了理解图形驱动程序设计,弄懂GDI和驱动程序的角色以及它们如何协调是重要的。具有增强能力的GDI能够处理很多图形驱动程序预先要求的操作。GDI对于管理一些对图形操作很关键的数据构造,例如外表,也是有效的,尽管每个图形驱动程序必须它们。2.2.1GDI和驱动程序的通信驱动程序对于GDI仅输出一个函数:DrvEnableDriver。所有其他的驱动程序支持的函数,包括DrvDisableDriver函数,是GDI通过一个指针数组来输出的。GDI调用DrvEnableDriver初始化驱动程序并返回驱动程序支持的DDI函数列表。因为有一些驱动程序必须支持的函数,所以GDI处理操作不包括在驱动程序的DrvEnableDriver例程的函数表中。当驱动程序被卸载时,GDI调用DrvDisableDriver。DDI函数在第3章"支持DDI〞中深入讨论。GDI使大量的效劳对于驱动程序是可用的。这些效劳分为两类:用户对象和效劳例程。GDI用户对象GDI保护重要的内部数据构造,但通过把它们作为用户对象传递使驱动程序能这些构造的公共域。用户对象是中间数据构造,在GDI数据构造和需要这些构造内的信息的驱动程序之间提供了接口。驱动程序能把指向用户对象的指针传递回GDI,用以询问消息信息或请求各种效劳。带有公共域的用户对象有以下优点:排除了直接内部GDI数据构造相关的问题。为驱动程序提供了一个空间保存GDI数据。例如,PATHOBJ构造能保存计算一个复杂对象〔如路径〕要求的所有额外数据。以下用户对象是可用的:对象描述BRUSHOBJ为图形函数定义了画刷对象,输出直线、文本或填充。驱动程序能调用BRUSHOBJ效劳来实现画刷或找到GDI预先缓存的实现方法。CLIPOBJ为绘图或填充提供能裁剪区的驱动程序。这个区域能用一系列矩形计算。FLOATOBJ允许图形驱动程序模拟浮点操作。浮点操作不适用所有其他的核心模式驱动程序。FONTOBJ使驱动程序字体的一个特别的实例〔或实现〕的信息。PALOBJ包含RGB调色板颜色的构造;通过PALOBJ_cGetColors和DrvSetPalette函数可以。PATHOBJ定义路径指定要绘制什么〔直线或贝塞尔曲线〕。PATHOBJ构造传递给驱动程序用以描述要绘制或填充的一系列直线和贝塞尔曲线。STROBJ为驱动程序计算轮廓处理和位置的列表,描述如何绘制文本字符串。SURFOBJ识别一个外表,它可以是GDI位图、设备相关位图或设备管理的外表。更多的信息参见外表类型。*FORMOBJ描述一个任意的线性二维变换,如几何宽度直线〔geometricwideline〕。*LATEOBJ定义从源外表格式到目的外表格式转换像素所需要的变换。GDI效劳例程GDI输出许多效劳例程,其名字的形式是Eng***。驱动程序动态地连接到win32k.sys来直接这些例程。GDI效劳例程包括外表管理、绘图模拟以及路径、调色板、字体和文本效劳。这些效劳在GDI支持的效劳中详细讨论。2.2.2PDEV协商任何图形驱动程序的首要任务之一是在驱动程序初始化期间使PDEV有效。PDEV是物理设备的逻辑表现。这个表现由驱动程序定义,一般是私有的数据构造。启用PDEV的更多的信息参考DrvEnablePDEV。通过DrvEnablePDEV函数,驱动程序必须给GDI提供信息,描述请求的设备及其能力。驱动程序给GDI的一条重要信息是DEVINFO构造的flGraphicsCaps和flGraphicsCaps2成员中的一组图形能力标志〔GCAPS_***和GCAPS2_***标志〕。能力标志允许GDI确定那些操作是PDEV支持的。例如,GDI测试能力标志,指示在GDI尝试用这些根本的类型调用DrvStrokePath函数来绘制路径之前,PDEV是否能处理贝塞尔曲线和几何宽度直线。如果能力标志指示PDEV不能处理这些根本类型,GDI断开直线或曲线,使GDI能简化对驱动程序的调用。从驱动程序一侧来看,无论何时驱动程序从GDI获得一个高级的路径相关的调用,如果路径或裁剪区对设备进展的处理过于复杂,它可返回FALSE。当驱动程序处理一条装饰线〔cosmeticline〕时它不能从DrvStrokePath返回FALSE,因为它必须为装饰线处理任意复杂的裁剪区或造型。然而,如果路径是贝塞尔曲线或几何直线,DrvStrokePath能够返回FALSE。当这种情况出现时,GDI把调用分割成简单的调用。就像能力标志位没有置1一样。例如,如果当DrvStrokePath发送一个几何直线时返回FALSE,GDI简化直线并调用DrvFillPath函数。如果DrvStrokePath被报告一个错误,它必须返回DDI_ERROR。在GDI和驱动程序之间的这种协商,对依赖于PDEV的函数,允许GDI和驱动程序产生高质量的输出而无须过多的通信。2.2.3外表协商绘图和文本输出要求一个绘制的外表。这个外表由DrvEnableSurface函数创立并称作主外表〔primarysurface〕。它也被称作屏幕上的外表〔on-screensurface〕,因为它出现在视频显示器上。每个PDEV只能启用一个主外表,尽管一个驱动程序能够支持几个PDEV。支持DrvCreateDeviceBitmap函数的驱动程序能够创立和使用其他的外表。这些位图外表称作次要外表〔secondarysurface〕或屏幕外的外表〔off-screensurface〕。对任一种类型的外表,驱动程序负责确定它支持的绘图操作的类型。外表坐标设备外表是228*228像素数组的子集。这些像素是由一对28位的带符号数寻址的。设备外表左上角的像素坐标是〔0,0〕。设备外表位于这个坐标空间的右下象限,两个坐标都是非负的。DC原点应用程序要求在227*227像素的数组范围内保存其图形。设备空间在DDI级有其他的尺寸,因为窗口管理器可能用一个带符号的27位的坐标即DC原点偏移应用程序的坐标。DC原点对驱动程序是不可见的,驱动程序在偏移执行之后才识别图形坐标。FI*坐标DDI使用分数坐标,能够在设备外表上1/16像素的范围内表示一个位置。〔在矢量设备上,分数坐标比设备分辨率准确16倍。〕分数坐标用32位数字表示,是带符号的28.4位FI*表示法。在这种表示法中,高28位表示坐标的整数局部,最低的4位表示分数局部。例如,0*0000003C等于+3.7500,0*FFFFFFE8等于-1.5000。FI*坐标表示直线和贝塞尔曲线的控制点。对*一对象,如矩形裁剪区,GDI用带符号的32位整数表示坐标。因为坐标是28位数,整数坐标最高的5位或者全清0或者全置1。外表类型外表类型在如何处理它们的上下文中可以看到。这些类型如下:引擎管理的外表设备管理的外表〔标准格式位图〕设备管理的外表〔非标准外表〕引擎管理的外表引擎管理的外表有以下特征:由GDI创立和管理。用一种标准的DIB格式作为DIB创立:从上至下,原点位于左上角,或者从底向上,原点位于左下角。类型为STYPE_BITMAP。外表没有相应的设备句柄。标准格式位图是单平面、压缩像素〔每个像素的数据用连续的方式存储〕格式的位图。位图的每条扫描线在4字节的边界排列。在EngCreateBitmap函数中创立的位图是DIB格式。为了使引擎能管理位图,必须是DIB格式。设备管理的外表〔标准格式位图〕设备管理的外表有以下特征:通过对设备驱动程序的DrvCreateDeviceBitmap函数的调用创立。有一个外表的相关设备句柄〔DHSURF;参见在线DDKGraphicsDriverReference中的SURFOBJ。〕可以是透明的或不透明的。不透明的设备管理外表是一种GDI既没有任何有关位图格式的信息,也没有位图中位的参考信息的外表。因为这些原因,驱动程序最少必须支持DrvBitBlt、DrvTe*tOut和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函数使引擎返回一个到位图的句柄。GDI彩色空间转换GDI使用三个RGB颜色空间描述它的位图。在每个颜色空间中,三个位域,或颜色通道,在给定的颜色中分别用来指定红、绿、蓝使用的位的数量。为了能匹配GDI的位图能力,显示器驱动程序必须能从一个RGB颜色空间转换到另一个。GDI能识别以下的颜色空间。5,5,5RGB:红、绿、蓝都是5位颜色通道。5,6,5RGB:红色是5位颜色通道,绿色是6位颜色通道,蓝色是5位颜色通道。8,8,8RGB:红、绿、蓝都是8位颜色通道。通常,当从一个多位的颜色通道向少位的颜色通道转换时,GDI丢弃掉低位。当从一个少位的颜色通道向多位的通道转换时,较小通道的所有位全部拷贝到较大的通道。为了填充较大通道的剩余位,较小通道的*些位将再次拷贝到较大的通道。下表概述了GDI从一个RGB颜色空间转换到另一个所使用的规则。在这个表中,转换过程中值发生改变的颜色通道用黑体表示。GDI颜色空间转换规则FromTo规则例子5,5,55,6,5源的绿色通道的最高有效位〔MSB〕加到目标的绿色通道的低位最后。〔0*15,0*19,0*1D〕变成〔0*15,0*33,0*1D〕。注意只有绿色通道改变。源的5位通道的值是二进制11001,转换成6位值,110011。5,5,58,8,8对每个通道,源通道的3个MSB加到目标通道的最低位的最后。〔0*15,0*19,0*1D〕变成〔0*AD,0*CE,0*EF〕。在红色通道中,10101变成10101101。类似的变化也出现在绿色和蓝色通道。5,6,55,5,5丢弃源绿色通道的最低有效位〔LSB〕。〔0*15,0*33,0*1D〕变成〔0*15,0*19,0*1D〕。注意只有绿色通道改变。丢弃110011的最低位,得到11001。5,6,58,8,8对源的5位通道〔红色和蓝色〕,从源通道拷贝3个MSB加到目标通道的最低位的最后。对6位的绿色通道,从源通道拷贝2个MSB加到目标通道的最低位的最后。〔0*15,0*33,0*1D〕变成〔0*AD,0*CE,0*EF〕。在红色通道中,10101变成10101101。在绿色通道中,110011变成11001111。蓝色通道的变化和红色通道类似。8,8,85,5,5丢弃源通道的3个最低有效位〔LSB〕。〔0*AB,0*CD,0*EF〕变成〔0*15,0*19,0*1D〕。在红色通道中,10101101变成10101。类似的变化也出现在其他两个通道。8,8,85,6,5丢弃红色和蓝色通道的3个最低有效位〔LSB〕。丢弃绿色通道的2个最低有效位〔LSB〕。〔0*AB,0*CD,0*EF〕变成〔0*15,0*33,0*1D〕。在绿色通道中,11001101变成110011。红色和蓝色通道的变化与前面列出的变换一样。和Punting术语Hooking和Punting指的是驱动程序决定是否提供标准的位图绘画操作,或依赖GDI提供这些操作。如果驱动程序实现了引擎管理的外表,GDI能处理所有的绘图操作。然而,如果硬件能加速这些操作,驱动程序能提供一个或更多的绘图函数。通过实现,或HookingDrv***函数来做到这一点。也许只想实现绘图操作的一个子集,实现一个特殊的DDI接口点。对它不支持的任何操作,驱动程序能调用相应的GDI函数来实现。这称作Punting到GDI。有一些情形是操作必须在驱动程序内实现。例如,如果驱动程序实现了一个设备管理的外表,*些绘图函数必须在显示器驱动程序内完成。Hooking缺省情况下,当绘图外表是引擎管理的外表时,GDI处理绘画〔绘图〕操作。驱动程序利用硬件对一给定的外表,为一些或所有的绘图函数提供了加速,或者使用了特别的块传送硬件,能够hook这些函数。对于hook调用,驱动程序把hook指定为EngAssociateSurface和EngModifySurface函数flHook参数的标记。如果驱动程序指定了一个函数的hook标记,它必须提供在其支持DDI入口点的列表中的函数。驱动程序能够优化具有硬件支持的操作。这样的驱动程序在一个hook调用中可能只能处理*一种情况。例如,如果在一个hook调用中请求了复杂的图形,它可能还要更有效地直接回调GDI,允许GDI处理操作。这里还有另一个例子,驱动程序选择是否处理hook调用。考虑应该支持硬件的驱动程序,有能力用*些ROP处理位块传输调用。即使驱动程序能够独立地实现许多操作,其他方面仅是一个缓冲区。这样的驱动程序将为帧缓冲区给位图外表返回一个句柄,就像为其PDEV外表一样,但它将为自己hookDrvBitBlt调用。当GDI调用DrvBitBlt时,驱动程序能够检查ROP来看它是否是由硬件支持的一个函数。如果不是,驱动程序能通过对EngBitBlt的一个调用把操作传递GDI。支持设备管理外表的驱动程序必须向外hook一些绘图函数,名字是DrvCopyBits、DrvTe*tOut和DrvStrokePath。虽然GDI模拟能够处理其他绘图函数,因为性能上的原因推荐这种类型的驱动程序hook其他函数,就像DrvBitBlt和DrvRealizeBrush函数,因为模拟需要从或向外表绘图。PuntingPunting回调到GDI的意思是提交一个调用到相应的GDI模拟。通常,对每个Drv***调用都有一个相应的GDIEng***模拟调用,带有一样的参数。在驱动程序制作透明的位图时,所有的参数都没有改变地传递到GDI模拟。对每个调用驱动程序punt回GDI,驱动程序的大小缩减了〔因为功能上的代码忽略了〕。然而,因为引擎拥有调用,驱动程序在执行速度上没有控制。对一些复杂的情况,在驱动程序中提供支持也许没有实际的优势。可以hook的GDI图形输出函数驱动程序能够hook的图形输出函数和相应的GDI模拟在下表中列出。驱动程序图形输出函数相应的GDI模拟DrvBitBltEngBitBltDrvPlgBltEngPlgBltDrvStretchBltEngStretchBltDrvStretchBltROPEngStretchBltROPDrvTe*tOutEngTe*tOutDrvStrokePathEngStrokePathDrvFillPathEngFillPathDrvStrokeAndFillPathEngStrokeAndFillPathDrvLineToEngLineToDrvCopyBitsEngCopyBitsDrvAlphaBlendEngAlphaBlendDrvGradientFillEngGradientFillDrvTransparentBltEngTransparentBlt2.3GDI支持的效劳GDI输出许多效劳例程,能简化驱动程序的设计。驱动程序能够直接调用这些例程。通常图形引擎效劳例程的名字以Eng开头。与特殊的对象相关的效劳例程总是用对象的名字开头;例如,CLIPOBJ_cEnumStart是一个CLIPOBJ效劳。注意第一个参数是用户对象的指针的任务例程,是用户对象的方法和使用通常的C++惯例调用。因此,用C++写的驱动程序能作为方法效劳例程。这些效劳例程有以下几类:外表管理调色板效劳路径效劳绘图效劳字体和文本效劳第3章"支持DDI〞描述了DDI的入口点,并解释许多这些效劳例程能用来帮助驱动程序实现入口点。每个效劳函数的详细描述参见在线DDK。2.3.1GDI对外表的支持对每个PDEV,驱动程序必须支持DrvEnableSurface函数。DrvEnableSurface建立要绘制的外表并将其和PDEV相关。驱动程序也必须支持DrvDisableSurface函数停顿创立的外表。因为GDI创立和维护外表,驱动程序依赖几个GDI效劳函数〔在下页的表中列出〕实现启用和制止外表。函数名用途EngAssociateSurface用PDEV相关一个外表并定义驱动程序编写者要hook的那个外表的绘图操作。它使用PDEV缺省的调色板和方式步骤。驱动程序在DrvEnableSurface的执行过程中必须对主外表进展调用。当驱动程序在锁定外表进展写之前启用第二个外表时,也必须进展这个调用。EngCheckAbort(仅针对打印机)使打印机驱动程序能够测定打印机的工作是否已经完毕。EngCreateBitmap创立一个标准格式DIB。在这种类型外表上GDI能够执行所有绘图操作。EngCreateDeviceBitmap创立一个DDB,驱动程序在上面绘图是可靠的〔虽然也可创立一个DIB,在这种情况下驱动程序能够回调以使GDI在上面绘图。EngCreateDeviceSurface创立一个设备管理外表。驱动程序为这个外表管理*些绘图操作是可靠的。此函数又返回一个驱动程序管理句柄。EngDeleteSurface删除一个外表〔DIB,DDB,或设备管理外表〕EngEraseSurface在外表上用给定的颜色填充指定的矩形,有效地去除外表。调用这个函数仅可去除一个GDI位图外表。EngLockSurface通过创立外表的一个用户对象〔SURFOBJ〕使驱动程序已创立的外表。〔源外表是不锁定的。〕EngMarkBandingSurface(仅针对打印机)标记外表为相关的外表。EngUnlockSurface当驱动程序已完成一项绘图操作时释放一个外表〔制止第二个外表时调用此函数〕这些函数更详细的内容,请参考在线DDK。2.3.2GDI支持的调色板GDI可以做大多数有关调色板管理的工作。当GDI调用DrvEnablePDEV函数,驱动程序把缺省的调色板作为DEVINFO构造的一局部返回到GDI。驱动程序必须用EngCreatePalette函数创立这个调色板。调色板有效地把32位颜色索引映射到24位RGB颜色值,这是GDI使用调色板的方法。驱动程序指定其调色板,这样GDI能确定不同的颜色索引如何在设备上出现。驱动程序只要使用GDI提供的*LATEOBJ,就不需要处理大多数调色板操作和计算。如果设备支持可改变的调色板,必须实现DrvSetPalette函数。当应用为设备改变调色板并把作为结果的新调色板传递给驱动程序时,GDI调用DrvSetPalette。驱动程序要设置内部的硬件调色板,尽可能地匹配新调色板。可以用下表列出的两种格式为GDI定义调色板。调色板格式描述Inde*ed一个颜色索引是RGB值的数组的一个索引。这一数组可以是小的,例如,包括16个颜色索引;或者是大的,例如,包括4096个颜色索引,甚至更多。BitFields颜色索引里的位域依据每一种颜色里R、G和B的数量指定颜色。例如,5位能够用来为每一种颜色提供0和31之间的一个值。当转换为RGB时,每个局部的5位的值将放大到包括0~255的范围。〔通常RGB代表自己是由位域定义的〕相反,GDI一般使用调色板映射。也就是说,应用指定一个RGB颜色进展绘图,并且GDI必须指定设备显示的颜色索引的地址。就像下表指出的,GDI提供两种主要的调色板效劳函数用来创立和删除调色板,以及一些与PALOBJ和*LATEOBJ有关的效劳函数用于在两个调色板之间转换颜色索引。函数描述EngCreatePalette创立一个调色板。驱动程序通过给DEVINFO构造里的调色板返回一个句柄使设备和调色板相联系。EngDeletePalette删除给定的调色板。PALOBJ_cGetColors允许驱动程序从从一个索引的调色板下载RBG颜色。它由显示驱动程序在DrvSetPalette函数中调用。*LATEOBJ_i*late从一个源颜色索引转换到目的颜色索引*LATEOBJ_piVector从一个索引的源调色板中检索转换向量。驱动程序能使用这个向量完成其自身从源索引到目的索引的转换。*LATEOBJ_cGetPalette在一个索引的源调色板中检索24位RGB颜色或颜色的位域格式驱动程序能使用这个函数从调色板获得信息执行颜色混合。这些函数更详细的内容,请参考在线DDK。2.3.3路径的GDI效劳为帮助矢量设备填充复杂的区域,驱动程序能调用创立、修改和计算路径的引擎函数;这些函数在下表列出。驱动程序通过PATHOBJ构造路径。GDI路径效劳函数描述EngCreatePath为驱动程序的临时使用分配一个路径。驱动程序在从当前的绘图调用返回GDI之前要删除这个路径。EngDeletePath删除通过EngCreatePath函数创立的路径。PATHOBJ_vGetBounds返回路径的一个混合矩形。PATHOBJ_vEnumStart通知PATHOBJ驱动程序将调用PATHOBJ_bEnum用指定的路径计算曲线。这个函数假设计算重新开场时必须要调用。PATHOBJ_bEnum从路径检索下一个PATHDATA记录。每个记录描述了一个子路径的全部或局部。PATHOBJ_vEnumStartClipLines允许驱动程序请求相对一个PATHOBJ要裁剪的直线。当裁剪区比一个矩形更复杂时是有用的。PATHOBJ_bEnumClipLines从路径计算已裁剪的直线段PATHOBJ_bMoveTo在一个已定义的PATHOBJ路径里改变现有的位置PATHOBJ_bPloyLineTo在一个已定义的PATHOBJ路径里绘制直线PATHOBJ_bPloyBezierTo在一个已定义的PATHOBJ路径里绘制贝塞尔曲线PATHOBJ_bCloseFigure通过正绘制的一条直线回至起始点关闭路径这些函数更详细的内容,请参考在线DDK。2.3.4GDI绘图效劳及其他为了支持CLIPOBJ,BRUSHOBJ,和*FORMOBJ构造,GDI提供几种绘图效劳〔在下页的表中列出〕此外GDI模拟在前面hooking对punting中描述。GDI绘图效劳函数描述EngCreateClip为驱动程序的临时使用分配一个CLIPOBJ。当不再需要它时驱动程序调用EngDeleteClip函数删除它。EngDeleteClip用EngCreateClip函数删除已分配的CLIPOBJEngBitBltDrvBitBlt函数的GDI模拟EngCopyBitsDrvCopyBits函数的GDI模拟EngStretchBltDrvStretchBlt函数的GDI模拟EngFillPathDrvFillPath函数的GDI模拟EngStrokeAndFillPathDrvStrokeAndFillPath函数的GDI模拟EngStrokePathDrvStrokePath函数的GDI模拟EngLineToDrvLineTot函数的GDI模拟BRUSHOBJ_pvAllocRbrush为实现驱动程序的画刷分配存储器。BRUSHOBJ_pvGetRbrush为实现驱动程序的画刷返回一个指针;如果还没有实现画刷就实现画刷。CLIPOBJ_cEnumStart在已裁剪的全部或局部区域里为矩形的计算设定参数。〔没有调用这个函数时能够计算一次这个区域,但是随后的计算需要使用这个函数。〕CLIPOBJ_bEnum从裁剪区域恢复大量矩形。CLIPOBJ_ppoGetPath作为路径用来恢复复杂的区域。这些函数更详细的内容,请参考在线DDK。2.3.5GDI字体和文本效劳GDI提供对字体管理和文本输出的支持。FONTOBJ构造和相关函数允许驱动程序一个字体的特定实例。为了支持文本输出,驱动程序STROBJ构造和相关函数。下表列出了FONTOBJ和STROBJ相关的函数。函数描述EngTE*tOutGDI模拟DrvTe*tOut函数FONTOBJ_cGetAllGlyphHandles允许驱动程序恢复GDI字体的每一个字形句柄。驱动程序使用这个效劳下载全部字体。FONTOBJ_vGetInfo返回描述已分配字体的信息。FONTOBJ_cGetGlyphs为字体使用者把字形句柄翻译成指针给已分配的字形数据。到下一次调用FONTOBJ_cGetGlyphs之前这些指针均有效。FONTOBJ_pQueryGlyphAttrs返回有关字体字形的信息。FONTOBJ_p*oGet*form为相关的字体恢复从抽象到设备的转换。这个转换要求驱动程序实现一个驱动程序提供的字体。FONTOBJ_pifi取得一个到描述相关字体的IFIMETRICS构造的指针。FONTOBJ_pvTrueTypeFontFile取得一个到与TrueType字体相关的ROM映射TrueType文件的指针。STROBJ_vEnumStart为指定的STROBJ构造重新计算GLYPHPOS数组。驱动程序要在随后的计算之前调用这个函数。STROBJ_bEnum在指定的STROBJ中计算字体轮廓一致性和位置。STROBJ_dwGetCodePage返回与指定的STROBJ相关的代码页。这些函数更详细的内容,请参考在线DDK。2.3.6GDI支持的效劳及其他GDI给驱动程序编写者提供了多种一般的支持效劳,包括装载、读取、操作数据文件的能力,以及分配内核模式和用户模式的存储器。2.4浮点数支持内核模式图形驱动程序在调用GDI提供的EngSaveFloatingPointState和EngRestoreFloatingPointState例程之间必须进展所有的浮点操作。如果硬件有一个浮点处理器,驱动程序能够直接做浮点操作。另外,驱动程序能使用GDI的FLOATOBJ效劳来计算浮点操作。不考虑处理器类型,当声明浮点值时,驱动程序要使用FLOAT数据类型。2.5数据类型下表中定义的数据类型在设备驱动程序接口里出现。这些数据类型中的几个在前面GDI用户对象里描述过。指针型数据类型用星号〔*〕标记。DDI数据类型变量前缀名定义BOOLb可以是TRUE或FALSE的32位值BYTEj8位无符号整数BRUSHOBJ*pbo指向画刷对象的指针CLIPLINEcl裁剪线对象CLIPOBJpco裁剪对象的指针DHPDEVdhpdev由设备驱动程序定义的32位句柄。它识别一个物理设备。DHSURFdhsurf由设备驱动程序定义的32位句柄。它识别一个设备管理外表。FI*fi*定点数FLOATLe浮点数FLOAT-LONGel32位溢出值,依据上下文解释成LONG或FLOATFLONGfl32位标志的设定FONTOBJ*pfo字体对象的指针FSHORTfs16位标志的设定HBMhbm由GDI定义能识别位图的32位句柄HPALhpal由GDI定义能识别调色板的32位句柄HSURFhsurf由GDI定义能识别外表的32位句柄LONGl32位有符号整数MI*mi*32位数量,它的低16位定义前景和背景的混合模式PALOBJ*ppalo调色板对象指针PATHOBJ*ppo路径对象指针POINTEpte由{FLOAT*,y;}组成的小数点构造POINTF*ptf*由{FI**,y;}组成的小数点构造POINTLptl由{LONG*,y;}组成的小数点构造PWSZpwsz以0完毕的Unicode字符串的指针PVOIDpv没有定义数据类型的VOID指针RECTLrcl由{LONG*Left,yTop,*Right,yBottom;}组成的矩形构造RECTF*rcf*由{FI**Left,yTop,*Right,yBottom;}组成的矩形构造ROP4rop4指定如何混合源、目标、图形以及屏蔽像素的32位值SHORTs16位有符号整数SIZELsizl由{ULONGC*,Cy;}组成的二维构造STROBJ*pstro文本字符串对象指针SURFOBJ*pso外表对象指针ULONGul32位无符号整数USHORTus16位无符号整数*FORMOBJ*p*o坐标转换对象指针*LATEOBJ*p*lo颜色转换对象指针下表中列出的参数前缀用于修改它们使用的变量名前缀。前缀参数用途i已计算的索引c计数p指针第3章支持DDI为响应通过图形设备接口〔GDI〕传送的设备无关应用调用,图形驱动程序必须确认其图形设备产生请求的输出。图形驱动程序通过实现必须的图形驱动程序接口〔DDI〕控制图形输出。DDI函数用Drv***的形式命名。GDI调用这些Drv***函数传递数据到驱动程序。当应用进展GDI请求并且DDI确定驱动程序支持相应的函数,GDI调用这个函数。驱动程序对提供函数是可靠的并且在函数的实现中返回到GDI。这一章描述显示器和打印机驱动程序编写者必须明白的DDI函数。DDI函数声明、构造定义和常量在winddi.h中可以找到。这个头文件和MicrosoftWindows2000DDK一起发布。每个DDI入口点函数、GDI效劳函数以及DDI构造和类型的详细信息参见在线DDK的GraphicsDriverReference。3.1图形驱动程序函数支持这一节描述驱动程序入口点函数,把它们归类为必需的、有条件必需的和可选的,后一节提供实现信息,对一般的图形驱动程序入口点从功能类别上组织。这个指南的第二和第三局部分别给出了显示器驱动程序和打印机驱动程序详细的设计信息。当设备驱动程序返回一个错误,一般调用GDI的EngSetLastError函数报告扩展的错误代码。应用程序可以取得这个错误代码。3.1.1必需的图形驱动程序函数所有的图形驱动程序必须支持GDI调用的入口点,启用或制止驱动程序、PDEV构造和外表与每个PDEV相关。下表以一般调用使用的顺序列出了需要的函数。入口点描述DrvEnableDriver作为初始化驱动程序入口点,这个函数把驱动程序版本号以及所支持的任意函数的入口点提供给GDI。DrvGetModes由指定的视频硬件设备列出所支持的模式。〔只有显示器驱动程序需要这个函数〕DrvEnablePDEV启用PDEV。DrvpletePDEV通知驱动程序设备安装已完成。DrvEnableSurface为指定的硬件设备创立一个外表。DrvDisableSurface通知驱动程序不再需要为当前设备已创立的外表。DrvDisablePDEV当不再需要硬件时,释放已创立但还没有删除、由设备和一些外表使用的存储器和资源。DrvDisableDriver为驱动程序释放所有已分配的资源并把它的初始化状态返回硬件。DrvAssertMode为指定的硬件设备重新设置视频模式。〔只有显示器驱动程序需要这个函数〕3.1.2有条件必需图形驱动程序函数除了经常请求的函数,还有其他一些函数可能请求,这依赖于驱动程序如何实现。条件请求函数在下表中列出。如果驱动程序管理其自身的主外表〔使用EngCreateDeviceSurface函数取得外表的句柄〕或者其自身的屏幕外位图,它也必须支持几个绘图函数。驱动程序向标准格式的DIB写时通常允许GDI管理大多数或全部的这些操作。支持可设置调色板的显示器必须也支持DrvSetPallete函数。对于打印机驱动程序定义或绘制字体比显示器更加普通。显示器驱动程序不要求处理字体。如果硬件有驻留的字体,驱动程序必须对GDI支持有关这个字体的信息。这个信息包括规格、从Unicode到个体字体轮廓识别、个体字体轮廓属性和字距调整表的映射。入口点请求描述DrvCopyBits设备管理外表源到目标的拷贝DrvDescribePi*elFormat在单一外表上具有不同像素格式、支持windows的显示器描述PDEV的像素格式DrvGetTrueTypeFileTrueType字体驱动程序使GDI映射存储器TrueType字体文件DrvLoadFontFile字体驱动程序为实现字体指定使用的文件DrvQueryFont打印机驱动程序为已给字体检索GDI构造DrvQueryFontCaps字体驱动程序询问驱动程序字体驱动程序的容量DrvQueryFontData打印机驱动程序检索有关已实现字体的信息DrvQueryFontFile字体驱动程序询问驱动程序字体文件信息DrvQueryFontTree打印机驱动程序查询子目录构造定义的字体映射的三种类型之一DrvQueryTrueTypeOutlineTrueType字体驱动程序返回TrueType字形句柄给GDIDrvQueryTrueTypeTableTrueType字体驱动程序使GDITrueType字体文件DrvResetPDEV在文档里允许模式改变的设备从旧PDEV到新PDEV传送驱动程序状态DrvSetPalette支持可设置调色板的显示器为指定设备实现调色板DrvSetPi*elFormat在单一外表上具有不同像素格式、支持windows的显示器设定窗口的像素格式DrvStrokePath设备管理外表在显示器上实现路径DrvSwapBuffers具有成对缓冲器、支持像素格式的驱动程序显示外表隐藏的缓冲器的目录DrvTe*tOut设备管理外表或定义字体的驱动程序在指定位置实现一组字符映像〔图示符〕DrvUnloadFontFile字体驱动程序通知驱动程序不需要字体文件3.1.3可选的图形驱动程序函数为了减小驱动程序的大小,驱动程序编写者通常只加进硬件支持最好的几个可选的函数。例如,支持图象颜色管理〔ICM〕的硬件驱动程序能实现DrvIcm***函数。下表列出了图形驱动程序能选择实现的函数。显示器和打印机驱动程序函数入口点描述DrvAlphaBlend提供具有混合能力的位块传送。DrvBitBlt执行一般的从和向外表的位块传送DrvCreateDeviceBitmap用驱动程序定义的格式创立和管理位图。DrvDeleteDeviceBitmap删除设备管理位图DrvDitherColor请求设备创立一个相对设备调色板抖动的画刷。DrvFillPath为设备管理的外表绘制一个闭合的路径。DrvGradientFill屏蔽已指定的原语DrvIcmCheckBitmapBits检查在指定位图里的像素是否位于指定转换的设备范围内DrvIcmCreateColorTransform创立ICM颜色的变换DrvIcmDeleteColorTransform删除已指定的ICM颜色的变换DrvIcmSetDeviceGammaRamp设置指定的显示器设备的硬件斜面DrvLineTo绘制单一的实心装饰线。DrvPlgBlt在设备管理和GDI管理外表的结合之间提供旋转的位块传送能力。DrvRealizeBrush为已定义的外表实现指定的画刷DrvStretchBlt在设备管理和GDI管理外表之间允许加长的位块传送。DrvStretchBltROP使用ROP实现加长的位块传送。DrvStrokeAndFillPath同时填充和识别路径。DrvSynchronize在GDI和显示器驱动程序支持的协处理器设备之间协调绘图操作;这仅针对引擎管理外表。DrvSynchronizeSurface在GDI和显示器驱动程序支持的协处理器设备之间协调绘图操作;这仅针对引擎管理外表。如果驱动程序提供DrvSynchronize和DrvSynchronizeSurface,GDI将仅能调用DrvSynchronizeSurface.DrvTransparentBlt提供透明的位块传送能力。仅由显示器驱动程序使用的函数入口点描述DrvMovePointer把指针移动至新位置并刷新它。DrvSaveScreenBits存储或恢复屏幕上指定的矩形。〔仅针对显示器驱动程序〕DrvSetPointerShape如果驱动程序已完成绘图,从屏幕上删除指针,然后设置一个新的指针形式。主要由打印机驱动程序使用的函数入口点描述DrvDestroyFont通知驱动程序不再需要认识字体;驱动程序释放已分配的数据构造。DrvDrawEscape完成绘图类型退出的函数。DrvEscape在独立设备DDI里从无效设备查询信息。DrvFree释放同指示数据构造相关联的字体存储器。仅由打印机驱动程序使用的函数入口点描述DrvEndDoc发送文档完毕的信息。DrvFontManagement允许不能直接通过GDI可用的打印机功能。DrvGetGlyphMode返回作为特殊字体存储的字体类型信息。DrvNe*tBand了解外表刚刚绘图的区域的内容。DrvQueryPerBandInfo为指定相关的打印机外表返回相关信息。DrvSendPage发送从外表至打印机的写后读位。DrvStartBanding为驱动程序准备分区。DrvStartDoc发送文档开场控制的信息。DrvStartPage发送页首控制的信息。字体驱动程序函数入口点描述DrvQueryAdvanceWidths为指定的一组字形提供增加宽度的字符。3.2支持初始化和终止函数图形驱动程序能支持多个设备和每个设备的多个并发使用。因此,初始化和终止发生在3个不同的层次,每个层次都有其自己的定时。初始化以以下顺序发生:驱动程序初始化PDEV初始化外表初始化终止以相反的顺序发生。3.2.1驱动程序初始化和去除当设备驱动程序要实现几个或多个函数,它只向GDI输出DrvEnableDriver。驱动程序通过一个函数表输出其他的支持的函数。GDI向设备驱动程序调用的第一个函数是DrvEnableDriver。在这个函数中,驱动程序在传递进的DRVENABLEDATA构造内填充,这样GDI能确定支持其他的哪个Drv***函数以及它们的位置在哪里。在DRVENABLEDATA构造中驱动程序提供以下信息:GDI的DDI版本号。这个常量在winddi.h中定义为DDI_DRIVER_VERSION。一个指向DRVFN构造的数组的指针,这个构造列出了支持的函数和它们的索引。在数组中DRVFN构造的成员。为了使GDI调用一个函数和驱动程序的启用和制止函数不同,驱动程序必须使函数名和位置对GDI可用。虽然DrvEnableDriver也能完成一次初始化,如信号的分配,驱动程序在DrvEnableDriver期间不能实际启用硬件。硬件初始化要在驱动程序的DrvEnablePDEV函数中发生。同样地,驱动程序在DrvEnableSurface函数中使外表有效。GDI调用DrvDisableDriver函数通知驱动程序它将要卸载。为响应这个调用,驱动程序要释放在这一点它分配的所有资源和存储器。如果硬件需要重新设置,GDI调用驱动程序的DrvAssertMode函数。3.2.2PDEV初始化和去除每个核心模式图形驱动程序表示一个GDI管理的逻辑设备。反过来,一个驱动程序能管理一个或多个PDEV构造。PDEV是物理设备的逻辑表现。它由硬件的类型、逻辑地址和能支持的外表来描述:硬件的类型─驱动程序支持由硬件的类型描述的PDEV的一个例子是支持假设的LaserWhiz、LaserWhizⅡ和LaserWhiz超级打印机。由GDI传递的设备名指定在驱动程序支持的全部设备集中哪一个设备被请求。逻辑地址—例如,一个驱动程序能支持连在LPT1、2和名为\\SERVER1\PSLASER的效劳器上的多个打印机。另外,一个能同时支持超过一个VGA显示器的显示器驱动程序可能通过端口号进展区分,如0*3CE,0*2CE,等等。打印机和其他硬拷贝输出设备的逻辑地址由GDI决定;EngWritePrinter函数向相应的目标直接输出。显示器既可以隐含地确定其逻辑地址,也可以从DEVMODEW的私有局部取到地址。DEVMODEW构造给驱动程序提供了请求的环境设置,如设备名和指定打印机或显示器驱动程序的其他信息。外表—每个PDEV请求一个唯一的外表。例如,如果一个打印机驱动程序同时有两个打印作业在工作,每个作业请求不同的页面格式,如风景和肖像格式,每个打印作业请求不同的PDEV。类似地,显示器驱动程序可能在同一显示器上支持两个桌面,每个桌面请求不同的PDEV和外表。对每个外表请求,有一个对DrvEnablePDEV函数的调用为外表创立一个不同的PDEV。为响应对DrvEnablePDEV的调用,驱动程序通过几个构造返回有关硬件设备能力的信息。在GDI调用DrvEnablePDEV之前,GDIINFO构造填充着0。驱动程序在GDIINFO中填充以下信息与GDI通信:驱动程序版本号根本的设备技术〔光栅和矢量〕可打印页的大小和分辨率彩色调色板和灰度比例信息字体和文本性能过渡调色支持样式步号驱动程序只填充它支持的域而忽略其余局部。驱动程序用标志在GDIINFO构造中填充,描述这个PDEV的图形性能。在几乎所有的情况下,GDIINFO的信息告诉GDI驱动程序能提供的图形支持的级别。例如,如果需要绘制一个三角记号,GDIINFO中的信息告诉GDI是否驱动程序能处理贝塞尔曲线或者是否GDI必须发送多条直线线段。驱动程序要填充它支持的所有域,而不涉及其他的域。驱动程序必须提供的另一条重要的信息是一个指针〔phsurfPatterns〕,指向用外表的句柄填充的缓冲区,表示标准的填充模式。除了标准的填充模式以外,phsurfPatterns能包括空〔null〕,这将导致GDI根据设备分辨率和像素大小自动创立模式外表。当GDI被调用,用标准模式实现一个画刷,它调用DrvRealizeBrush函数实现为请求的模式定义的画刷。GDI为支持设备的核心驱动程序传递给DrvEnablePDEV一个句柄,hDriver。对于一个打印机驱动程序,hDriver提供句柄给打印机并在假脱机的调用中使用,如EngWritePrinter。无论何时GDI调用DrvEnablePDEV,驱动程序必须分配存储器,用以支持创立的PDEV,即使调用DrvEnablePDEV用来为不同的模式创立其他的PDEV。〔一个驱动程序可能有几个激活的PDEV,虽然在一个时刻只有一个能被启用。〕然而,直到GDI调用DrvEnableSurface,不支持一个实际的外表。如果设备外表请求位图的分配,直到外表启用为止分配是不必要的〔通常在DrvEnableSurface函数中〕。虽然在实际写到设备之前应用常请求设备信息,等待分配一个大的位图能保存有价值的资源,并在系统初始化时改良驱动程序的性能。PDEV的初始化完成时,GDI调用DrvpletePDEV函数通知驱动程序物理设备的安装已经完成。这个函数也给驱动程序提供到PDEV的GDI的逻辑句柄,驱动程序在调用GDI函数中使用。对驱动程序的DrvDisablePDEV函数的调用指示给定的物理设备不再需要。在这个函数中,驱动程序要释放物理设备使用的所有存储器和资源。3.2.3启用和制止外表在初始化阶段的最后,GDI调用DrvEnableSurface使驱动程序为一个存在的PDEV启用一个外表。DrvEnableSurface必须通过调用相应的GDI效劳指定外表的类型来创立它。就像第2章GDI对外表的支持中描述的,以及依据设备和环境,驱动程序能从DrvEnableSurface中调用适宜的GDI效劳创立外表:对设备管理的外表,驱动程序调用EngCreateDeviceSurface函数得到外表的句柄。为创立一个GDI能完全管理的标准格式〔DIB〕位图,包括所有绘图操作的性能,驱动程序要调用EnfCreateBitmap函数。驱动程序能钩住它能优化的所有的绘图操作。驱动程序也能使GDI为每个像素分配空间或为自身提供空间,虽然后一个选项通常只由打印机或帧缓冲区使用。DrvEnableSurface返回一个有效的外表句柄作为返回值。随着外表的创立,驱动程序必须通过调用GDI的EngAssociateSurface效劳使外表与一个PDEV相关。这个调用也告诉GDI驱动程序为外表挂上了哪个绘图函数。GDI调用DrvDisableSurface函数通知驱动程序不再请求由DrvEnableSurface为PDEV创立的当前的外表。驱动程序必须释放在执行DrvEnableSurface期间分配的所有的存储器和资源。如果PDEV有一个启用的外表,DrvDisableSurface总是在DrvDisablePDEV之前调用。外表一旦创立,当它不再使用时必须删除。不能正确匹配外表创立的删除将导致无用对象的累积并使系统性能下降。3.3创立设备相关位图当应用请求位图的创立,驱动程序通过支持DrvCreateDeviceBitmap函数能创立和管理DDB。当这样一个驱动程序创立了位图,它能用任何格式存储位图。驱动程序检查传递的参数,并用至少是请求的每个像素的位数提供位图。注意图形驱动程序通过在屏幕外的存储器支持位图和使用硬件绘制位图能提高性能。这方面的一个例子是Permedia显示器驱动程序的例子。在DrvCreateDeviceBitmap中,驱动程序调用GDI的EngCreateDeviceBitmap效劳使GDI为设备位图创立一个句柄。如果驱动程序支持DrvCreateDeviceBitmap,它创立一个DDB,定义其格式,并返回一个它的句柄。驱动程序控制位图用什么格式在哪里存储。驱动程序要支持最接近匹配其设备外表的颜色格式。位图的内容在创立之后不能定义。如果驱动程序返回NULL,它不能创立和管理位图;而由GDI替代执行这些任务。如果驱动程序创立了位图,也必须能通过执行DrvDeleteDeviceBitmap函数删除它。3.4支持图形输出驱动程序处理的特殊图形操作依赖于绘图外表和硬件的能力。如果外表是一个标准格式的DIB,GDI处理所有驱动程序不支持的绘图操作。驱动程序能hook任意的绘图函数并实现它们,得到硬件支持的优势。对于设备管理的外表,驱动程序最少必须支持图形输出函数DrvCopyBits、DrvTe*tOut和DrvStrokePath。它也能可选支持任何其他的图形输出函数,例如支持DrvBitBlt,能提高性能。有些函数要求确定的能力级别,而其他的允许设备通过在DEVINFO构造中设置相应的GCAPS标志指示其性能。对驱动程序的所有的绘图调用都是单线程的,而不关心外表的类型。下面的局部描述驱动程序如何实现以下操作:绘制直线和曲线绘制和填充路径拷贝位图过渡调色技术图象颜色管理3.4.1绘制直线和曲线包括在图象输出中的直线和曲线类型是几何直线、装饰直线和贝塞尔曲线。对于直线和曲线输出,驱动程序能支持DrvStrokePath、DrvFillPath和DrvStrokeAndFillPath函数。如果外表是设备管理的,驱动程序必须支持DrvStrokePath绘制直线;驱动程序不要求支持曲线。当GDI用任意的属性集绘制直线或曲线,GDI调用DrvStrokePath。至少,DrvStrokePath函数必须支持用实色画刷和任意的裁剪绘制实线和样式装饰线。为实现这一点,GDI的PATHOBJ_***和CLIPOBJ_***效劳函数通过预先计算的裁剪把这些直线分割成一个像素宽的线段的集合。DrvStrokePath提供一个指针,plineattrs,指向定义不同直线属性的LINEATTRS构造。当路径或裁剪对于驱动程序在设备上的过程过于复杂,驱动程序能通过调用EngStrokePath函数把回调函数punt到GDI。对这种情况,GDI能把对DrvStrokePath的调用分割成用预先计算的裁剪得到的一个像素宽的线段的集合。通过调用GDI的CLIPOBJ_***效劳,驱动程序能使GDI计算在路径中的所有的直线,并执行所有的直线裁剪计算。另外,驱动程序可以使用PATHOBJ_***、CLIPOBJ_***或*FORMOBJ_***效劳简化图形操作。例如,驱动程序能使用CLIPOBJ_cEnumStart和CLIPOBJ_cEnum计算在一个裁剪区域内的矩形,发送这个区域到打印机,以及裁剪它。驱动程序也能使用PATHOBJ_cEnumStart和PATHOBJ_cEnum计算路径中的直线或曲线。然后它能把路径发送到设备并绘制它。装饰线装饰线通常是一个像素宽并使用实色画刷绘制。它按照网格穿插点量化〔GIQ〕菱形约定绘制,这种方法确定装饰线上哪个像素要被绘制。图3.1显示了一条直线置于一个矩形网格上,像素定位在网格穿插点上。为确定哪个像素将被点亮,想象一个菱形在直线中间并沿直线滑动。菱形的宽度和高度恰好等于两个相邻像素中心的距离。当菱形沿着直线移动,中心完全被菱形覆盖的像素被选中。如果直线穿过的一个点在两个相邻像素的中间,被点亮的像素取决直线的斜度和相邻像素的走向:水平的或是垂直的。下表概括了这些情况。直线的斜率〔绝对值〕相邻像素的走向结果斜率<1或斜率>1水平的点亮菱形左顶点的像素斜率<1或斜率>1垂直的点亮菱形上顶点的像素斜率=1水平的点亮菱形上顶点的像素斜率=1垂直的点亮菱形右顶点的像素菱形协议使斜率在-1和1之间的直线上每一列有一个像素点亮,使斜率的绝对值比1大的直线上每一行里有一个像素点亮。用这种方式,装饰线能没有间隙地绘制。装饰线的首尾像素也由菱形协议确定。装饰线是首像素包含而末像素不包含的;即如果直线起始于菱形内的一个像素,这个像素变亮。类似地,如果直线完毕于菱形内的一个像素,这个像素不变亮,如图3.1显示。图3.1装饰线的菱形协议为了着色装饰线,DrvStrokePath函数遵循GIQ菱形协议。DrvLineTo函数是一个可选入口点,驱动程序能够为应用调用Microsoft®Win32LineTo函数提供优化。DrvLineTo比DrvStrokePath简单,因为它仅支持整数端点和实心装饰线。对于支持R2_NOT混合模式的光栅设备,二进制光栅操作改变目标颜色为相反色,驱动程序必须使用准确的着色。对于要求GDI和驱动程序两者绘图的设备,着色也必须是准确的。这包括GDI在一些位图上绘图的设备以及驱动程序在其他外表上绘图的设备〔除非像素太小不能产生可视的差异〕。这也包括请求GDI处理复杂裁剪的设备。几何宽度直线〔GeometricWideLine〕几何直线的形状是由宽度、连接类型、画刷端点类型以及在*FORMOBJ构造里当前区域至设备转换来确定的。能够使用实心的或非实心的画刷绘制直线。更高级的硬件设备驱动程序可以支持DrvStrokePath函数中的几何宽度直线。在调用DrvEnablePDEV返回的DEVINFO构造里测试GCAPS_GEOMETRICWIDE性能标志位,GDI确定驱动程序是否能够绘制包括几何直线的路径。如果驱动程序没有这个能力,或者因为路径或裁剪对设备过于复杂,而使函数处理此操作失败,GDI自动转换调用较简单的DrvFillPath函数。几何宽度直线对显示器驱动程序图形函数有特殊的含义。包含设备坐标的路径使用当前转换的逆转换变成世界坐标。具有指定宽度的几何构造获得加宽的路径,考虑连接和端点。这个路径又转换成设备坐标并用指定的画刷填充。几何宽度直线的线型是由浮点数数组确定的。数组是定长的,但好象能无限重复使用。在世界坐标里,第一个数组条目指定第一个短线的长度;下一个条目指定第一个间隙的长度。在这以后,短线和间隙的长度交替。例如,线型数组3.0,1.0,1.0,1.0可绘制长短线交替的直线。当驱动程序沿着加宽前的路径移动,可以考虑线型,"擦除〞路径对应于间隙的局部。这将路径分割成许多子路径。然后分割开的路径被加宽,就像它没有线型,照常应用端点盖住和连接。线型数组可以是不定长的。例如,线型数组{1,0}使驱动程序用交替的短线绘制一条直线。线型状态〔定义当前的距离到线型数组〕在路径中第一个子路径的开头提供。在每个后来的子路径的开场考虑重置为0.0,这在任何Win32MoveToE*操作后出现。花式装饰直线〔StyledCosmeticLine〕DrvStrokePath函数必须支持用实色画刷绘制的带任意裁剪的装饰线。驱动程序能够进展一个到GDI的PATHOBJ_vEnumStartClipLines的调用来预先计算裁剪。装饰线的线型类似于几何宽度直线,因为它由一个重复的数组指定。对于一条造型的装饰线,数组条目是LONG类型的值,包含类型步的长度。类型步和像素的关系由DrvEnablePDEV函数返回的GDIINFO构造的*StyleStep、yStyleStep和DenStyleStep字段定义。当驱动程序通过复杂的裁剪调用PATHOBJ_vEnumStartClipLines处理装饰线,GDI修改CLIPLINE构造的iStyleState成员来表示线型状态。线型状态是回到线段的第一个像素的偏移,即如果直线没有被裁剪,将绘制第一个像素。线型状态由压缩到一个ULONG值中的两个16位值组成。如果HIGH和LOW是线型状态的高序〔high-order〕和低序〔low-order〕的16位值,线型状态的分数版,称作线型位置,可计算为:styleposition=HIGH+LOW/denStyleStep例如,如果在iStyleState中的值是1和2,denStyleStep是3,styleposition是5/3。为准确确定在线型数组中线型从哪里开场绘制,计算乘积:styleposition*denStyleStep在这个例子中,denStyleStep的值是3,绘图位置计算不包括线型数组的前5个像素〔5/3*3〕。即这条裁剪线从线型数组中的第6个像素开场绘制。有y线型的装饰线和*线型的装饰线。如果一条线在*方向扩展d*个设备单元,在y方向扩展dy个设备单元,当以下条件为真直线是y型的:(dy*yStyleStep)≥(d***StyleStep)在这种情况下,对每个像素在y方向的前进,线型位置的前进由yStyleStep/denStyleStep计算。反过来,直线是*线型的,当下式为真时,对每个像素在*方向的前进,线型位置的前进由*StyleStep/denStyleStep计算:(d**yStyleStep)>(dy**StyleStep)当线型位置前进到一个新的整数时,在线型数组中线型步前进一个单元。图3.2显示不同斜率的几条装饰线。像素网格显示不是方的;它就像在EGA显示器中显示的那样,在*方向的4个像素与y方向的3个像素表示一样的距离。在这个图示中,线型数组〔由LINEATTRS构造的pstyle成员定义〕是{1,1},它把直线分割成相等大小的点和间隙。驱动程序的*StyleStep的值是3,yStyleStep的值是4,denStyleStep是12。为进一步说明,假设一个点阵打印机有144dpi的水平分辨率和72dpi的垂直分辨率。另外,假设最小点的长度是1/24英寸。为支持这个打印机,要选择能补偿打印机的方式比的最小的*StyleStep和yStyleStep值,如*StyleStep为1,yStyleStep为2〔144/72〕,denStyleStep为6〔144/24〕。图3.2花式装饰线的例子如果LINEATTRS构造里标志的LA_ALTERNATE位置1,装饰线使用了指定的线型。在这种情况下,其他每个像素都选中,而不管方向或方式比。线型状态返回,好似线型数组是{1,1},*StyleStep、yStyleStep和denStyleStep都是一个。换句话说,如果IstyleState是0,第一个像素点亮;IstyleState是1,第一个像素不亮。如果LINEATTRS构造里标志的LA_STAARTGAP位置1,在线型数组里元素的检测是相反的。第一个数组条目指定第一个间隙的长度,第二个条目指定第一个短线的长度,如此下去。贝塞尔曲线一些高级硬件设备能够绘制包含贝塞尔曲线的路径,是一般作用的曲线图元。如果这样,在DrvStrokePath函数中驱动程序包含对这些曲线的支持。当GDI必须在设备管理的外表绘制贝塞尔曲线路径,它测试GCAPS_BEZIERS标志〔在DEVINFO构造中〕确定是否调用DrvStrokePath。如果调用,这个函数执行执行请求操作或决定不处理它,就像在几何宽度直线中做的那样。在后一种情况中,

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论