[vlc-devel] [PATCH 5/5] [RFC] direct3d11: add direct rendering support for the D3D11 decoder
Steve Lhomme
robux4 at gmail.com
Thu May 28 17:20:53 CEST 2015
---
modules/video_output/Makefile.am | 1 +
modules/video_output/msw/common.h | 1 -
modules/video_output/msw/direct3d11.c | 126 +++++++++++++++++++++++++---------
3 files changed, 93 insertions(+), 35 deletions(-)
diff --git a/modules/video_output/Makefile.am b/modules/video_output/Makefile.am
index d7aef95..8436673 100644
--- a/modules/video_output/Makefile.am
+++ b/modules/video_output/Makefile.am
@@ -184,6 +184,7 @@ EXTRA_LTLIBRARIES += libdirect3d9_plugin.la
libdirect3d11_plugin_la_SOURCES = video_output/msw/direct3d11.c \
video_output/msw/common.c video_output/msw/common.h \
+ ../src/win32/direct3d11_pool.c ../src/win32/direct3d11_pool.h \
../src/win32/picture.c ../src/win32/picture.h
libdirect3d11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
-DMODULE_NAME_IS_direct3d11
diff --git a/modules/video_output/msw/common.h b/modules/video_output/msw/common.h
index 903414e..f0617c9 100644
--- a/modules/video_output/msw/common.h
+++ b/modules/video_output/msw/common.h
@@ -183,7 +183,6 @@ struct vout_display_sys_t
d3d_quad_cfg_t picQuadConfig;
ID3D11RenderTargetView *d3drenderTargetView;
ID3D11DepthStencilView *d3ddepthStencilView;
- picture_sys_t *picsys;
const char *d3dPxShader;
// SPU
diff --git a/modules/video_output/msw/direct3d11.c b/modules/video_output/msw/direct3d11.c
index 6a5dad6..746af41 100644
--- a/modules/video_output/msw/direct3d11.c
+++ b/modules/video_output/msw/direct3d11.c
@@ -34,6 +34,7 @@
#include <d3d11.h>
#include <d3dx9math.h>
+#include "../../src/win32/direct3d11_pool.h"
#include "../../src/win32/picture.h"
/* avoided until we can pass ISwapchainPanel without c++/cx mode
@@ -82,6 +83,7 @@ typedef struct
} d3d_format_t;
static const d3d_format_t d3d_formats[] = {
+ { "VA_NV12", DXGI_FORMAT_NV12, VLC_CODEC_D3D11_OPAQUE, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
{ "I420", DXGI_FORMAT_NV12, VLC_CODEC_I420, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
{ "YV12", DXGI_FORMAT_NV12, VLC_CODEC_YV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
{ "NV12", DXGI_FORMAT_NV12, VLC_CODEC_NV12, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8G8_UNORM },
@@ -104,13 +106,6 @@ static const d3d_format_t d3d_formats[] = {
{ NULL, 0, 0, 0, 0}
};
-struct picture_sys_t
-{
- ID3D11Texture2D *texture;
- ID3D11DeviceContext *context;
- vout_display_t *vd;
-};
-
/* matches the D3D11_INPUT_ELEMENT_DESC we setup */
typedef struct d3d_vertex_t {
D3DXVECTOR3 position;
@@ -124,6 +119,8 @@ typedef struct d3d_vertex_t {
static int Open(vlc_object_t *);
static void Close(vlc_object_t *object);
+static picture_pool_t *Pool(vout_display_t *vd, unsigned count);
+
static void Prepare(vout_display_t *, picture_t *, subpicture_t *subpicture);
static void Display(vout_display_t *, picture_t *, subpicture_t *subpicture);
@@ -136,6 +133,9 @@ static void Direct3D11Close(vout_display_t *);
static int Direct3D11CreateResources (vout_display_t *, video_format_t *);
static void Direct3D11DestroyResources(vout_display_t *);
+static int Direct3D11CreatePool (vout_display_t *, video_format_t *);
+static void Direct3D11DestroyPool(vout_display_t *);
+
static int Direct3D11MapTexture(picture_t *);
static void Direct3D11DeleteRegions(int, picture_t **);
static int Direct3D11MapSubpicture(vout_display_t *, int *, picture_t ***, subpicture_t *);
@@ -451,11 +451,12 @@ static int Open(vlc_object_t *object)
}
vout_display_info_t info = vd->info;
- info.is_slow = true;
+ info.is_slow = fmt.i_chroma != VLC_CODEC_D3D11_OPAQUE;
info.has_double_click = true;
info.has_hide_mouse = false;
info.has_pictures_invalid = true;
info.has_event_thread = true;
+ info.has_pictures_invalid = fmt.i_chroma != VLC_CODEC_D3D11_OPAQUE;
if (var_InheritBool(vd, "direct3d11-hw-blending") &&
sys->d3dregion_format != DXGI_FORMAT_UNKNOWN)
@@ -467,7 +468,7 @@ static int Open(vlc_object_t *object)
video_format_Copy(&vd->fmt, &fmt);
vd->info = info;
- vd->pool = CommonPool;
+ vd->pool = Pool;
vd->prepare = Prepare;
vd->display = Display;
vd->control = CommonControl;
@@ -494,6 +495,15 @@ static void Close(vlc_object_t *object)
free(vd->sys);
}
+static picture_pool_t *Pool(vout_display_t *vd, unsigned count)
+{
+ if ( vd->sys->pool == NULL )
+ vd->sys->pool = AllocPoolD3D11Ex( VLC_OBJECT(vd), vd->sys->d3ddevice,
+ vd->sys->d3dcontext, &vd->fmt,
+ vd->sys->picQuadConfig.textureFormat, count );
+ return vd->sys->pool;
+}
+
static HRESULT UpdateBackBuffer(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
@@ -597,7 +607,21 @@ static void Manage(vout_display_t *vd)
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
{
vout_display_sys_t *sys = vd->sys;
- VLC_UNUSED(picture);
+
+ if (picture->format.i_chroma == VLC_CODEC_D3D11_OPAQUE) {
+ D3D11_BOX box;
+ box.left = 0;
+ box.right = picture->format.i_visible_width;
+ box.top = 0;
+ box.bottom = picture->format.i_visible_height;
+ box.back = 1;
+ box.front = 0;
+ ID3D11DeviceContext_CopySubresourceRegion(sys->d3dcontext,
+ (ID3D11Resource*) sys->picQuad.pTexture,
+ 0, 0, 0, 0,
+ (ID3D11Resource*) picture->p_sys->texture,
+ 0, &box);
+ }
#if VLC_WINSTORE_APP /* TODO: Choose the WinRT app background clear color */
float ClearColor[4] = { 1.0f, 0.125f, 0.3f, 1.0f };
@@ -806,7 +830,12 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
hr = D3D11CreateDevice(NULL, driverAttempts[driver], NULL, creationFlags,
NULL, 0, D3D11_SDK_VERSION,
&sys->d3ddevice, NULL, &sys->d3dcontext);
- if (SUCCEEDED(hr)) break;
+ if (SUCCEEDED(hr)) {
+#ifndef NDEBUG
+ msg_Dbg(vd, "Created the D3D11 device 0x%p ctx 0x%p type %d.", sys->d3ddevice, sys->d3dcontext, driverAttempts[driver]);
+#endif
+ break;
+ }
}
if (FAILED(hr)) {
@@ -935,6 +964,7 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
switch (fmt->i_chroma)
{
case VLC_CODEC_NV12:
+ case VLC_CODEC_D3D11_OPAQUE:
if( fmt->i_height > 576 )
sys->d3dPxShader = globPixelShaderBiplanarYUV_BT709_2RGB;
else
@@ -1230,18 +1260,38 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
ID3D11DeviceContext_PSSetSamplers(sys->d3dcontext, 0, 1, &d3dsampState);
ID3D11SamplerState_Release(d3dsampState);
- picture_sys_t *picsys = malloc(sizeof(*picsys));
+ if (Direct3D11CreatePool(vd, fmt))
+ {
+ msg_Err(vd, "Direct3D picture pool initialization failed");
+ return VLC_EGENERIC;
+ }
+
+ msg_Dbg(vd, "Direct3D11 resources created");
+ return VLC_SUCCESS;
+}
+
+static int Direct3D11CreatePool(vout_display_t *vd, video_format_t *fmt)
+{
+ vout_display_sys_t *sys = vd->sys;
+
+ if ( fmt->i_chroma == VLC_CODEC_D3D11_OPAQUE )
+ /* a D3D11VA pool will be created when needed */
+ return VLC_SUCCESS;
+
+ picture_sys_t *picsys = calloc(1, sizeof(*picsys));
if (unlikely(picsys == NULL)) {
return VLC_ENOMEM;
}
picsys->texture = sys->picQuad.pTexture;
picsys->context = sys->d3dcontext;
- picsys->vd = vd;
- picture_resource_t resource = { .p_sys = picsys };
+ picture_resource_t resource = {
+ .p_sys = picsys,
+ .pf_destroy = DestroyD3D11Picture,
+ };
for (int i = 0; i < PICTURE_PLANE_MAX; i++)
- resource.p[i].i_lines = fmt->i_visible_height / (i > 0 ? 2 : 1);
+ resource.p[i].i_lines = fmt->i_height / (i > 0 ? 2 : 1);
picture_t *picture = picture_NewFromResource(fmt, &resource);
if (!picture) {
@@ -1250,7 +1300,6 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
}
ID3D11Texture2D_AddRef(picsys->texture);
ID3D11DeviceContext_AddRef(picsys->context);
- sys->picsys = picsys;
picture_pool_configuration_t pool_cfg;
memset(&pool_cfg, 0, sizeof(pool_cfg));
@@ -1264,10 +1313,18 @@ static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
return VLC_ENOMEM;
}
- msg_Dbg(vd, "Direct3D11 resources created");
return VLC_SUCCESS;
}
+static void Direct3D11DestroyPool(vout_display_t *vd)
+{
+ vout_display_sys_t *sys = vd->sys;
+
+ if (sys->pool)
+ picture_pool_Release(sys->pool);
+ sys->pool = NULL;
+}
+
static int AllocQuad(vout_display_t *vd, const video_format_t *fmt, d3d_quad_t *quad,
d3d_quad_cfg_t *cfg, ID3D11PixelShader *d3dpixelShader,
const float vertices[4 * sizeof(d3d_vertex_t)])
@@ -1360,14 +1417,7 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
- /* TODO: Destroy Shaders? */
- if (sys->pool) {
- picture_sys_t *picsys = sys->picsys;
- ID3D11Texture2D_Release(picsys->texture);
- ID3D11DeviceContext_Release(picsys->context);
- picture_pool_Release(sys->pool);
- }
- sys->pool = NULL;
+ Direct3D11DestroyPool(vd);
ReleaseQuad(&sys->picQuad);
Direct3D11DeleteRegions(sys->d3dregion_count, sys->d3dregions);
@@ -1388,14 +1438,14 @@ static int Direct3D11MapTexture(picture_t *picture)
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr;
int res;
- hr = ID3D11DeviceContext_Map(picture->p_sys->context, (ID3D11Resource *)picture->p_sys->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ picture_sys_t *p_sys = picture->p_sys;
+ hr = ID3D11DeviceContext_Map(picture->p_sys->context, (ID3D11Resource *)p_sys->texture,
+ 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( FAILED(hr) )
- {
- msg_Dbg( picture->p_sys->vd, "failed to map the texture (hr=0x%lX)", hr );
return VLC_EGENERIC;
- }
+
res = CommonUpdatePicture(picture, NULL, mappedResource.pData, mappedResource.RowPitch);
- ID3D11DeviceContext_Unmap(picture->p_sys->context,(ID3D11Resource *)picture->p_sys->texture, 0);
+ ID3D11DeviceContext_Unmap(picture->p_sys->context,(ID3D11Resource *)p_sys->texture, 0);
return res;
}
@@ -1482,10 +1532,14 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
continue;
}
quad_picture = (*region)[i];
- hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ hr = ID3D11DeviceContext_Map(sys->d3dcontext,
+ (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pTexture,
+ 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) ) {
err = CommonUpdatePicture(quad_picture, NULL, mappedResource.pData, mappedResource.RowPitch);
- ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pTexture, 0);
+ ID3D11DeviceContext_Unmap(sys->d3dcontext,
+ (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pTexture,
+ 0);
if (err != VLC_SUCCESS) {
msg_Err(vd, "Failed to set the buffer on the OSD picture" );
picture_Release(quad_picture);
@@ -1529,7 +1583,9 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
float opacity = (float)r->i_alpha / 255.0f;
- hr = ID3D11DeviceContext_Map(sys->d3dcontext, (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
+ hr = ID3D11DeviceContext_Map(sys->d3dcontext,
+ (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pVertexBuffer,
+ 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) ) {
d3d_vertex_t *dst_data = mappedResource.pData;
@@ -1565,7 +1621,9 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
dst_data[3].texture.y = 0.0f;
dst_data[3].opacity = opacity;
- ID3D11DeviceContext_Unmap(sys->d3dcontext, (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pVertexBuffer, 0);
+ ID3D11DeviceContext_Unmap(sys->d3dcontext,
+ (ID3D11Resource *)((d3d_quad_t *) quad_picture->p_sys)->pVertexBuffer,
+ 0);
} else {
msg_Err(vd, "Failed to lock the subpicture vertex buffer (hr=0x%lX)", hr );
}
--
2.4.0
More information about the vlc-devel
mailing list