Directx Direct3D:从IDirect3DSurface9(默认池)获取系统内存位图的有效方法?

Directx Direct3D:从IDirect3DSurface9(默认池)获取系统内存位图的有效方法?,directx,direct3d,direct3d9,rendertarget,Directx,Direct3d,Direct3d9,Rendertarget,我有IDirect3DSurface9,默认池,YUV格式。如何有效地从中获取位图位?此刻我: 创建渲染目标: device->CreateRenderTarget(surf_desc.Width、surf_desc.Height、D3DFMT_A8R8G8B8、D3DMULTISAMPLE_NONE、0、TRUE和render_target、NULL) 将YUV转换为RGB32: device->StretchRect(videomem\u surf,NULL,render\u target\

我有IDirect3DSurface9,默认池,YUV格式。如何有效地从中获取位图位?此刻我:

    创建渲染目标:
    device->CreateRenderTarget(surf_desc.Width、surf_desc.Height、D3DFMT_A8R8G8B8、D3DMULTISAMPLE_NONE、0、TRUE和render_target、NULL)
    将YUV转换为RGB32:
    device->StretchRect(videomem\u surf,NULL,render\u target\u,NULL,D3DTEXF\u NONE)

    (完整的矩形,无拉伸)
    在系统内存中创建普通屏幕外表面
    device->CreateOffscreenPlainSurface(冲浪描述宽度、冲浪描述高度、D3DFMT\U A8R8G8B8、D3DPOOL\U系统内存和系统内存屏幕外冲浪、空)
    将数据从视频内存复制到系统内存:
    device->GetRenderTargetData(渲染目标、系统内存、屏幕外表面)
    从屏幕外表面获取DC,创建兼容DC和兼容位图,将位图从屏幕外表面复制到兼容DC,并通过GetDIBits()将位图位复制到我的缓冲区。
这看起来有点开销,因为复制太多:从原始曲面到渲染目标,然后到屏幕外曲面,然后到兼容位图,最后到我的缓冲区。如何改进这一点


谢谢

因为您在可锁定模式下创建了渲染目标(第6个参数为
CreateRenderTarget
),所以您可以使用
LockRect
锁定渲染目标,并直接从那里复制数据

MSDN不建议使用可锁定渲染目标,并且:

如果需要对渲染目标进行读取访问,请使用GetRenderTargetData而不是lockable 渲染目标


因此,另一种方法是将
GetRenderTargetData
调用到屏幕外表面,然后锁定屏幕外表面(而不是使用DCs和位图)。

正如interjay指出的那样。。。你几乎是在用“正确”的方式做事

明显的改进是调用CreateRenderTarget和CreateOffscreenPlainSurface一次,然后多次重复使用。最快的方法是直接锁定曲面,将位取出

此外,如果您需要在视频之类的东西上实时执行此操作,则最好设置一组曲面(两种类型)。然后,可以将多个YUV帧加载到CreateRenderTarget的曲面上,然后填充阵列后,将第一个帧复制到OffscreenPlainSurface并将其锁定


通过这种方式,您将允许更多命令通过管道传输,并停止调用lock和强制管道同步(即,在继续进行导致管道同步的操作之前,您要锁定的表面必须准备就绪)。

LockRect提供了哪种数据格式?没有找到任何描述。与GetDIBits()相同?@robin:每行像素都根据颜色格式压缩了字节。因此,对于D3DFMT_A8R8G8B8,每个像素有4个字节。每个像素的字节顺序相反(小端),因此在本例中,它们的顺序为:B、G、R、A。提供给您的
Pitch
值告诉您每行需要多少字节。您需要这样做,因为每行末尾可能有未使用的字节。