2010-12-13 32 views
4

J'ai IDirect3DSurface9, pool par défaut, format YUV. Comment puis-je obtenir efficacement des bits bitmap? En ce moment je:
Direct3D: moyen efficace d'obtenir bitmap de mémoire système à partir de IDirect3DSurface9 (pool par défaut)?

    créer render target:
    device->CreateRenderTarget(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL)
    convertir YUV RGB32:
    device->StretchRect(videomem_surf, NULL, render_target_, NULL, D3DTEXF_NONE)
    (rectangle complet, sans étirement)
    créer plaine offscreen surface dans la mémoire système
    device->CreateOffscreenPlainSurface(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &sysmem_offscreen_surf, NULL)
    copier les données m vidéo mem à sysmem:
    device->GetRenderTargetData(render_target, sysmem_offscreen_surface)
    GetDC de offscreen surface, de créer bitmap DC et compatible compatible, BitBlt de offscreen sufrace DC à DC compatible et copier les bits bitmap à mon tampon par GetDIBits()

Cela ressemble un peu d'overhead, à cause de tant de copies: de la surface d'origine à la cible de rendu, puis à la surface hors écran, puis à l'image bitmap compatible, et enfin à mon buffer. Comment ça pourrait être amélioré?

grâce

Répondre

2

Puisque vous vous créez un rendu cible en mode fermant à clé (6ème paramètre à CreateRenderTarget), vous pouvez verrouiller la cible rendu avec LockRect et copier les données directement à partir de là.

MSDN ne recommande pas d'utiliser des cibles rendre verrouillable et says:

Si vous avez besoin d'accès en lecture pour rendre les cibles, utiliser GetRenderTargetData au lieu de fermant à clé rendre les cibles.

donc une alternative est d'appeler GetRenderTargetData dans la surface hors-champ, puis verrouiller la surface hors écran (au lieu d'utiliser les CD et bitmaps).

+0

Quel format de données fournit LockRect? n'a trouvé aucune description. le même que GetDIBits()? –

+0

@robin: Chaque ligne de pixels contient des octets compressés selon le format de couleur.Donc pour D3DFMT_A8R8G8B8 vous auriez 4 octets par pixel. Les octets pour chaque pixel sont dans l'ordre inverse (little-endian), donc dans ce cas ils seraient dans l'ordre: B, G, R, A. Et la valeur 'Pitch' qui vous est donnée vous indique combien d'octets chaque ligne prend. Vous en avez besoin car il peut y avoir des octets inutilisés à la fin de chaque ligne. – interjay

3

Eh bien, comme le souligne Interjay ... vous êtes sur le point de faire les choses de manière "correcte".

Les améliorations évidentes sont d'appeler une fois CreateRenderTarget et CreateOffscreenPlainSurface, puis de les réutiliser plusieurs fois. Le moyen le plus rapide de récupérer les bits serait de verrouiller directement la surface.

En outre, si vous avez besoin de le faire en temps réel sur quelque chose comme la vidéo, il serait probablement préférable de configurer un tableau de surfaces (les deux types). Vous pouvez ensuite charger plusieurs trames YUV sur la surface CreateRenderTarget'd, puis une fois que vous avez rempli le tableau, copiez le premier sur OffscreenPlainSurface et verrouillez-le. De cette façon, vous autorisez plus de commandes à être pipelinées et vous arrêtez d'appeler le verrouillage et FORCER une synchronisation du pipeline (c'est-à-dire que la surface que vous verrouillez HAS est prête avant de procéder, ce qui provoque une synchronisation du pipeline).