DXGKDDI_PRESENT回调函数 (d3dkmddi.h)

DxgkDdiPresent 函数将内容从源分配复制到主图面 (,有时复制到屏幕外系统内存分配) 。

语法

DXGKDDI_PRESENT DxgkddiPresent;

NTSTATUS DxgkddiPresent(
  [in]     IN_CONST_HANDLE hContext,
  [in/out] INOUT_PDXGKARG_PRESENT pPresent
)
{...}

参数

[in] hContext

复制信息的设备上下文的句柄。 显示微型端口驱动程序的 DxgkDdiCreateContext 函数以前在 dxgkDdiCreateContextpCreateContext 参数指向的 DXGKARG_CREATECONTEXT 结构的 hContext 成员中返回此句柄。

如果驱动程序不支持创建上下文,Microsoft DirectX 图形内核子系统会将上下文的句柄替换为设备的句柄。 显示微型端口驱动程序的 DxgkDdiCreateDevice 函数之前返回了 dxgkDdiCreateDevicepCreateDevice 参数指向的 DXGKARG_CREATEDEVICE 结构 hDevice 成员中的设备句柄。

[in/out] pPresent

指向包含复制操作相关信息 的DXGKARG_PRESENT 结构的指针。

返回值

DxgkDdiPresent 返回以下值之一:

