Direct3D:从IDIRECT3DSURFACE9(默认池)获取系统内存位图的有效方法?
-
09-10-2019 - |
题
我有IDIRECT3DSURFACE9,默认池,YUV格式。如何从中有效地获得位图位?目前我:
- 创建渲染目标:
device->CreateRenderTarget(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL)
- 将YUV转换为RGB32:
device->StretchRect(videomem_surf, NULL, render_target_, NULL, D3DTEXF_NONE)
(完整的矩形,没有拉伸)
- 在系统内存中创建平原屏幕外表面
device->CreateOffscreenPlainSurface(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sysmem_offscreen_surf, NULL)
- 从视频mem复制数据到sysmem:
device->GetRenderTargetData(render_target, sysmem_offscreen_surface)
- 从屏幕外面的getDC,创建兼容的直流和兼容位图,从屏幕外sufrace DC到兼容DC,然后通过getDibits()将位图位副本复制到我的缓冲区
这看起来有些开销,因为复制了很多:从原始表面到渲染目标,然后再到屏幕外面的表面,然后再兼容位图,然后最后到我的缓冲区。如何改进?
谢谢
解决方案
由于您创建了以锁定模式渲染目标(第六参数为 CreateRenderTarget
),您可以用 LockRect
并直接从那里复制数据。
MSDN不建议使用可锁定渲染目标,并且 说:
如果您需要阅读对渲染目标的访问,请使用getRendertArgetData而不是可锁定渲染目标。
因此,另一种是打电话 GetRenderTargetData
进入屏幕外表面,然后锁定屏幕表面(而不是使用DC和位图)。
其他提示
正如Interjay指出的那样...您几乎以“正确”的方式做事。
明显的改进是一次调用CreaterenDertArget和CreateOffScreenPlainsUrface,然后多次重复使用它们。恢复钻头的最快方法是直接锁定表面。
此外,如果您需要在视频之类的视频上实时执行此操作,则最好设置一系列表面(两种类型)。然后,您可以将多个YUV框架加载到CreaterenDertarget的表面,然后一旦填充数组,然后将首先复制到OffScreenPlainsUrface并锁定。
这样,您将允许更多的命令被管道进行管道,并阻止您调用锁定并强迫管道的同步(即,您要锁定的表面必须准备就绪,然后才能继续进行管道同步)。
不隶属于 StackOverflow