驱动开发之六 --- 一个简单的显示驱动之六 【译文】

驱动开发之六 --- 一个简单的显示驱动之六 【译文】

先后顺序

现在,让我们清楚地回顾下的这个步骤:

  • DrvEnableDriver:加载驱动
  • DrvGetModes:获取缓冲尺寸,来存放所有支持的显示模式。
  • DrvGetModes: 得到显示模式
  • DrvEnablePDEV: 通知显示驱动在DEVMODE数据结构中初始化一个选中的模式,并且返回一个实例句柄。
  • DrvCompletePDEV: 通知驱动,设备初始化已经完成。  
  • DrvEnableSurface:得到驱动来提供一个绘画表面。
  • DrvDisableSurface: 删除绘画表面
  • DrvDisablePDEV: 删除实例结构
  • DrvDisableDriver: 卸载显示驱动

怎样进行绘制?

像"BitBlt"这样的“GDI调用”在你的显示驱动中实际上使用DrvBitBlt。你可能注意到,我们的驱动自身没有实现任何绘画命令。这是因为我们没有硬件来加速绘画特性,所以我决定只是调用WINDOWS提供的,已经在软件中实现的例程。示例中,DrvBitBlt简单的转向EngBitBlt。这些将直接渲染到我们的视频缓冲,这里的视频缓冲,我们使用的是内存映像文件。

你可能对“我怎样从Drv*的调用中得到我的PDEV或者我的表面对象”产生疑惑。好的,传递给这些API的SURFOBJ包含了一个指向表面对象的指针。Dhsurf成员是一个设备创建的提供给SURFOBJ的句柄,用来代表一个设备管理的表面。这个可以通过检查设置于SURFOBJ 上的STYPE_DEVICE标志位来决定。

显示驱动escape codes

前面的设备驱动中,我们知道了使用"DeviceIoControl"可以实现从用户模式应用与驱动程序之间的通讯。对于显示驱动,这也是可以的。然而这里有一点不同,他们不再被叫作"IOCTLs",他们被称作"Escape Codes"

在用户模式下,你可以使用两种方法中的一种发送"Escape Codes"到显示驱动。第一种是ExtEscape,它可以简单的发送你提供的数据给驱动。你的显示驱动随后将在DrvEscape例程中处理它。

第二种办法是DrawEscape,它可以在你驱动的DrvDrawEscape中处理。不同的是,DrawEscape允许你提供一个包含你的数据的窗口DC和这个窗口的裁剪区域,提供给你的驱动。这允许你简单的实现扩展的绘画命令。你的驱动将通知正确的裁剪区域使这些命令在windows环境中运转正常。

OpenGL支持

在Windows中,通过使用一个可安装用户驱动包(ICD:Installable Client Driver)来实现OpenGL支持,这个概念最初由SGI提出,通过让制造商完全地实现图形管道来提高OpenGL的性能。当OpenGL32.DLL被加载时,它会向视频驱动询问它的ICD,如果有,就会被加载到进程空间,OpenGL的API就是由ICD提供。ICD完全控制着图形管道,因而每个制造商和驱动版本都有不同的实现。

通常的做法是缓冲OpenGL命令,然后使用ExtEscape这个api将他们从缓冲刷新到图形加速卡。ICD包现在是由微软维护的,如果你想为它开发,但它不是免费的。

另有一种支持OpenGL办法是通过小型用户驱动包(MCD:Mini Client Driver)实现的。这是微软最早为提供OpenGL 支持而使用的办法,类似于ICD,但是MCD位于内核中。据我所知这种办法非常慢,没有被任何的驱动制造商使用。

DirectX支持

在XPDM下, GDI驱动通过DrvEnableDirectDraw接口提供了DirectDraw的支持。由微软公司提供的系统元件实现了DirectX图形管道的用户模式部分和一些内核部分。这些API简单的返回一系列回调接口,内核中的DirectDraw层将用来在硬件中执行特殊的动作。

