首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在使用GDI绘制带有DWM组合的窗口时,有可能防止撕裂伪影吗?

在使用GDI绘制带有DWM组合的窗口时,有可能防止撕裂伪影吗?
EN

Stack Overflow用户
提问于 2014-10-02 13:49:25
回答 1查看 1.2K关注 0票数 14

我正在绘制一个使用双缓冲GDI在窗口上的动画,在启用DWM组合的系统上,并在屏幕上看到明显可见的tearing。有什么办法可以防止这种情况发生吗?

详细信息

动画接受相同的图像,并将其向左移动到屏幕上;像素数由当前时间与动画开始时间和结束时间之间的差异决定,以获得一个分数完成,该分数被应用于整个窗口宽度,使用timeGetTime和一个1ms resolution。动画在不处理应用程序消息的情况下绘制一个循环;它调用(VCL库)方法Repaint,该方法在内部无效,然后为所讨论的窗口调用UpdateWindow,直接使用WM_PAINT调用消息过程。油漆处理程序的VCL实现使用BeginBufferedPaint。绘画本身是双重缓冲的。

这样做的目的是有一个尽可能高的帧速率,以获得一个顺利的动画在屏幕上。(绘图使用双缓冲以消除闪烁,并确保整个图像或帧在任何时候都在屏幕上。它通过调用消息过程直接使其无效和更新,而不执行其他消息处理。绘画是用现代技术(如BeginBufferedPaint)来实现的。在这个过程中,绘画是在两个BitBlt调用中完成的(一个用于动画的左侧,即屏幕外移动的内容,另一个用于动画的右侧,即屏幕上的移动)。

当观看动画时,有明显可见的tearing.出现在Windows上,7和8.1出现在不同显卡的多个系统上。

我处理这一问题的方法是降低绘制速度,或者在重新绘制之前尝试等待VSync。这可能是错误的方法,所以这个问题的答案可能是“完全做其他的事情: X”。如果是这样,那就太好了:)

(我真正想要的是一种方法,要求DWM只为这个特定的窗口编写/使用完全绘制的框架。)

我尝试过以下方法,但没有一种方法可以消除所有可见的撕裂。因此,问题是,在使用DWM组合物时,是否有可能避免撕裂,如果是,如何避免撕裂?

尝试了以下方法:

  • 通过GetDeviceCaps(Application.MainForm.Handle, VREFRESH)获取监视器刷新速率;休眠1/刷新速率毫秒。稍微比绘画进步得快,但可能是一厢情愿的。感觉稍不流畅的动画率。(调整:普通Sleep和使用timeGetTime的高分辨率自旋等待。)
  • 使用DwmSetPresentParameters尝试将更新限制在代码绘制的相同速率上。(变化:大量缓冲区(cBuffer = 8) (无可见效果);指定监视器刷新速率/ 1的源速率并使用上述代码休眠(与尝试休眠方法相同);指定1、10等帧的刷新(无可见效果);更改源帧覆盖(无可见效果)。
  • 以多种方式使用DwmGetCompositionTimingInfo

代码语言:javascript
复制
- ​
    - While `cFramesPending` > 0, spin;

代码语言:javascript
复制
- ​
    - Get `cFrame` (frame composed) and spin while this number doesn't change; 

代码语言:javascript
复制
- ​
    - Get `cFrameDisplayed` and spin while this doesn't change;

代码语言:javascript
复制
- ​
    - Calculating a time to sleep to by adding `qpcVBlank + qpcRefreshPeriod`, and then while `QueryPerformanceCounter` returns a time less than this, spin

  • 所有这些方法也因绘画而不同,然后在重新绘画之前旋转/睡觉;或相反:睡觉然后绘画。

很少有明显的效果,有什么影响是很难合格的,可能只是一个较低的帧速率的结果。无一防止撕裂(没有使DWM用窗口DC的内容的“完整”副本组成窗口)。

谢谢你的建议:)

EN

回答 1

Stack Overflow用户

发布于 2015-11-05 14:32:06

由于您使用的是BitBlt,请确保您的DIBs为4字节/像素。使用3个字节/像素,当DWM运行时,GDI非常慢,这可能是撕裂的来源。我遇到的另一个BitBlt问题是,如果您的DIB比BitBlt调用要花费的时间要长得出人意料。如果您将一个调用拆分为较小的调用,而不是只提取一部分数据,则可能会有所帮助。这两项都对我的情况有所帮助,只是因为BitBlt本身运行太慢,从而导致了视频伪影。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26162308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档