窗口 – 在DWM组合的窗口上使用GDI绘制时可以防止撕裂伪影吗?

前端之家收集整理的这篇文章主要介绍了窗口 – 在DWM组合的窗口上使用GDI绘制时可以防止撕裂伪影吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我在窗口上,在启用DWM组合的系统上绘制一个使用双缓冲GDI的动画,并在屏幕上看到清晰可见的 tearing.有办法防止这种情况吗?

细节

动画采取相同的图像,并将其向右移动到屏幕上;像素数量由当前时间与动画开始时间之间的差异以及时间结束决定,以使用timeGetTime1ms resolution一起应用于整个窗口宽度的分数完成.动画吸引没有处理应用程序消息的循环;它调用了内部无效的(VCL库)方法Repaint,然后调用相关窗口的UpdateWindow,直接使用WM_PAINT调用消息过程.绘画处理程序的VCL实现使用BeginBufferedPaint.绘画本身是双重缓冲的.

这样做的目的是尽可能高的帧率,以便在屏幕上获得平滑的动画. (绘图使用双缓冲来消除闪烁,并确保任何一个屏幕上的整个图像或帧,通过调用消息过程直接进行消息和更新,而不进行其他消息处理.使用现代技术例如,用于Aero构图的BeginBufferedPaint))在其中,绘画是在几个BitBlt调用中完成的(一个用于动画的左侧,即移动在屏幕之外,还有一个用于动画的右侧,即屏幕上移动的内容. )

观看动画时,清晰可见tearing.这种情况发生在具有不同显卡的多个系统上的Windows Vista,7和8.1上.

处理这个问题的方法是降低绘制速度,或者在再次绘制之前尝试等待VSync.这可能是错误的做法,所以这个问题的答案可能是“完成其他事情:X”.如果是的话,很棒:)

(我真正想要的是要求DWM在这个特定的窗口中编写/使用全画幅的方法.)

我尝试了以下方法,没有一个删除所有可见的撕裂.所以问题是,在使用DWM组合时是否有可能避免撕裂,如果是这样呢?

方法尝试:

>通过GetDeviceCaps(Application.MainForm.Handle,VREFRESH)获取显示器刷新率;睡眠1 /刷新率毫秒.稍稍改善画面尽可能快,但可能是一厢情愿.感觉上略微平滑的动画率. (调整:正常睡眠和使用timeGetTime的高分辨率旋转等待)
>使用DwmSetPresentParameters尝试将更新限制为与代码绘制相同的速率. (变化:大量的缓冲区(cBuffer = 8)(无可见效果);指定监视器刷新率/ 1的源速率和使用上述代码进行睡眠(与刚尝试睡眠方式相同);指定每帧刷新1,10等(无可见效果);改变源帧覆盖(无可见效果)
>以各种方式使用DwmGetCompositionTimingInfo

>
>虽然cFramesPending> 0,旋转

>
>获取cFrame(框架组合)并旋转,而此数字不变;

>
>获取cFrame显示和旋转,而这并没有改变;

>
>通过添加qpcVBlank qpcRefreshPeriod计算睡眠时间,然后QueryPerformanceCounter返回的时间少于此值,旋转

>所有这些方法也通过绘画而变化,然后再次喷涂/睡觉;或反过来:睡觉然后画画.

几乎似乎有任何明显的效果,并且有什么影响是很难限定,可能只是由于帧率较低.没有防止撕裂,即没有使DWM使用窗口的DC的内容的“整体”副本组成窗口.

忠告赞:)

由于您使用BitBlt,请确保您的DIB是4字节/像素.使用3个字节/像素,GDI在DWM运行时非常慢,这可能是您的撕裂的根源.另一个BitBlt问题我遇到了,如果你的DIB有点大,比BitBlt调用让我们意想不到的长时间.如果您将一个呼叫分成较小的呼叫,而不仅仅是绘制一部分数据,那么它可能会有所帮助.这两个项目都帮助我,只因为BitBlt本身运行得太慢,从而导致视频制品.

猜你在找的Windows相关文章