Direct3D通过DrvGetDirectDrawInfo来完成初始化,在DrvGetDirectDrawInfo 中GDI驱动要求支持Direct3D。提供的回调将被调用几次来得到恰当的进入驱动的接口,这些接口实现了Direct3D不同的特征。这些在MSDN中作了描写。

什么是镜像驱动?

镜像驱动并不像字面意思那样,你可以加载一个视频驱动,这个视频驱动镜像另一个显示驱动。他们会收到同他们镜像的显示驱动一样的调用。镜像驱动不支持DrvGetModes,然而如果你实现它,返回的显示模式将会被缓存,你不能动态的改变这些模式。尽管我听说在模式切换上,实现DrvGetModes能帮助加载和卸载显示驱动,但是我没有能得到证实。

为了加载镜像驱动,这个设备的注册表键需要设置"Attach.ToDesktop"的值为1。然后你可以在镜像驱动上使用参数"CDS_UPDATEREGISTRY"调用ChangeDisplaySettingsEx。然后设置你希望切换的显示模式,再在镜像驱动上调用一次ChangeDisplaySettingsEx。

镜像驱动在模式切换时不会完全地卸载。通常如果有绘制表面的引用,驱动将不会卸载。所以,从我的经验来看,得到镜像驱动,为了模式切换,你需要一个应用程序来检测WM_DISPLAYCHANGE消息。你也可以在加载显示驱动后,设置"Attach.ToDesktop“为0。这将有助于你卸载显示驱动,对于WM_DISPLAYCHANGE,你可以仔细检查这个卸载镜像驱动的过程。

如果你希望立即卸载镜像驱动,而不需要显示驱动改变,你需要遵循同加载一样的步骤。设置"Attach.ToDesktop"为0,然后执行"CDS_UPDATEREGISTRY"。然后不带参数再调用"ChangeDisplaySettingsEx"一次来强制卸载。尽管这看上去像是再运行一遍,所有的事情都通过引用显示表面完成。所以如果有对于显示表面显著的引用,驱动将不会被卸载。DDK中镜像驱动的例子没有全部实现这些,有一些缺少部分,正如在加载镜像驱动后,没有实现WM_DISPLAYCHANGE,也没有重新设置"Attach.ToDesktop"为0。

例子

本篇示例驱动在应用程序和显示驱动之间简单共享了一个内存映像文件。显示驱动写图形命令给内存映像文件,应用程序作为监视器执行,每秒钟大约刷新自己70次。尽管这不是是非常有效,但这仅仅是一个例子。显示驱动象一个常规硬件驱动一样的安装,看上去类似于ATI或者NVIDIA驱动。

为了安装这个示例,你需要使用控制面板中的"Add New Hardware" 。你必须选择"Hardware is already installed"和"Manually select hardware from a list"。下面的图片显示了设备列表,你需要滚动到最后,选择"Add a new hardware device"

驱动开发之六 --- 一个简单的显示驱动之六 【译文】_第1张图片

然后,你选择"Have Disk"找这个工程提供的.INF文件。然后,向下滚动到新的列表,找出如下图所示的"Toby Opferman Sample Video Display"

驱动开发之六 --- 一个简单的显示驱动之六 【译文】_第2张图片

除非你不想安装这个驱动,不然你会看到下面的对话框,你选择"Continue Anyway"来安装。下一步要做的就是使用显示设置和第三个选项卡激活第二个监视器。运行本篇提供的镜像程序,你会在应用窗口中看到第二个监视器。

驱动开发之六 --- 一个简单的显示驱动之六 【译文】_第3张图片

结论:

本篇展示了如何创建一个简单的显示驱动来处理GDI命令。本篇提及的显示驱动体系结构仅仅适用于XPDM,不适用于windows vista中新的LDDM.

你可能感兴趣的:(驱动开发学习)