Direct3D: Эффективный способ получить системную память BITMAP от IDIRECT3DSURFace9 (пул по умолчанию)?
-
09-10-2019 - |
Вопрос
У меня 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 и заблокируйте его.
Таким образом, вы позволите большему количеству команд быть кондиционированными и остановить вызов блокировки и заставить синхронизацию трубопровода (то есть поверхность, которую вы блокируете, должны быть готовы перед продолжением, что приводит к синхронизации трубопровода).