Direct3D: Эффективный способ получить системную память BITMAP от IDIRECT3DSURFace9 (пул по умолчанию)?

StackOverflow https://stackoverflow.com/questions/4430204

Вопрос

У меня IDIRECT3DSURFACE9, пул по умолчанию, формат YUV. Как я могу эффективно получить биты растрового изображения? На данный момент я:

    Создать цель рендеринга:
    device->CreateRenderTarget(surf_desc.Width, surf_desc.Height, D3DFMT_A8R8G8B8, D3DMULTISAMPLE_NONE, 0, TRUE, &render_target, NULL)
    Конвертировать юве на 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 с Offscreen Surface, создайте совместимый постоянный и совместимый растровый кармас, BitBLT от Offscreen Surace DC в совместимый DC и скопируйте биты растровых изображений в мой буфер GetDibits ()

Это выглядит немного наверху, из-за столько копирования: от оригинальной поверхности для рендеринга цели, затем на поверхность офсэкрана, затем для совместимого растрового изображения, а затем, наконец, в мой буфер. Как это может быть улучшено?

спасибо

Это было полезно?

Решение

Поскольку вы создаете вы визуализации цели в запираемом режиме (6-й параметр для CreateRenderTarget), вы можете заблокировать цель рендеринга с LockRect и скопируйте данные прямо оттуда.

MSDN не рекомендует использовать запираемые целевые для визуализации и говорит:

Если вам нужен доступ для чтения к целям рендеринга, используйте GetRenderTarGetData вместо заблокированных целей рендеринга.

Так что альтернатива - звонить GetRenderTargetData на поверхность вне окна, а затем заблокируйте поверхность вне окна (вместо того, чтобы использовать DC и растровые изображения).

Другие советы

Что ж, как Interjay указывает ... Вы почти делаете что-то «правильно».

Очевидные улучшения состоит в том, чтобы позвонить CreateRenderTartarget и createOffSlenplainsurface один раз, а затем повторно используйте их несколько раз. Самый быстрый способ получения битов обратно будет напрямую блокировать поверхность.

Кроме того, если вам нужно сделать это в режиме реального времени на что-то вроде видео, вероятно, будет лучше настроить массив поверхностей (оба типа). Затем вы можете загрузить несколько фреймов YUV на поверхность CreateRenderTarget'd, а затем, как только вы заполнили массив, скопируйте первый в OffScreenPlainsuroface и заблокируйте его.

Таким образом, вы позволите большему количеству команд быть кондиционированными и остановить вызов блокировки и заставить синхронизацию трубопровода (то есть поверхность, которую вы блокируете, должны быть готовы перед продолжением, что приводит к синхронизации трубопровода).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top