2010-12-13 15 views
4

私はIDirect3DSurface9、デフォルトプール、YUV形式を持っています。ビットマップビットを効率的に取得するにはどうすればよいですか?現時点ではI:
Direct3D:システムメモリのビットマップをIDirect3DSurface9(デフォルトプール)から効率的に取得する方法?

    は、レンダーターゲット作成:RGB32へ
    device->CreateRenderTarget(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL)
    コンバートYUV:
    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)
    copy data fro sysMEMするm個のビデオMEM:
    device->GetRenderTargetData(render_target, sysmem_offscreen_surface)
    オフスクリーンサーフェスから、互換性のDCと互換性のあるビットマップを作成し、BitBltをオフスクリーンsufrace DCから互換性のDCへGetDCとGetDIBits(で私のバッファへのビットマップのビットをコピー)

このルックスオリジナルのサーフェスからターゲットをレンダリングするまで、次にオフスクリーンのサーフェスに、次に互換性のあるビットマップに、そして最後に私のバッファにコピーするので、オーバーヘッドのビットが少しあります。どのように改善することができますか?あなたは、ロック可能なモード(CreateRenderTargetに第六パラメータ)でレンダーターゲット作成するので

おかげ

答えて

2

は、あなたがLockRectとレンダーターゲットをロックし、そこから直接データをコピーすることができます。

MSDNには、ロック可能なレンダーターゲット使用することをお勧めします、とsaysしません:

あなたは目標をレンダリングする代わりにロック可能 のGetRenderTargetDataを使用し、ターゲットをレンダリングするために読み取りアクセスを必要とする場合。

代わりにGetRenderTargetDataをオフスクリーンのサーフェスに呼び出し、オフスクリーンサーフェイスをロックします(DCとビットマップを使用する代わりに)。

+0

LockRectが提供するデータ形式はどれですか?説明が見つかりませんでした。 GetDIBits()と同じですか? –

+0

@robin:ピクセルの各行には、カラーフォーマットに従ってパックされたバイトがあります。したがって、D3DFMT_A8R8G8B8の場合、1ピクセルあたり4バイトになります。各ピクセルのバイトは逆順(リトルエンディアン)なので、この場合はB、G、R、Aの順番になります。そしてあなたに与えられた 'Pitch'値は、各行にどれくらいのバイトがかかるかを示します。各行の最後に未使用のバイトがある可能性があるため、これが必要です。 – interjay

3

インタージャーが指摘しているように、あなたはほぼ「正しい」方法で作業しています。

明白な改善点は、CreateRenderTargetとCreateOffscreenPlainSurfaceを一度呼び出してから、それらを複数回再利用することです。ビットを戻す最速の方法は、サーフェスを直接ロックすることです。

さらに、ビデオなどのリアルタイムでこれを行う必要がある場合は、サーフェスの配列(両方のタイプ)を設定する方がよいでしょう。 CreateRenderTargetされたサーフェイスに複数のYUVフレームをロードし、配列を塗りつぶしたら、最初のものをOffScreenPlainSurfaceにコピーしてロックすることができます。

このようにして、より多くのコマンドをパイプライン化し、パイプラインの同期を強制的に停止します(パイプラインの同期化を行う前に、HASをロックしている表面を準備する必要があります)。

関連する問題