Window 的合成引擎 (DWM) 中的背景颜色伪像 [英] Background Color Artifact in Window's Composition Engine (DWM)

查看:108
本文介绍了Window 的合成引擎 (DWM) 中的背景颜色伪像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

上下文来自 Kenny Kerr 的博客:

<块引用>

Windows Vista 引入了一项称为桌面窗口管理器的服务.这个名字曾经并且继续具有误导性.将其视为 Windows 合成引擎或合成器.这个合成引擎彻底改变了应用程序窗口在桌面上的呈现方式.不是让每个窗口直接渲染到显示器或显示适配器,而是每个窗口都渲染到屏幕外表面或缓冲区.系统为每个顶级窗口分配一个这样的表面,所有 GDI、Direct3D 和当然 Direct2D 图形都被渲染到这些表面.这些离屏表面被称为重定向表面,因为 GDI 绘图命令甚至 Direct3D 交换链呈现请求都被重定向或复制(在 GPU 内)到重定向表面.

<块引用>

在某些时候,独立于任何给定的窗口,组合引擎会根据最新的一批更改决定是时候组合桌面了.这涉及将所有这些重定向表面组合在一起,添加非客户区域(通常称为窗口镶边),可能添加一些阴影和其他效果,并将最终结果呈现给显示适配器.


来自上一个SO问题的背景(见图片):

在 DirectX 中缩小尺寸时,右/下边缘会出现 win32 背景的伪影.这可以通过应用 WS_EX_NOREDIRECTIONBITMAP 样式来纠正.由于交换链是比窗口小还是大都无关紧要,因此如果没有 WS_EX_NOREDIRECTIONBITMAP,合成引擎将太小的矩形复制到重定向表面(因为窗口大小落后于鼠标位置/拖动矩形").


实际问题

但是,WS_EX_NOREDIRECTIONBITMAP 仅适用于顶级窗口,我正在尝试将 DirectX 作为子窗口嵌入到 WPF 中,并且来自子窗口背景的工件仍在通过.这让我想到了一些相关的问题:

  1. (可选)当交换链小于窗口大小时,窗口的其余部分填充为黑色(见图片).这是从交换链复制到重定向表面的结果,其中目标步幅的剩余部分(在源宽度之后)被清零?
  2. (可选)win32 后台的神器是怎么出现的?在从交换链复制之前,重定向表面是否填充了这种颜色?
  3. (可选)是否每次调整窗口大小时都会调整重定向表面的大小?
  4. (必需)每个子窗口是否都有一个重定向表面,该重定向表面又会被复制到顶层窗口的重定向表面.如果不是,那孩子的win32后台神器是怎么出现的?
  5. (必需)这是否意味着嵌入到 WPF 中的 win32 窗口的帧速率仅限于 WPF 的可变帧速率?(将 DirectX 窗口嵌入 WPF 的目的是获得恒定的 60fps 帧速率)

解决方案

我错过的是像素到达屏幕有两条路径

  1. 通过重定向表面
  2. 通过翻转演示模型

如果没有 WS_EX_NOREDIRECTIONBITMAP,交换链的内容会被复制到重定向表面的内容上.但是,在调整大小和剪裁以防止交换链的内容延伸超过窗口时存在一个错误,剪裁过小的矩形以允许看到重定向表面.当我使用 CreateSwapChainForComposition() 和 DirectComposition 获得与 CreateSwapChainForHwnd() 完全相同的行为时,我意识到了这一点.

回答我要求的问题:不,使用 HwndHost 中的翻转演示模型不会限制您使用 WPF 的刷新率.

Context from Kenny Kerr's blog:

Windows Vista introduced a service called the Desktop Window Manager. The name was and continues to be misleading. Think of it as the Windows composition engine or compositor. This composition engine completely changed the way application windows are rendered on the desktop. Rather than allowing each window to render directly to the display, or display adapter, every window renders to an off-screen surface or buffer. The system allocates one such surface per top-level window and all GDI, Direct3D and, of course, Direct2D graphics are rendered to these surfaces. These off-screen surfaces are called redirection surfaces because GDI drawing commands and even Direct3D swap chain presentation requests are redirected or copied (within the GPU) to the redirection surface.

At some point, independent of any given window, the composition engine decides it’s time to compose the desktop given the latest batch of changes. This involves composing all of these redirection surfaces together, adding the non-client areas (often called window chrome), perhaps adding some shadows and other effects, and presenting the final result to the display adapter.


Background from previous SO question (see pictures):

When resizing down in DirectX there is an artifact of the win32 background appearing at the right/bottom edges. This can be corrected by applying the WS_EX_NOREDIRECTIONBITMAP style. Since it doesn't matter whether the swapchain is smaller or larger than the window, it appears that without WS_EX_NOREDIRECTIONBITMAP the Composition Engine copies too small a rectangle to the Redirection Surface (because the window size lags behind the mouse position/"Drag rectangle").


Actual Question

However, WS_EX_NOREDIRECTIONBITMAP only works for top level windows and I'm trying to embed DirectX as a child window into WPF, and the artifact from the child window's background is still coming through. This leads me to some relate questions:

  1. (Optional) When when the swapchain is smaller than the window size, the remainder of the window is filled in black (see pictures). Is this a result of the copy from the swapchain to the Redirection Surface where the remainder of the destination stride (after the source width) is zeroed out?
  2. (Optional) How is the artifact from the win32 background appearing? Is the Redirection Surface filled with this color before the copy from the swapchain?
  3. (Optional) Are the Redirection Surfaces being resized every-time the window is resized?
  4. (Required) Does each child window have a Redirection Surface that in turn gets copied to the top level window's Redirection Surface. If not, how is the child's win32 background artifact appearing?
  5. (Required) Does this mean that the frame rate a win32 window embedded into WPF is limited to WPF's variable frame rate? (The purpose of embedding a DirectX window into WPF was to get a constant 60fps frame rate)

解决方案

What I missed was that there are two paths for pixels to get to the screen

  1. through a Redirection Surface
  2. through the Flip Presentation model

Without WS_EX_NOREDIRECTIONBITMAP the swapchain's contents get copied over the Redirection Surface's content. However, there is a bug when resizing down and the clipping to prevent the swapchain's contents, from extending past the window, clip too small a rectangle allowing the Redirection Surface to be seen. I realized this when I got the exact same behavior using CreateSwapChainForComposition() with DirectComposition as I got for CreateSwapChainForHwnd().

To answer my required questions: No, using the flip presentation model from a HwndHost does not limit your to WPF's refresh rate.

这篇关于Window 的合成引擎 (DWM) 中的背景颜色伪像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