我有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并锁定。

这样,您将允许更多的命令被管道进行管道,并阻止您调用锁定并强迫管道的同步(即,您要锁定的表面必须准备就绪,然后才能继续进行管道同步)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top