返回代码 说明
STATUS_SUCCESS DxgkDdiPresent 已成功复制内容。
STATUS_NO_MEMORY 或 STATUS_INSUFFICIENT_RESOURCES DxgkDdiPresent 无法分配完成该操作所需的内存。
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER DMA) 缓冲区 (当前直接内存访问已耗尽。
STATUS_GRAPHICS_CANNOTCOLORCONVERT 显示微型端口驱动程序检测到设备无法执行的颜色转换的位块传输 (bitblt) 。 Microsoft Direct3D 运行时阻止应用程序继续,并且应用程序收到复制内容失败。
STATUS_PRIVILEGED_INSTRUCTION DxgkDdiPresent 检测到非特权指令 (,即访问超出当前中央处理单元 [CPU] 进程) 特权的内存的指令。
STATUS_ILLEGAL_INSTRUCTION DxgkDdiPresent 检测到图形硬件不支持的指令。
STATUS_INVALID_HANDLE DxgkDdiPresent 在命令缓冲区中检测到无效句柄。
STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE 显示微型端口驱动程序在 DMA 流中检测到错误。 如果驱动程序返回此错误代码,则图形上下文设备将处于丢失状态。

注解

DirectX 图形内核子系统调用显示微型端口驱动程序的 DxgkDdiPresent 函数,以将内容从源分配通常复制到主图面。 (此函数还可以将内容复制到屏幕外系统内存分配。) 由于主图面定义松散,因此可以在以下方案中实现 DxgkDdiPresent

  • 根据窗口的位置, DxgkDdiPresent 函数必须跨位于同一适配器或不同适配器上的不同主副本执行。
  • 主数据库位于远程监视器上,可通过终端服务客户端或 Microsoft NetMeeting 进行访问。
  • 最近发生了模式切换,主要格式与源格式不同,因此需要颜色转换。 此外,由于窗口剪辑和排序, 可以剪切 DxgkDdiPresent 操作。
由于上述方案可以异步更改,因此用户模式显示驱动程序无法提前为显示微型端口驱动程序的 DxgkDdiPresent 函数编译硬件说明。 显示微型端口驱动程序必须为实际的 DxgkDdiPresent 操作创建硬件命令,并且它们必须放置在输出 DMA 缓冲区中。 调用显示微型端口驱动程序的 DxgkDdiPresent 函数以生成 DMA 缓冲区后,操作系统保证在呈现该缓冲区之前不会发生方案更改。

只要驱动程序支持以下抽象,显示微型端口驱动程序就不需要了解上述方案的详细信息:

  • 在从视频内存源复制到主视频或系统内存目标的复制操作中,从屏幕外系统内存源复制到主目标、从主源复制和复制到主目标,或者从主源复制到屏幕外系统内存目标,源由 pPresentDXGKARG_PRESENT 结构的pAllocationList[DXGK_PRESENT_SOURCE_INDEX] 数组元素的 hDeviceSpecificAllocation 成员指定DxgkDdiPresent 指向 的参数。 目标是设备的当前主节点或屏幕外系统内存分配,由 DXGKARG_PRESENT 的 pAllocationList[DXGK_PRESENT_DESTINATION_INDEX] 数组元素的 hDeviceSpecificAllocation 成员指定。 如果目标等于源 (即 destination == source) ,则复制操作是屏幕到屏幕位块传输 (bitblt) 。 因此,图形子系统将源和目标设置为以下值:
    • destination != NULL (,即 destination == nonNULL)
    • source != NULL (即 source == nonNULL)
  • 在视频内存从当前分配翻转到另一个分配时,源可由操作系统指定,并在 DXGKARG_PRESENT 的 pAllocationList[DXGK_PRESENT_SOURCE_INDEX] 数组元素的 hDeviceSpecificAllocation 成员中设置。 图形子系统将源和目标设置为以下值:
    • destination == NULL
    • source != NULL (即 source == nonNULL)
    注意 可以从与当前扫描的分配相同的源分配执行无操作翻转。 无操作翻转用于在呈现流中插入排队等待垂直空白。 显示微型端口驱动程序应插入硬件翻转命令,就像它正在翻转到另一个分配一样。
     
  • 在主图面的颜色填充操作中,不需要源分配,目标为由DXGKARG_PRESENT的 pAllocationList[DXGK_PRESENT_DESTINATION_INDEX] 数组元素的 hDeviceSpecificAllocation 成员指定的主分配句柄。 DXGKARG_PRESENT 的 Color 成员通常采用D3DDDIFORMAT枚举类型的 D3DDDIFMT_A8R8G8B8 格式。 但是,当主要格式为淡化 RGB 时, Color 包含调色板索引。 因此,图形子系统将源和目标设置为以下值:
    • destination != NULL (,即 destination == nonNULL)
    • source == NULL
若要使所有 DxgkDdiPresent 方案正常运行,显示微型端口驱动程序的 DxgkDdiCreateDevice 函数应将 DXGK_DEVICEINFO 结构的 DmaBufferSize 成员设置为足够大,以容纳向显示器或屏幕外目标呈现至少一个 RECT 矩形所需的硬件命令。 但是,如果 DxgkDdiPresent 方案中的子实体数耗尽当前 DMA 缓冲区,并且驱动程序需要另一个 DMA 缓冲区才能继续,则驱动程序的 DxgkDdiPresent 函数可以返回STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER。

然后,图形子系统获取新的 DMA 缓冲区,并使用与以前的 DxgkDdiPresent 调用相同的 RECT 结构列表再次调用驱动程序的 DxgkDdiPresent 函数。 驱动程序必须使用 pPresent 指向的 DXGKARG_PRESENT 结构的 MultipassOffset 成员来记录在对 DxgkDdiPresent 的上一次调用中完成 RECT 列表的进度,以便驱动程序可以从它使用新的 DMA 缓冲区停止的位置继续运行。 当驱动程序的 DxgkDdiPresent 函数完成 RECT 结构列表时,它将返回STATUS_SUCCESS。

除了生成 DMA 缓冲区外,显示微型端口驱动程序还必须生成修补程序位置列表,该列表指示 DMA 缓冲区内的各种偏移量,当分配的物理地址已知时,以后必须修补这些偏移量。 有时,视频内存管理器为驱动程序提供预修补的信息 (,即分配列表中源和目标) 的最后已知物理地址。

当视频内存管理器提供此信息时,驱动程序必须通过确定这些物理地址是 DirectX 图形内核子系统将提供的最终地址来生成 DMA 缓冲区。 图形子系统可能不会在 DMA 缓冲区上调用 DxgkDdiPatch 函数,以便稍后再次修补它。 因此,驱动程序必须使用预修补信息来正确生成 DMA 缓冲区。 当 DXGKARG_PRESENT的 pAllocationList 数组的第 N个元素的 SegmentId 成员为非零时,会为元素 N 提供预先修补的信息。

注意即使驱动程序的 DxgkDdiPresent 函数预先修补 DMA 缓冲区,驱动程序仍必须将对分配的所有引用插入到 DXGKARG_PRESENTpPatchLocationListOut 成员指定的输出修补程序位置列表中。 驱动程序必须插入这些引用,因为在将 DMA 缓冲区提交到 GPU 之前,分配的地址可能会更改;因此,DirectX 图形内核子系统将调用 DxgkDdiPatch 函数来重新绘制 DMA 缓冲区。
 
如果驱动程序支持旋转 (即,在调用其 DxgkDdiEnumVidPnCofuncModality 函数时,报告D3DKMDT_VIDPN_PRESENT_PATH_TRANSFORMATION结构的 RotationSupport 成员中对旋转模式的支持) ,则驱动程序必须能够执行从源到目标的旋转位块传输 (bitblt) 。 在 DXGKARG_PRESENT 的 Flags 成员的 DXGK_PRESENTFLAGS 结构中指定旋转位字段标志时,驱动程序应应用旋转,就像从非旋转图面到当前源的最终方向一样。

源的主分配在 DxgkDdiCommitVidPn 函数中指定。 如果多个路径源自给定源 (克隆模式) ,则显示微型端口驱动程序必须确保在给定不同目标的路径旋转模式的情况下正确旋转输出。 提供给 DxgkDdiPresent 的所有参数与旋转无关。 源矩形和目标矩形都可以是整个屏幕,因为客户端 (例如 768 x 1024) 。

注意 这种情况无法解决处于旋转模式的全屏 Direct3D 应用程序。
 
如果显示微型端口驱动程序之前指示,则在调用其 DxgkDdiQueryAdapterInfo 函数时, 它支持内存映射 I/O (基于 MMIO) 的翻转 (,方法是将 DXGK_DRIVERCAPS 结构的 FlipCaps 成员中的 FlipOnVSyncMmIo 位字段标志设置为 TRUE) ,随后调用驱动程序的 DxgkDdiPresent 函数,并将 DXGKARG_PRESENTpDmaBuffer 成员设置为 NULL因为基于 MMIO 的翻转不需要 DMA 缓冲区在 GPU 上运行。 相反,驱动程序的 DxgkDdiPresent 函数必须根据需要验证源图面和编程翻转硬件。 DirectX 图形内核子系统调用驱动程序的 DxgkDdiSetVidPnSourceAddress 函数来运行这种类型的翻转。

应使 DxgkDdiPresent 可分页。

要求

要求
最低受支持的客户端 Windows Vista
目标平台 桌面
标头 d3dkmddi.h
IRQL PASSIVE_LEVEL

另请参阅

D3DDDIFORMAT

DXGKARG_CREATECONTEXT

DXGKARG_PRESENT

DXGK_DEVICEINFO

DXGK_DRIVERCAPS

DXGK_PRESENTFLAGS

DxgkDdiCommitVidPn

DxgkDdiCreateContext

DxgkDdiCreateDevice

DxgkDdiEnumVidPnCofuncModality

DxgkDdiPatch

DxgkDdiQueryAdapterInfo