vout: direct3d11: build in C++

This allows using COM helpers and shorter API calls.

It's already built with C++ from the sensor and DirectComposition handlers.
This commit is contained in:
Steve Lhomme 2021-07-08 09:57:47 +02:00
parent 5fc6a7ca5b
commit 6b7a6d86ae
17 changed files with 430 additions and 550 deletions

View File

@ -29,6 +29,15 @@
#include "dxgi_fmt.h"
#ifdef __cplusplus
extern "C" {
#ifndef IID_GRAPHICS_PPV_ARGS
#define IID_GRAPHICS_PPV_ARGS(ppType) IID_PPV_ARGS(ppType)
#endif
#endif
DEFINE_GUID(GUID_CONTEXT_MUTEX, 0x472e8835, 0x3f8e, 0x4f93, 0xa0, 0xcb, 0x25, 0x79, 0x77, 0x6c, 0xed, 0x86);
/* see https://msdn.microsoft.com/windows/hardware/commercialize/design/compatibility/device-graphics
@ -100,7 +109,7 @@ static inline d3d11_decoder_device_t *GetD3D11OpaqueDevice(vlc_decoder_device *d
{
if (device == NULL || device->type != VLC_DECODER_DEVICE_D3D11VA)
return NULL;
return device->opaque;
return (d3d11_decoder_device_t *)device->opaque;
}
static inline d3d11_decoder_device_t *GetD3D11OpaqueContext(vlc_video_context *vctx)
@ -186,4 +195,8 @@ picture_context_t *d3d11_pic_context_copy(picture_context_t *);
picture_t *D3D11_AllocPicture(vlc_object_t *,
const video_format_t *, vlc_video_context *, const d3d_format_t *);
#ifdef __cplusplus
}
#endif
#endif /* include-guard */

View File

@ -29,6 +29,10 @@
#include <vlc_common.h>
#include <vlc_fourcc.h>
#ifdef __cplusplus
extern "C" {
#endif// __cplusplus
#define GPU_MANUFACTURER_AMD 0x1002
#define GPU_MANUFACTURER_NVIDIA 0x10DE
#define GPU_MANUFACTURER_VIA 0x1106
@ -83,4 +87,8 @@ void DXGI_GetBlackColor( const d3d_format_t *,
union DXGI_Color black[DXGI_MAX_RENDER_TARGET],
size_t colors[DXGI_MAX_RENDER_TARGET] );
#ifdef __cplusplus
}
#endif// __cplusplus
#endif /* include-guard */

View File

@ -137,18 +137,15 @@ vout_LTLIBRARIES += libglinterop_dxva2_plugin.la
endif
endif
libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.c \
video_output/win32/d3d11_quad.c video_output/win32/d3d11_quad.h \
video_output/win32/d3d11_shaders.c video_output/win32/d3d11_shaders.h \
libdirect3d11_plugin_la_SOURCES = video_output/win32/direct3d11.cpp \
video_output/win32/d3d11_quad.cpp video_output/win32/d3d11_quad.h \
video_output/win32/d3d11_shaders.cpp video_output/win32/d3d11_shaders.h \
video_output/win32/d3d_shaders.c video_output/win32/d3d_shaders.h \
video_output/win32/d3d_dynamic_shader.c video_output/win32/d3d_dynamic_shader.h \
video_output/win32/d3d11_swapchain.c video_output/win32/d3d11_swapchain.h \
video_output/win32/dxgi_swapchain.c video_output/win32/dxgi_swapchain.h \
video_output/win32/d3d11_swapchain.cpp video_output/win32/d3d11_swapchain.h \
video_output/win32/dxgi_swapchain.cpp video_output/win32/dxgi_swapchain.h \
video_output/win32/common.c video_output/win32/common.h
libdirect3d11_plugin_la_LIBADD = libchroma_copy.la libd3d11_common.la $(LIBCOM) -luuid
if HAVE_DCOMP
libdirect3d11_plugin_la_SOURCES += video_output/win32/dcomp_wrapper.cpp video_output/win32/dcomp_wrapper.h
endif
if !HAVE_WINSTORE
libdirect3d11_plugin_la_SOURCES += video_output/win32/events.c \
video_output/win32/events.h \

View File

@ -24,6 +24,10 @@
#include <vlc_vout_display.h>
#ifdef __cplusplus
extern "C" {
#endif// __cplusplus
/*****************************************************************************
* event_thread_t: event thread
*****************************************************************************/
@ -75,9 +79,6 @@ void CommonPlacePicture (vout_display_t *, display_win32_area_t *);
void CommonInit(display_win32_area_t *);
# ifdef __cplusplus
extern "C" {
# endif
void* HookWindowsSensors(vout_display_t*, HWND);
void UnhookWindowsSensors(void*);
# ifdef __cplusplus

View File

@ -29,15 +29,16 @@
# define _WIN32_WINNT 0x0601 // _WIN32_WINNT_WIN7
#endif
#include <assert.h>
#include <cassert>
#include <vlc_common.h>
#define COBJMACROS
#include <d3d11.h>
#include "d3d11_quad.h"
#include "common.h"
using Microsoft::WRL::ComPtr;
void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d11_quad_t *quad, d3d11_vertex_shader_t *vsshader,
ID3D11ShaderResourceView *resourceView[DXGI_MAX_SHADER_VIEW],
d3d11_select_plane_t selectPlane, void *selectOpaque)
@ -45,29 +46,32 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d11_quad_t *quad, d3d11_vertex_
UINT offset = 0;
/* Render the quad */
ID3D11DeviceContext_IASetPrimitiveTopology(d3d_dev->d3dcontext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
d3d_dev->d3dcontext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
/* vertex shader */
ID3D11DeviceContext_IASetInputLayout(d3d_dev->d3dcontext, vsshader->layout);
ID3D11DeviceContext_IASetVertexBuffers(d3d_dev->d3dcontext, 0, 1, &quad->pVertexBuffer, &quad->generic.vertexStride, &offset);
ID3D11DeviceContext_IASetIndexBuffer(d3d_dev->d3dcontext, quad->pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
if ( quad->viewpointShaderConstant )
ID3D11DeviceContext_VSSetConstantBuffers(d3d_dev->d3dcontext, 0, 1, &quad->viewpointShaderConstant);
d3d_dev->d3dcontext->IASetInputLayout(vsshader->layout.Get());
d3d_dev->d3dcontext->IASetVertexBuffers(0, 1, quad->vertexBuffer.GetAddressOf(), &quad->generic.vertexStride, &offset);
d3d_dev->d3dcontext->IASetIndexBuffer(quad->indexBuffer.Get(), DXGI_FORMAT_R16_UINT, 0);
if ( quad->viewpointShaderConstant.Get() )
d3d_dev->d3dcontext->VSSetConstantBuffers(0, 1, quad->viewpointShaderConstant.GetAddressOf());
ID3D11DeviceContext_VSSetShader(d3d_dev->d3dcontext, vsshader->shader, NULL, 0);
d3d_dev->d3dcontext->VSSetShader(vsshader->shader.Get(), NULL, 0);
if (quad->SamplerStates[0])
ID3D11DeviceContext_PSSetSamplers(d3d_dev->d3dcontext, 0, 2, quad->SamplerStates);
if (quad->SamplerStates[0].Get())
{
ID3D11SamplerState *states[] = {quad->SamplerStates[0].Get(), quad->SamplerStates[1].Get()};
d3d_dev->d3dcontext->PSSetSamplers(0, 2, states);
}
/* pixel shader */
ID3D11DeviceContext_PSSetConstantBuffers(d3d_dev->d3dcontext, 0, 1, &quad->pPixelShaderConstants);
d3d_dev->d3dcontext->PSSetConstantBuffers(0, 1, quad->pPixelShaderConstants.GetAddressOf());
assert(quad->resourceCount <= DXGI_MAX_SHADER_VIEW);
ID3D11DeviceContext_PSSetShaderResources(d3d_dev->d3dcontext, 0, quad->resourceCount, resourceView);
d3d_dev->d3dcontext->PSSetShaderResources(0, quad->resourceCount, resourceView);
for (size_t i=0; i<ARRAY_SIZE(quad->d3dpixelShader); i++)
{
if (!quad->d3dpixelShader[i])
if (!quad->d3dpixelShader[i].Get())
break;
ID3D11RenderTargetView *renderView = NULL;
@ -75,18 +79,18 @@ void D3D11_RenderQuad(d3d11_device_t *d3d_dev, d3d11_quad_t *quad, d3d11_vertex_
continue;
if (renderView != NULL)
ID3D11DeviceContext_OMSetRenderTargets(d3d_dev->d3dcontext, 1, &renderView, NULL);
d3d_dev->d3dcontext->OMSetRenderTargets(1, &renderView, NULL);
ID3D11DeviceContext_PSSetShader(d3d_dev->d3dcontext, quad->d3dpixelShader[i], NULL, 0);
d3d_dev->d3dcontext->PSSetShader(quad->d3dpixelShader[i].Get(), NULL, 0);
ID3D11DeviceContext_RSSetViewports(d3d_dev->d3dcontext, 1, &quad->cropViewport[i]);
d3d_dev->d3dcontext->RSSetViewports(1, &quad->cropViewport[i]);
ID3D11DeviceContext_DrawIndexed(d3d_dev->d3dcontext, quad->generic.indexCount, 0, 0);
d3d_dev->d3dcontext->DrawIndexed(quad->generic.indexCount, 0, 0);
// /* force unbinding the input texture, otherwise we get:
// * OMSetRenderTargets: Resource being set to OM RenderTarget slot 0 is still bound on input! */
// ID3D11ShaderResourceView *reset[DXGI_MAX_SHADER_VIEW] = { 0 };
// ID3D11DeviceContext_PSSetShaderResources(d3d_dev->d3dcontext, 0, quad->resourceCount, reset);
// d3d_dev->d3dcontext->PSSetShaderResources(0, quad->resourceCount, reset);
}
}
@ -97,28 +101,24 @@ static bool AllocQuadVertices(vlc_object_t *o, d3d11_device_t *d3d_dev, d3d11_qu
if (!D3D_QuadSetupBuffers(o, &quad->generic, projection))
return false;
D3D11_BUFFER_DESC bd;
memset(&bd, 0, sizeof(bd));
D3D11_BUFFER_DESC bd = { };
bd.Usage = D3D11_USAGE_DYNAMIC;
bd.ByteWidth = quad->generic.vertexStride * quad->generic.vertexCount;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
hr = ID3D11Device_CreateBuffer(d3d_dev->d3ddevice, &bd, NULL, &quad->pVertexBuffer);
hr = d3d_dev->d3ddevice->CreateBuffer(&bd, NULL, quad->vertexBuffer.GetAddressOf());
if(FAILED(hr)) {
msg_Err(o, "Failed to create vertex buffer. (hr=%lX)", hr);
goto fail;
}
/* create the index of the vertices */
D3D11_BUFFER_DESC quadDesc = {
.Usage = D3D11_USAGE_DYNAMIC,
.ByteWidth = sizeof(WORD) * quad->generic.indexCount,
.BindFlags = D3D11_BIND_INDEX_BUFFER,
.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
};
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
bd.ByteWidth = sizeof(WORD) * quad->generic.indexCount;
hr = ID3D11Device_CreateBuffer(d3d_dev->d3ddevice, &quadDesc, NULL, &quad->pIndexBuffer);
hr = d3d_dev->d3ddevice->CreateBuffer(&bd, NULL, quad->indexBuffer.GetAddressOf());
if(FAILED(hr)) {
msg_Err(o, "Could not create the quad indices. (hr=0x%lX)", hr);
goto fail;
@ -126,41 +126,17 @@ static bool AllocQuadVertices(vlc_object_t *o, d3d11_device_t *d3d_dev, d3d11_qu
return true;
fail:
if (quad->pVertexBuffer)
{
ID3D11Buffer_Release(quad->pVertexBuffer);
quad->pVertexBuffer = NULL;
}
if (quad->pIndexBuffer)
{
ID3D11Buffer_Release(quad->pIndexBuffer);
quad->pIndexBuffer = NULL;
}
quad->vertexBuffer.Reset();
quad->indexBuffer.Reset();
return false;
}
void D3D11_ReleaseQuad(d3d11_quad_t *quad)
{
if (quad->pPixelShaderConstants)
{
ID3D11Buffer_Release(quad->pPixelShaderConstants);
quad->pPixelShaderConstants = NULL;
}
if (quad->pVertexBuffer)
{
ID3D11Buffer_Release(quad->pVertexBuffer);
quad->pVertexBuffer = NULL;
}
if (quad->pIndexBuffer)
{
ID3D11Buffer_Release(quad->pIndexBuffer);
quad->pIndexBuffer = NULL;
}
if (quad->viewpointShaderConstant)
{
ID3D11Buffer_Release(quad->viewpointShaderConstant);
quad->viewpointShaderConstant = NULL;
}
quad->pPixelShaderConstants.Reset();
quad->vertexBuffer.Reset();
quad->indexBuffer.Reset();
quad->viewpointShaderConstant.Reset();
D3D11_ReleaseQuadPixelShader(quad);
ReleaseD3D11PictureSys(&quad->picSys);
}
@ -174,29 +150,29 @@ bool D3D11_UpdateQuadPosition( vlc_object_t *o, d3d11_device_t *d3d_dev, d3d11_q
D3D11_MAPPED_SUBRESOURCE mappedResource;
d3d_vertex_t *dst_data;
if (unlikely(quad->pVertexBuffer == NULL))
if (unlikely(quad->vertexBuffer.Get() == NULL))
return false;
/* create the vertices */
hr = ID3D11DeviceContext_Map(d3d_dev->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
hr = d3d_dev->d3dcontext->Map(quad->vertexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
msg_Err(o, "Failed to lock the vertex buffer (hr=0x%lX)", hr);
return false;
}
dst_data = mappedResource.pData;
dst_data = static_cast<d3d_vertex_t*>(mappedResource.pData);
/* create the vertex indices */
hr = ID3D11DeviceContext_Map(d3d_dev->d3dcontext, (ID3D11Resource *)quad->pIndexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
hr = d3d_dev->d3dcontext->Map(quad->indexBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr)) {
msg_Err(o, "Failed to lock the index buffer (hr=0x%lX)", hr);
ID3D11DeviceContext_Unmap(d3d_dev->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0);
d3d_dev->d3dcontext->Unmap(quad->vertexBuffer.Get(), 0);
return false;
}
result = D3D_SetupQuadData(o, &quad->generic, output, dst_data, mappedResource.pData, orientation);
ID3D11DeviceContext_Unmap(d3d_dev->d3dcontext, (ID3D11Resource *)quad->pIndexBuffer, 0);
ID3D11DeviceContext_Unmap(d3d_dev->d3dcontext, (ID3D11Resource *)quad->pVertexBuffer, 0);
d3d_dev->d3dcontext->Unmap(quad->indexBuffer.Get(), 0);
d3d_dev->d3dcontext->Unmap(quad->vertexBuffer.Get(), 0);
return result;
}
@ -207,15 +183,15 @@ static bool ShaderUpdateConstants(vlc_object_t *o, d3d11_device_t *d3d_dev, d3d1
switch (type)
{
case PS_CONST_LUMI_BOUNDS:
res = (ID3D11Resource *)quad->pPixelShaderConstants;
res = quad->pPixelShaderConstants.Get();
break;
case VS_CONST_VIEWPOINT:
res = (ID3D11Resource *)quad->viewpointShaderConstant;
res = quad->viewpointShaderConstant.Get();
break;
}
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr = ID3D11DeviceContext_Map(d3d_dev->d3dcontext, res, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
HRESULT hr = d3d_dev->d3dcontext->Map(res, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (unlikely(FAILED(hr)))
{
msg_Err(o, "Failed to lock the picture shader constants (hr=0x%lX)", hr);
@ -231,7 +207,7 @@ static bool ShaderUpdateConstants(vlc_object_t *o, d3d11_device_t *d3d_dev, d3d1
memcpy(mappedResource.pData, new_buf, sizeof(VS_PROJECTION_CONST));
break;
}
ID3D11DeviceContext_Unmap(d3d_dev->d3dcontext, res, 0);
d3d_dev->d3dcontext->Unmap(res, 0);
return true;
}
@ -258,7 +234,7 @@ void (D3D11_UpdateQuadLuminanceScale)(vlc_object_t *o, d3d11_device_t *d3d_dev,
void (D3D11_UpdateViewpoint)(vlc_object_t *o, d3d11_device_t *d3d_dev, d3d11_quad_t *quad,
const vlc_viewpoint_t *viewpoint, float f_sar)
{
if (!quad->viewpointShaderConstant)
if (!quad->viewpointShaderConstant.Get())
return;
D3D_UpdateViewpoint(&quad->generic, viewpoint, f_sar);
@ -275,13 +251,12 @@ int D3D11_AllocateQuad(vlc_object_t *o, d3d11_device_t *d3d_dev,
HRESULT hr;
static_assert((sizeof(PS_CONSTANT_BUFFER)%16)==0,"Constant buffers require 16-byte alignment");
D3D11_BUFFER_DESC constantDesc = {
.Usage = D3D11_USAGE_DYNAMIC,
.ByteWidth = sizeof(PS_CONSTANT_BUFFER),
.BindFlags = D3D11_BIND_CONSTANT_BUFFER,
.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE,
};
hr = ID3D11Device_CreateBuffer(d3d_dev->d3ddevice, &constantDesc, NULL, &quad->pPixelShaderConstants);
D3D11_BUFFER_DESC constantDesc = { };
constantDesc.Usage = D3D11_USAGE_DYNAMIC;
constantDesc.ByteWidth = sizeof(PS_CONSTANT_BUFFER);
constantDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
constantDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
hr = d3d_dev->d3ddevice->CreateBuffer(&constantDesc, NULL, quad->pPixelShaderConstants.GetAddressOf());
if(FAILED(hr)) {
msg_Err(o, "Could not create the pixel shader constant buffer. (hr=0x%lX)", hr);
goto error;
@ -291,7 +266,7 @@ int D3D11_AllocateQuad(vlc_object_t *o, d3d11_device_t *d3d_dev,
{
static_assert((sizeof(VS_PROJECTION_CONST)%16)==0,"Constant buffers require 16-byte alignment");
constantDesc.ByteWidth = sizeof(VS_PROJECTION_CONST);
hr = ID3D11Device_CreateBuffer(d3d_dev->d3ddevice, &constantDesc, NULL, &quad->viewpointShaderConstant);
hr = d3d_dev->d3ddevice->CreateBuffer(&constantDesc, NULL, quad->viewpointShaderConstant.GetAddressOf());
if(FAILED(hr)) {
msg_Err(o, "Could not create the vertex shader constant buffer. (hr=0x%lX)", hr);
goto error;

View File

@ -31,7 +31,7 @@
#include <vlc_common.h>
#include <assert.h>
#include <cassert>
#define COBJMACROS
#include <d3d11.h>
@ -39,6 +39,8 @@
#include "d3d11_shaders.h"
#include "d3d_dynamic_shader.h"
using Microsoft::WRL::ComPtr;
HRESULT (D3D11_CompilePixelShaderBlob)(vlc_object_t *o, const d3d_shader_compiler_t *compiler,
d3d11_device_t *d3d_dev,
const display_info_t *display,
@ -56,8 +58,7 @@ HRESULT D3D11_SetQuadPixelShader(vlc_object_t *o, d3d11_device_t *d3d_dev,
bool sharp,
d3d11_quad_t *quad, d3d_shader_blob pPSBlob[DXGI_MAX_RENDER_TARGET])
{
D3D11_SAMPLER_DESC sampDesc;
memset(&sampDesc, 0, sizeof(sampDesc));
D3D11_SAMPLER_DESC sampDesc = { };
sampDesc.Filter = sharp ? D3D11_FILTER_MIN_MAG_MIP_POINT : D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT;
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
@ -67,31 +68,31 @@ HRESULT D3D11_SetQuadPixelShader(vlc_object_t *o, d3d11_device_t *d3d_dev,
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
HRESULT hr;
hr = ID3D11Device_CreateSamplerState(d3d_dev->d3ddevice, &sampDesc, &quad->SamplerStates[0]);
hr = d3d_dev->d3ddevice->CreateSamplerState(&sampDesc, quad->SamplerStates[0].GetAddressOf());
if (FAILED(hr)) {
msg_Err(o, "Could not Create the D3d11 Sampler State. (hr=0x%lX)", hr);
return hr;
}
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
hr = ID3D11Device_CreateSamplerState(d3d_dev->d3ddevice, &sampDesc, &quad->SamplerStates[1]);
hr = d3d_dev->d3ddevice->CreateSamplerState(&sampDesc, quad->SamplerStates[1].GetAddressOf());
if (FAILED(hr)) {
msg_Err(o, "Could not Create the D3d11 Sampler State. (hr=0x%lX)", hr);
ID3D11SamplerState_Release(quad->SamplerStates[0]);
quad->SamplerStates[0].Reset();
return hr;
}
hr = ID3D11Device_CreatePixelShader(d3d_dev->d3ddevice,
hr = d3d_dev->d3ddevice->CreatePixelShader(
pPSBlob[0].buffer, pPSBlob[0].buf_size,
NULL, &quad->d3dpixelShader[0]);
NULL, quad->d3dpixelShader[0].GetAddressOf());
D3D_ShaderBlobRelease(&pPSBlob[0]);
if (pPSBlob[1].buffer)
{
hr = ID3D11Device_CreatePixelShader(d3d_dev->d3ddevice,
hr = d3d_dev->d3ddevice->CreatePixelShader(
pPSBlob[1].buffer, pPSBlob[1].buf_size,
NULL, &quad->d3dpixelShader[1]);
NULL, quad->d3dpixelShader[1].GetAddressOf());
D3D_ShaderBlobRelease(&pPSBlob[1]);
}
@ -102,21 +103,13 @@ void D3D11_ReleaseQuadPixelShader(d3d11_quad_t *quad)
{
for (size_t i=0; i<ARRAY_SIZE(quad->d3dpixelShader); i++)
{
if (quad->d3dpixelShader[i])
{
ID3D11PixelShader_Release(quad->d3dpixelShader[i]);
quad->d3dpixelShader[i] = NULL;
}
if (quad->SamplerStates[i])
{
ID3D11SamplerState_Release(quad->SamplerStates[i]);
quad->SamplerStates[i] = NULL;
}
quad->d3dpixelShader[i].Reset();
quad->SamplerStates[i].Reset();
}
}
HRESULT D3D11_CreateRenderTargets( d3d11_device_t *d3d_dev, ID3D11Resource *texture,
const d3d_format_t *cfg, ID3D11RenderTargetView *output[DXGI_MAX_RENDER_TARGET] )
const d3d_format_t *cfg, ComPtr<ID3D11RenderTargetView> output[DXGI_MAX_RENDER_TARGET] )
{
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
@ -127,8 +120,8 @@ HRESULT D3D11_CreateRenderTargets( d3d11_device_t *d3d_dev, ID3D11Resource *text
if (cfg->resourceFormat[i])
{
renderTargetViewDesc.Format = cfg->resourceFormat[i];
HRESULT hr = ID3D11Device_CreateRenderTargetView(d3d_dev->d3ddevice, texture,
&renderTargetViewDesc, &output[i]);
HRESULT hr = d3d_dev->d3ddevice->CreateRenderTargetView(texture,
&renderTargetViewDesc, output[i].GetAddressOf());
if (FAILED(hr))
{
return hr;
@ -139,7 +132,7 @@ HRESULT D3D11_CreateRenderTargets( d3d11_device_t *d3d_dev, ID3D11Resource *text
}
void D3D11_ClearRenderTargets(d3d11_device_t *d3d_dev, const d3d_format_t *cfg,
ID3D11RenderTargetView *targets[DXGI_MAX_RENDER_TARGET])
ComPtr<ID3D11RenderTargetView> targets[DXGI_MAX_RENDER_TARGET])
{
union DXGI_Color black[DXGI_MAX_RENDER_TARGET];
size_t colorCount[DXGI_MAX_RENDER_TARGET];
@ -147,11 +140,11 @@ void D3D11_ClearRenderTargets(d3d11_device_t *d3d_dev, const d3d_format_t *cfg,
if (colorCount[0])
{
ID3D11DeviceContext_ClearRenderTargetView( d3d_dev->d3dcontext, targets[0], black[0].array);
d3d_dev->d3dcontext->ClearRenderTargetView(targets[0].Get(), black[0].array);
}
if (colorCount[1])
{
ID3D11DeviceContext_ClearRenderTargetView( d3d_dev->d3dcontext, targets[1], black[1].array);
d3d_dev->d3dcontext->ClearRenderTargetView(targets[1].Get(), black[1].array);
}
}
@ -159,8 +152,8 @@ HRESULT (D3D11_CreateVertexShader)(vlc_object_t *obj, d3d_shader_blob *pVSBlob,
d3d11_device_t *d3d_dev, d3d11_vertex_shader_t *output)
{
HRESULT hr;
hr = ID3D11Device_CreateVertexShader(d3d_dev->d3ddevice, pVSBlob->buffer,
pVSBlob->buf_size, NULL, &output->shader);
hr = d3d_dev->d3ddevice->CreateVertexShader(pVSBlob->buffer, pVSBlob->buf_size,
NULL, output->shader.GetAddressOf());
if(FAILED(hr)) {
msg_Err(obj, "Failed to create the flat vertex shader. (hr=0x%lX)", hr);
@ -173,8 +166,8 @@ HRESULT (D3D11_CreateVertexShader)(vlc_object_t *obj, d3d_shader_blob *pVSBlob,
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
hr = ID3D11Device_CreateInputLayout(d3d_dev->d3ddevice, layout, 2, pVSBlob->buffer,
pVSBlob->buf_size, &output->layout);
hr = d3d_dev->d3ddevice->CreateInputLayout(layout, 2, pVSBlob->buffer,
pVSBlob->buf_size, output->layout.GetAddressOf());
if(FAILED(hr)) {
msg_Err(obj, "Failed to create the vertex input layout. (hr=0x%lX)", hr);
@ -188,16 +181,8 @@ error:
void D3D11_ReleaseVertexShader(d3d11_vertex_shader_t *shader)
{
if (shader->layout)
{
ID3D11InputLayout_Release(shader->layout);
shader->layout = NULL;
}
if (shader->shader)
{
ID3D11VertexShader_Release(shader->shader);
shader->shader = NULL;
}
shader->layout.Reset();
shader->shader.Reset();
}
HRESULT D3D11_CompileVertexShaderBlob(vlc_object_t *obj, const d3d_shader_compiler_t *compiler,

View File

@ -28,30 +28,32 @@
#include "../../video_chroma/d3d11_fmt.h"
#include <wrl/client.h>
/* Vertex Shader compiled sructures */
typedef struct {
ID3D11VertexShader *shader;
ID3D11InputLayout *layout;
} d3d11_vertex_shader_t;
struct d3d11_vertex_shader_t {
Microsoft::WRL::ComPtr<ID3D11VertexShader> shader;
Microsoft::WRL::ComPtr<ID3D11InputLayout> layout;
};
/* A Quad is texture that can be displayed in a rectangle */
typedef struct
struct d3d11_quad_t
{
picture_sys_d3d11_t picSys;
d3d_quad_t generic;
UINT resourceCount;
ID3D11Buffer *pVertexBuffer;
ID3D11Buffer *pIndexBuffer;
ID3D11Buffer *viewpointShaderConstant;
ID3D11Buffer *pPixelShaderConstants;
UINT PSConstantsCount;
ID3D11PixelShader *d3dpixelShader[DXGI_MAX_RENDER_TARGET];
ID3D11SamplerState *SamplerStates[2];
UINT resourceCount = 0;
Microsoft::WRL::ComPtr<ID3D11Buffer> vertexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> indexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> viewpointShaderConstant;
Microsoft::WRL::ComPtr<ID3D11Buffer> pPixelShaderConstants;
UINT PSConstantsCount = 0;
Microsoft::WRL::ComPtr<ID3D11PixelShader> d3dpixelShader[DXGI_MAX_RENDER_TARGET];
Microsoft::WRL::ComPtr<ID3D11SamplerState> SamplerStates[2];
D3D11_VIEWPORT cropViewport[DXGI_MAX_RENDER_TARGET];
PS_CONSTANT_BUFFER pConstants;
VS_PROJECTION_CONST vConstants;
} d3d11_quad_t;
};
HRESULT D3D11_CompilePixelShaderBlob(vlc_object_t *, const d3d_shader_compiler_t *,
d3d11_device_t *, const display_info_t *,
@ -72,10 +74,10 @@ HRESULT D3D11_CreateVertexShader(vlc_object_t *, d3d_shader_blob *, d3d11_device
#define D3D11_CreateVertexShader(a,b,c,d) D3D11_CreateVertexShader(VLC_OBJECT(a),b,c,d)
HRESULT D3D11_CreateRenderTargets(d3d11_device_t *, ID3D11Resource *, const d3d_format_t *,
ID3D11RenderTargetView *output[DXGI_MAX_RENDER_TARGET]);
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> output[DXGI_MAX_RENDER_TARGET]);
void D3D11_ClearRenderTargets(d3d11_device_t *, const d3d_format_t *,
ID3D11RenderTargetView *targets[DXGI_MAX_RENDER_TARGET]);
Microsoft::WRL::ComPtr<ID3D11RenderTargetView> targets[DXGI_MAX_RENDER_TARGET]);
void D3D11_ReleaseVertexShader(d3d11_vertex_shader_t *);

View File

@ -31,7 +31,7 @@
#include <vlc/libvlc_renderer_discoverer.h>
#include <vlc/libvlc_media_player.h>
#include <assert.h>
#include <cassert>
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0601 // _WIN32_WINNT_WIN7
# undef _WIN32_WINNT
@ -40,45 +40,44 @@
#include <windows.h>
#define COBJMACROS
#include <initguid.h>
#include <d3d11.h>
#include "dxgi_swapchain.h"
#include "d3d11_swapchain.h"
#include "d3d11_shaders.h"
#ifdef HAVE_DCOMP_H
# include "dcomp_wrapper.h"
#endif
#include <new>
using Microsoft::WRL::ComPtr;
struct d3d11_local_swapchain
{
struct dxgi_swapchain *sys;
struct dxgi_swapchain *sys = nullptr;
vlc_object_t *obj;
d3d11_device_t *d3d_dev;
vlc_object_t *obj = nullptr;
d3d11_device_t *d3d_dev = nullptr;
ID3D11RenderTargetView *swapchainTargetView[DXGI_MAX_RENDER_TARGET];
ComPtr<ID3D11RenderTargetView> swapchainTargetView[DXGI_MAX_RENDER_TARGET];
};
DEFINE_GUID(GUID_SWAPCHAIN_WIDTH, 0xf1b59347, 0x1643, 0x411a, 0xad, 0x6b, 0xc7, 0x80, 0x17, 0x7a, 0x06, 0xb6);
DEFINE_GUID(GUID_SWAPCHAIN_HEIGHT, 0x6ea976a0, 0x9d60, 0x4bb7, 0xa5, 0xa9, 0x7d, 0xd1, 0x18, 0x7f, 0xc9, 0xbd);
static bool UpdateSwapchain( struct d3d11_local_swapchain *display, const libvlc_video_render_cfg_t *cfg )
static bool UpdateSwapchain( d3d11_local_swapchain *display, const libvlc_video_render_cfg_t *cfg )
{
HRESULT hr;
D3D11_TEXTURE2D_DESC dsc = { 0 };
D3D11_TEXTURE2D_DESC dsc = { };
uint8_t bitsPerChannel = 0;
if ( display->swapchainTargetView[0] ) {
ID3D11Resource *res = NULL;
ID3D11RenderTargetView_GetResource( display->swapchainTargetView[0], &res );
if ( display->swapchainTargetView[0].Get() ) {
ComPtr<ID3D11Resource> res;
display->swapchainTargetView[0]->GetResource( res.GetAddressOf() );
if ( res )
{
ID3D11Texture2D_GetDesc( (ID3D11Texture2D*) res, &dsc );
ID3D11Resource_Release( res );
ComPtr<ID3D11Texture2D> res2d;
if (SUCCEEDED(res.As(&res2d)))
res2d->GetDesc( &dsc );
}
assert(DXGI_GetPixelFormat(display->sys)->formatTexture == dsc.Format);
bitsPerChannel = DXGI_GetPixelFormat(display->sys)->bitsPerChannel;
@ -89,22 +88,17 @@ static bool UpdateSwapchain( struct d3d11_local_swapchain *display, const libvlc
return true; /* nothing changed */
for ( size_t i = 0; i < ARRAY_SIZE( display->swapchainTargetView ); i++ )
{
if ( display->swapchainTargetView[i] ) {
ID3D11RenderTargetView_Release( display->swapchainTargetView[i] );
display->swapchainTargetView[i] = NULL;
}
}
display->swapchainTargetView[i].Reset();
const d3d_format_t *newPixelFormat = NULL;
#if VLC_WINSTORE_APP
IDXGISwapChain1 *dxgiswapChain = DXGI_GetSwapChain1(display->sys);
if (dxgiswapChain == NULL)
dxgiswapChain = (void*)(uintptr_t)var_InheritInteger(display->obj, "winrt-swapchain");
if (dxgiswapChain != NULL)
ComPtr<IDXGISwapChain1> dxgiswapChain = DXGI_GetSwapChain1(display->sys);
if (!dxgiswapChain.Get())
dxgiswapChain = static_cast<IDXGISwapChain1*>((void*)(uintptr_t)var_InheritInteger(display->obj, "winrt-swapchain"));
if (dxgiswapChain.Get())
{
DXGI_SWAP_CHAIN_DESC1 scd;
if (SUCCEEDED(IDXGISwapChain1_GetDesc1(dxgiswapChain, &scd)))
if (SUCCEEDED(dxgiswapChain->GetDesc1(&scd)))
{
for (const d3d_format_t *output_format = DxgiGetRenderFormatList();
output_format->name != NULL; ++output_format)
@ -135,35 +129,29 @@ static bool UpdateSwapchain( struct d3d11_local_swapchain *display, const libvlc
return false;
}
IDXGIDevice *pDXGIDevice = NULL;
hr = ID3D11Device_QueryInterface(display->d3d_dev->d3ddevice, &IID_IDXGIDevice, (void **)&pDXGIDevice);
ComPtr<IDXGIDevice> pDXGIDevice;
hr = display->d3d_dev->d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(pDXGIDevice.GetAddressOf()));
if (FAILED(hr)) {
return false;
}
IDXGIAdapter *dxgiadapter;
hr = IDXGIDevice_GetAdapter(pDXGIDevice, &dxgiadapter);
IDXGIDevice_Release(pDXGIDevice);
ComPtr<IDXGIAdapter> dxgiadapter;
hr = pDXGIDevice->GetAdapter(dxgiadapter.GetAddressOf());
if (FAILED(hr)) {
return false;
}
if (!DXGI_UpdateSwapChain( display->sys, dxgiadapter, (IUnknown*) display->d3d_dev->d3ddevice, newPixelFormat, cfg ))
{
IDXGIAdapter_Release(dxgiadapter);
if (!DXGI_UpdateSwapChain( display->sys, dxgiadapter.Get(), display->d3d_dev->d3ddevice, newPixelFormat, cfg ))
return false;
}
IDXGIAdapter_Release(dxgiadapter);
ID3D11Resource* pBackBuffer;
hr = IDXGISwapChain1_GetBuffer( DXGI_GetSwapChain1(display->sys), 0, &IID_ID3D11Resource, (LPVOID *) &pBackBuffer );
ComPtr<ID3D11Resource> pBackBuffer;
hr = DXGI_GetSwapChain1(display->sys)->GetBuffer( 0, IID_GRAPHICS_PPV_ARGS(pBackBuffer.GetAddressOf()) );
if ( FAILED( hr ) ) {
msg_Err( display->obj, "Could not get the backbuffer for the Swapchain. (hr=0x%lX)", hr );
return false;
}
hr = D3D11_CreateRenderTargets( display->d3d_dev, pBackBuffer,
hr = D3D11_CreateRenderTargets( display->d3d_dev, pBackBuffer.Get(),
DXGI_GetPixelFormat(display->sys), display->swapchainTargetView );
ID3D11Resource_Release( pBackBuffer );
if ( FAILED( hr ) ) {
msg_Err( display->obj, "Failed to create the target view. (hr=0x%lX)", hr );
return false;
@ -176,20 +164,14 @@ static bool UpdateSwapchain( struct d3d11_local_swapchain *display, const libvlc
void D3D11_LocalSwapchainCleanupDevice( void *opaque )
{
struct d3d11_local_swapchain *display = opaque;
for (size_t i=0; i < ARRAY_SIZE(display->swapchainTargetView); i++)
{
if (display->swapchainTargetView[i]) {
ID3D11RenderTargetView_Release(display->swapchainTargetView[i]);
display->swapchainTargetView[i] = NULL;
}
}
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
DXGI_LocalSwapchainCleanupDevice(display->sys);
delete display;
}
bool D3D11_LocalSwapchainUpdateOutput( void *opaque, const libvlc_video_render_cfg_t *cfg, libvlc_video_output_cfg_t *out )
{
struct d3d11_local_swapchain *display = opaque;
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
if ( !UpdateSwapchain( display, cfg ) )
return false;
DXGI_SwapchainUpdateOutput(display->sys, out);
@ -198,26 +180,26 @@ bool D3D11_LocalSwapchainUpdateOutput( void *opaque, const libvlc_video_render_c
void D3D11_LocalSwapchainSwap( void *opaque )
{
struct d3d11_local_swapchain *display = opaque;
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
DXGI_LocalSwapchainSwap( display->sys );
}
void D3D11_LocalSwapchainSetMetadata( void *opaque, libvlc_video_metadata_type_t type, const void *metadata )
{
struct d3d11_local_swapchain *display = opaque;
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
DXGI_LocalSwapchainSetMetadata( display->sys, type, metadata );
}
bool D3D11_LocalSwapchainWinstoreSize( void *opaque, uint32_t *width, uint32_t *height )
{
#if VLC_WINSTORE_APP
struct d3d11_local_swapchain *display = opaque;
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
/* legacy UWP mode, the width/height was set in GUID_SWAPCHAIN_WIDTH/HEIGHT */
UINT dataSize = sizeof(*width);
HRESULT hr = IDXGISwapChain1_GetPrivateData(DXGI_GetSwapChain1(display->sys), &GUID_SWAPCHAIN_WIDTH, &dataSize, width);
HRESULT hr = DXGI_GetSwapChain1(display->sys)->GetPrivateData(GUID_SWAPCHAIN_WIDTH, &dataSize, width);
if (SUCCEEDED(hr)) {
dataSize = sizeof(*height);
hr = IDXGISwapChain1_GetPrivateData(DXGI_GetSwapChain1(display->sys), &GUID_SWAPCHAIN_HEIGHT, &dataSize, height);
hr = DXGI_GetSwapChain1(display->sys)->GetPrivateData(GUID_SWAPCHAIN_HEIGHT, &dataSize, height);
return SUCCEEDED(hr);
}
#else
@ -228,7 +210,7 @@ bool D3D11_LocalSwapchainWinstoreSize( void *opaque, uint32_t *width, uint32_t *
bool D3D11_LocalSwapchainStartEndRendering( void *opaque, bool enter )
{
struct d3d11_local_swapchain *display = opaque;
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
if ( enter )
D3D11_ClearRenderTargets( display->d3d_dev, DXGI_GetPixelFormat(display->sys), display->swapchainTargetView );
@ -238,17 +220,17 @@ bool D3D11_LocalSwapchainStartEndRendering( void *opaque, bool enter )
bool D3D11_LocalSwapchainSelectPlane( void *opaque, size_t plane, void *out )
{
struct d3d11_local_swapchain *display = opaque;
if (!display->swapchainTargetView[plane])
d3d11_local_swapchain *display = static_cast<d3d11_local_swapchain *>(opaque);
if (!display->swapchainTargetView[plane].Get())
return false;
ID3D11RenderTargetView **output = out;
*output = display->swapchainTargetView[plane];
ID3D11RenderTargetView **output = static_cast<ID3D11RenderTargetView **>(out);
*output = display->swapchainTargetView[plane].Get();
return true;
}
void *D3D11_CreateLocalSwapchainHandleHwnd(vlc_object_t *o, HWND hwnd, d3d11_device_t *d3d_dev)
{
struct d3d11_local_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
d3d11_local_swapchain *display = new (std::nothrow) d3d11_local_swapchain();
if (unlikely(display == NULL))
return NULL;
@ -262,10 +244,10 @@ void *D3D11_CreateLocalSwapchainHandleHwnd(vlc_object_t *o, HWND hwnd, d3d11_dev
return display;
}
#ifdef HAVE_DCOMP_H
#if defined(HAVE_DCOMP_H) && !VLC_WINSTORE_APP
void *D3D11_CreateLocalSwapchainHandleDComp(vlc_object_t *o, void* dcompDevice, void* dcompVisual, d3d11_device_t *d3d_dev)
{
struct d3d11_local_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
d3d11_local_swapchain *display = new (std::nothrow) d3d11_local_swapchain();
if (unlikely(display == NULL))
return NULL;

View File

@ -29,7 +29,7 @@
#include "../../video_chroma/d3d11_fmt.h"
void *D3D11_CreateLocalSwapchainHandleHwnd(vlc_object_t *, HWND, d3d11_device_t *d3d_dev);
#ifdef HAVE_DCOMP_H
#if defined(HAVE_DCOMP_H) && !VLC_WINSTORE_APP
void *D3D11_CreateLocalSwapchainHandleDComp(vlc_object_t *, void* dcompDevice, void* dcompVisual, d3d11_device_t *d3d_dev);
#endif

View File

@ -23,6 +23,10 @@
#ifndef VLC_D3D_DYNAMIC_SHADER_H
#define VLC_D3D_DYNAMIC_SHADER_H
#ifdef __cplusplus
extern "C" {
#endif// __cplusplus
typedef struct
{
HINSTANCE compiler_dll; /* handle of the opened d3dcompiler dll */
@ -45,4 +49,8 @@ HRESULT D3D_CompileVertexShader(vlc_object_t *, const d3d_shader_compiler_t *,
D3D_FEATURE_LEVEL, bool flat,
d3d_shader_blob *);
#ifdef __cplusplus
}
#endif// __cplusplus
#endif /* VLC_D3D_DYNAMIC_SHADER_H */

View File

@ -29,6 +29,10 @@
#include <vlc_es.h>
#ifdef __cplusplus
extern "C" {
#endif// __cplusplus
#define DEFAULT_BRIGHTNESS 100
#define DEFAULT_SRGB_BRIGHTNESS 100
#define MAX_HLG_BRIGHTNESS 1000
@ -101,7 +105,7 @@ static inline void D3D_ShaderBlobRelease(d3d_shader_blob *blob)
{
if (blob->pf_release)
blob->pf_release(blob);
*blob = (d3d_shader_blob) { 0 };
*blob = (d3d_shader_blob) { };
}
float D3D_GetFormatLuminance(vlc_object_t *, const video_format_t *);
@ -118,4 +122,8 @@ bool D3D_SetupQuadData(vlc_object_t *, d3d_quad_t *, const RECT *, d3d_vertex_t*
void D3D_UpdateViewpoint(d3d_quad_t *, const vlc_viewpoint_t *, float f_sar);
#ifdef __cplusplus
}
#endif// __cplusplus
#endif /* VLC_D3D_SHADERS_H */

View File

@ -1,38 +0,0 @@
/*****************************************************************************
* Copyright (c) 2020 VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#undef WINAPI_FAMILY
#define WINAPI_FAMILY WINAPI_FAMILY_DESKTOP_APP
#include "dcomp_wrapper.h"
#include <dcomp.h>
HRESULT IDCompositionVisual_SetContent(void* opaque, IUnknown *content)
{
IDCompositionVisual* visual = (IDCompositionVisual*)opaque;
return visual->SetContent(content);
}
HRESULT IDCompositionDevice_Commit(void* opaque)
{
IDCompositionDevice* device = (IDCompositionDevice*)opaque;
return device->Commit();
}

View File

@ -1,35 +0,0 @@
/*****************************************************************************
* Copyright (c) 2020 VideoLAN
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
#ifndef VLC_DCOMP_WRAPPER_H_
#define VLC_DCOMP_WRAPPER_H_
#include <windows.h>
#include <unknwn.h>
#ifdef __cplusplus
extern "C" {
#endif
HRESULT IDCompositionVisual_SetContent(void* visual, IUnknown *content);
HRESULT IDCompositionDevice_Commit(void* device);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,7 +1,7 @@
/*****************************************************************************
* direct3d11.c: Windows Direct3D11 video output module
* direct3d11.cpp: Windows Direct3D11 video output module
*****************************************************************************
* Copyright (C) 2014-2015 VLC authors and VideoLAN
* Copyright (C) 2014-2021 VLC authors and VideoLAN
*
* Authors: Martell Malone <martellmalone@gmail.com>
* Steve Lhomme <robux4@gmail.com>
@ -40,11 +40,10 @@
#include <vlc/libvlc_renderer_discoverer.h>
#include <vlc/libvlc_media_player.h>
#include <assert.h>
#include <cassert>
#include <math.h>
#include <new>
#define COBJMACROS
#include <initguid.h>
#include <d3d11.h>
#ifdef HAVE_D3D11_4_H
#include <d3d11_4.h>
@ -62,6 +61,8 @@
#include "common.h"
#include "../../video_chroma/copy.h"
using Microsoft::WRL::ComPtr;
static int Open(vout_display_t *, const vout_display_cfg_t *,
video_format_t *, vlc_video_context *);
static void Close(vout_display_t *);
@ -96,20 +97,20 @@ typedef struct vout_display_sys_t
int log_level;
/* Sensors */
void *p_sensors;
void *p_sensors = NULL;
display_info_t display;
display_info_t display = {};
d3d11_device_t *d3d_dev;
d3d11_decoder_device_t *local_d3d_dev; // when opened without a video context
d3d_shader_compiler_t shaders;
d3d11_device_t *d3d_dev = NULL;
d3d11_decoder_device_t *local_d3d_dev = NULL; // when opened without a video context
d3d_shader_compiler_t shaders = {};
d3d11_quad_t picQuad;
#ifdef HAVE_D3D11_4_H
ID3D11Fence *d3dRenderFence;
ID3D11DeviceContext4 *d3dcontext4;
UINT64 renderFence;
HANDLE renderFinished;
ComPtr<ID3D11Fence> d3dRenderFence;
ComPtr<ID3D11DeviceContext4> d3dcontext4;
UINT64 renderFence = 0;
HANDLE renderFinished = NULL;
#endif
picture_sys_d3d11_t stagingSys;
@ -120,16 +121,16 @@ typedef struct vout_display_sys_t
/* copy from the decoder pool into picSquad before display
* Uses a Texture2D with slices rather than a Texture2DArray for the decoder */
bool legacy_shader;
bool legacy_shader = false;
// SPU
vlc_fourcc_t pSubpictureChromas[2];
d3d11_quad_t regionQuad;
int d3dregion_count;
picture_t **d3dregions;
d3d11_quad_t regionQuad;
int d3dregion_count = 0;
picture_t **d3dregions = NULL;
/* outside rendering */
void *outside_opaque;
void *outside_opaque = NULL;
libvlc_video_update_output_cb updateOutputCb;
libvlc_video_swap_cb swapCb;
libvlc_video_makeCurrent_cb startEndRenderingCb;
@ -156,7 +157,7 @@ static int Control(vout_display_t *, int);
static int UpdateDisplayFormat(vout_display_t *vd, const video_format_t *fmt)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
libvlc_video_render_cfg_t cfg;
cfg.width = vd->cfg->display.width;
@ -204,7 +205,7 @@ static int UpdateDisplayFormat(vout_display_t *vd, const video_format_t *fmt)
return VLC_EGENERIC;
}
display_info_t new_display = { 0 };
display_info_t new_display = { };
for (const d3d_format_t *output_format = DxgiGetRenderFormatList();
output_format->name != NULL; ++output_format)
@ -228,7 +229,7 @@ static int UpdateDisplayFormat(vout_display_t *vd, const video_format_t *fmt)
new_display.b_full_range = out.full_range;
/* guestimate the display peak luminance */
switch (out.transfer)
switch (new_display.transfer)
{
case TRANSFER_FUNC_LINEAR:
case TRANSFER_FUNC_SRGB:
@ -263,27 +264,25 @@ static int UpdateDisplayFormat(vout_display_t *vd, const video_format_t *fmt)
static void UpdateSize(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
msg_Dbg(vd, "Detected size change %dx%d", sys->area.place.width,
sys->area.place.height);
UpdateDisplayFormat(vd, vd->fmt);
RECT rect_dst = {
.left = sys->area.place.x,
.right = sys->area.place.x + sys->area.place.width,
.top = sys->area.place.y,
.bottom = sys->area.place.y + sys->area.place.height
};
RECT rect_dst;
rect_dst.left = sys->area.place.x;
rect_dst.right = sys->area.place.x + sys->area.place.width;
rect_dst.top = sys->area.place.y;
rect_dst.bottom = sys->area.place.y + sys->area.place.height;
D3D11_UpdateViewport( &sys->picQuad, &rect_dst, sys->display.pixelFormat );
RECT source_rect = {
.left = vd->source->i_x_offset,
.right = vd->source->i_x_offset + vd->source->i_visible_width,
.top = vd->source->i_y_offset,
.bottom = vd->source->i_y_offset + vd->source->i_visible_height,
};
RECT source_rect;
source_rect.left = vd->source->i_x_offset;
source_rect.right = vd->source->i_x_offset + vd->source->i_visible_width;
source_rect.top = vd->source->i_y_offset;
source_rect.bottom = vd->source->i_y_offset + vd->source->i_visible_height;
d3d11_device_lock( sys->d3d_dev );
D3D11_UpdateQuadPosition(vd, sys->d3d_dev, &sys->picQuad, &source_rect,
@ -303,8 +302,8 @@ static void UpdateSize(vout_display_t *vd)
static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *viewpoint)
{
vout_display_sys_t *sys = vd->sys;
if ( sys->picQuad.viewpointShaderConstant )
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
if ( sys->picQuad.viewpointShaderConstant.Get() )
{
d3d11_device_lock( sys->d3d_dev );
D3D11_UpdateViewpoint( vd, sys->d3d_dev, &sys->picQuad, viewpoint,
@ -316,7 +315,7 @@ static int SetViewpoint(vout_display_t *vd, const vlc_viewpoint_t *viewpoint)
static int UpdateStaging(vout_display_t *vd, const video_format_t *fmt)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
#ifdef HAVE_ID3D11VIDEODECODER
if (sys->legacy_shader)
{
@ -359,9 +358,12 @@ static const struct vlc_display_operations ops = {
static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
video_format_t *fmtp, vlc_video_context *context)
{
vout_display_sys_t *sys = vd->sys = vlc_obj_calloc(VLC_OBJECT(vd), 1, sizeof(vout_display_sys_t));
vout_display_sys_t *sys = new (std::nothrow) vout_display_sys_t();
if (!sys)
return VLC_ENOMEM;
vd->sys = sys;
d3d11_decoder_device_t *dev_sys = NULL;
int ret = D3D_InitShaderCompiler(VLC_OBJECT(vd), &sys->shaders);
if (ret != VLC_SUCCESS)
@ -370,13 +372,13 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
CommonInit(&sys->area);
sys->outside_opaque = var_InheritAddress( vd, "vout-cb-opaque" );
sys->updateOutputCb = var_InheritAddress( vd, "vout-cb-update-output" );
sys->swapCb = var_InheritAddress( vd, "vout-cb-swap" );
sys->startEndRenderingCb = var_InheritAddress( vd, "vout-cb-make-current" );
sys->sendMetadataCb = var_InheritAddress( vd, "vout-cb-metadata" );
sys->selectPlaneCb = var_InheritAddress( vd, "vout-cb-select-plane" );
sys->updateOutputCb = (libvlc_video_update_output_cb)var_InheritAddress( vd, "vout-cb-update-output" );
sys->swapCb = (libvlc_video_swap_cb)var_InheritAddress( vd, "vout-cb-swap" );
sys->startEndRenderingCb = (libvlc_video_makeCurrent_cb)var_InheritAddress( vd, "vout-cb-make-current" );
sys->sendMetadataCb = (libvlc_video_frameMetadata_cb)var_InheritAddress( vd, "vout-cb-metadata" );
sys->selectPlaneCb = (libvlc_video_output_select_plane_cb)var_InheritAddress( vd, "vout-cb-select-plane" );
d3d11_decoder_device_t *dev_sys = GetD3D11OpaqueContext( context );
dev_sys = GetD3D11OpaqueContext( context );
if ( dev_sys == NULL )
{
// No d3d11 device, we create one
@ -402,7 +404,7 @@ static int Open(vout_display_t *vd, const vout_display_cfg_t *cfg,
#endif /* !VLC_WINSTORE_APP */
/* use our internal swapchain callbacks */
#ifdef HAVE_DCOMP_H
#if defined(HAVE_DCOMP_H) && !VLC_WINSTORE_APP
if (cfg->window->type == VOUT_WINDOW_TYPE_DCOMP)
sys->outside_opaque = D3D11_CreateLocalSwapchainHandleDComp(VLC_OBJECT(vd), cfg->window->display.dcomp_device, cfg->window->handle.dcomp_visual, sys->d3d_dev);
else
@ -455,18 +457,18 @@ error:
static void Close(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
D3D_ReleaseShaderCompiler(&sys->shaders);
Direct3D11Close(vd);
#if !VLC_WINSTORE_APP
UnhookWindowsSensors(sys->p_sensors);
CommonWindowClean(&sys->sys);
#endif
Direct3D11Close(vd);
delete sys;
}
static int Control(vout_display_t *vd, int query)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
int res = CommonControl( vd, &sys->area, &sys->sys, query );
if ( sys->area.place_changed )
@ -480,7 +482,7 @@ static int Control(vout_display_t *vd, int query)
static bool SelectRenderPlane(void *opaque, size_t plane, ID3D11RenderTargetView **targetView)
{
vout_display_sys_t *sys = opaque;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(opaque);
if (!sys->selectPlaneCb)
{
*targetView = NULL;
@ -493,7 +495,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
vlc_tick_t date)
{
VLC_UNUSED(date);
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
if (sys->picQuad.generic.textureFormat->formatTexture == DXGI_FORMAT_UNKNOWN)
{
@ -503,17 +505,17 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
bool b_mapped = true;
for (i = 0; i < picture->i_planes; i++) {
hr = ID3D11DeviceContext_Map(sys->d3d_dev->d3dcontext, sys->stagingSys.resource[i],
hr = sys->d3d_dev->d3dcontext->Map(sys->stagingSys.resource[i],
0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( unlikely(FAILED(hr)) )
{
while (i-- > 0)
ID3D11DeviceContext_Unmap(sys->d3d_dev->d3dcontext, sys->stagingSys.resource[i], 0);
sys->d3d_dev->d3dcontext->Unmap(sys->stagingSys.resource[i], 0);
b_mapped = false;
break;
}
sys->stagingPlanes[i].i_pitch = mappedResource.RowPitch;
sys->stagingPlanes[i].p_pixels = mappedResource.pData;
sys->stagingPlanes[i].p_pixels = static_cast<uint8_t*>(mappedResource.pData);
}
if (b_mapped)
@ -522,7 +524,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
plane_CopyPixels(&sys->stagingPlanes[i], &picture->p[i]);
for (i = 0; i < picture->i_planes; i++)
ID3D11DeviceContext_Unmap(sys->d3d_dev->d3dcontext, sys->stagingSys.resource[i], 0);
sys->d3d_dev->d3dcontext->Unmap(sys->stagingSys.resource[i], 0);
}
}
else if (!is_d3d11_opaque(picture->format.i_chroma))
@ -530,13 +532,13 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT hr;
hr = ID3D11DeviceContext_Map(sys->d3d_dev->d3dcontext, sys->stagingSys.resource[0],
hr = sys->d3d_dev->d3dcontext->Map(sys->stagingSys.resource[0],
0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( unlikely(FAILED(hr)) )
msg_Err(vd, "Failed to map the %4.4s staging picture. (hr=0x%lX)", (const char*)&picture->format.i_chroma, hr);
else
{
uint8_t *buf = mappedResource.pData;
uint8_t *buf = static_cast<uint8_t*>(mappedResource.pData);
for (int i = 0; i < picture->i_planes; i++)
{
sys->stagingPlanes[i].i_pitch = mappedResource.RowPitch;
@ -547,7 +549,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
buf += sys->stagingPlanes[i].i_pitch * sys->stagingPlanes[i].i_lines;
}
ID3D11DeviceContext_Unmap(sys->d3d_dev->d3dcontext, sys->stagingSys.resource[0], 0);
sys->d3d_dev->d3dcontext->Unmap(sys->stagingSys.resource[0], 0);
}
}
else
@ -556,16 +558,15 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
if (sys->legacy_shader) {
D3D11_TEXTURE2D_DESC srcDesc,texDesc;
ID3D11Texture2D_GetDesc(p_sys->texture[KNOWN_DXGI_INDEX], &srcDesc);
ID3D11Texture2D_GetDesc(sys->stagingSys.texture[0], &texDesc);
D3D11_BOX box = {
.top = 0,
.bottom = __MIN(srcDesc.Height, texDesc.Height),
.left = 0,
.right = __MIN(srcDesc.Width, texDesc.Width),
.back = 1,
};
ID3D11DeviceContext_CopySubresourceRegion(sys->d3d_dev->d3dcontext,
p_sys->texture[KNOWN_DXGI_INDEX]->GetDesc(&srcDesc);
sys->stagingSys.texture[0]->GetDesc(&texDesc);
D3D11_BOX box;
box.top = 0;
box.bottom = __MIN(srcDesc.Height, texDesc.Height);
box.left = 0;
box.right = __MIN(srcDesc.Width, texDesc.Width);
box.back = 1;
sys->d3d_dev->d3dcontext->CopySubresourceRegion(
sys->stagingSys.resource[KNOWN_DXGI_INDEX],
0, 0, 0, 0,
p_sys->resource[KNOWN_DXGI_INDEX],
@ -574,7 +575,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
else
{
D3D11_TEXTURE2D_DESC texDesc;
ID3D11Texture2D_GetDesc(p_sys->texture[0], &texDesc);
p_sys->texture[0]->GetDesc(&texDesc);
if (texDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE)
{
/* for performance reason we don't want to allocate this during
@ -634,7 +635,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
}
#ifdef HAVE_D3D11_4_H
if (sys->d3dcontext4)
if (sys->d3dcontext4.Get())
{
vlc_tick_t render_start;
if (sys->log_level >= 4)
@ -645,8 +646,8 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
sys->renderFence++;
ResetEvent(sys->renderFinished);
ID3D11Fence_SetEventOnCompletion(sys->d3dRenderFence, sys->renderFence, sys->renderFinished);
ID3D11DeviceContext4_Signal(sys->d3dcontext4, sys->d3dRenderFence, sys->renderFence);
sys->d3dRenderFence->SetEventOnCompletion(sys->renderFence, sys->renderFinished);
sys->d3dcontext4->Signal(sys->d3dRenderFence.Get(), sys->renderFence);
WaitForSingleObject(sys->renderFinished, INFINITE);
if (sys->log_level >= 4)
@ -658,7 +659,7 @@ static void PreparePicture(vout_display_t *vd, picture_t *picture, subpicture_t
static void Prepare(vout_display_t *vd, picture_t *picture,
subpicture_t *subpicture, vlc_tick_t date)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
d3d11_device_lock( sys->d3d_dev );
#if VLC_WINSTORE_APP
@ -704,7 +705,7 @@ static void Prepare(vout_display_t *vd, picture_t *picture,
static void Display(vout_display_t *vd, picture_t *picture)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
VLC_UNUSED(picture);
d3d11_device_lock( sys->d3d_dev );
@ -714,7 +715,7 @@ static void Display(vout_display_t *vd, picture_t *picture)
static const d3d_format_t *GetDirectRenderingFormat(vout_display_t *vd, vlc_fourcc_t i_src_chroma)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
UINT supportFlags = D3D11_FORMAT_SUPPORT_SHADER_LOAD;
if (is_d3d11_opaque(i_src_chroma))
@ -725,7 +726,7 @@ static const d3d_format_t *GetDirectRenderingFormat(vout_display_t *vd, vlc_four
static const d3d_format_t *GetDirectDecoderFormat(vout_display_t *vd, vlc_fourcc_t i_src_chroma)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
UINT supportFlags = D3D11_FORMAT_SUPPORT_DECODER_OUTPUT;
return FindD3D11Format( vd, sys->d3d_dev, i_src_chroma, DXGI_RGB_FORMAT|DXGI_YUV_FORMAT, 0, 0, 0,
@ -738,7 +739,7 @@ static const d3d_format_t *GetDisplayFormatByDepth(vout_display_t *vd, uint8_t b
bool from_processor,
int rgb_yuv)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
UINT supportFlags = D3D11_FORMAT_SUPPORT_SHADER_LOAD;
if (from_processor)
@ -750,7 +751,7 @@ static const d3d_format_t *GetDisplayFormatByDepth(vout_display_t *vd, uint8_t b
static const d3d_format_t *GetBlendableFormat(vout_display_t *vd, vlc_fourcc_t i_src_chroma)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
UINT supportFlags = D3D11_FORMAT_SUPPORT_SHADER_LOAD | D3D11_FORMAT_SUPPORT_BLENDABLE;
return FindD3D11Format( vd, sys->d3d_dev, i_src_chroma, DXGI_RGB_FORMAT|DXGI_YUV_FORMAT, 0, 0, 0, DXGI_CHROMA_CPU, supportFlags );
@ -758,7 +759,7 @@ static const d3d_format_t *GetBlendableFormat(vout_display_t *vd, vlc_fourcc_t i
static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp, vlc_video_context *vctx)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
video_format_t fmt;
video_format_Copy(&fmt, vd->source);
int err = SetupOutputFormat(vd, &fmt, vctx);
@ -825,7 +826,7 @@ static int Direct3D11Open(vout_display_t *vd, video_format_t *fmtp, vlc_video_co
static int SetupOutputFormat(vout_display_t *vd, video_format_t *fmt, vlc_video_context *vctx)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
d3d11_video_context_t *vtcx_sys = GetD3D11ContextPrivate(vctx);
if (vtcx_sys != NULL &&
@ -951,7 +952,7 @@ static int SetupOutputFormat(vout_display_t *vd, video_format_t *fmt, vlc_video_
static void Direct3D11Close(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
Direct3D11DestroyResources(vd);
@ -966,7 +967,7 @@ static void Direct3D11Close(vout_display_t *vd)
static bool CanUseTextureArray(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
#ifndef HAVE_ID3D11VIDEODECODER
(void) vd;
@ -1000,7 +1001,7 @@ static bool CanUseTextureArray(vout_display_t *vd)
static bool BogusZeroCopy(const vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
if (sys->d3d_dev->adapterDesc.VendorId != GPU_MANUFACTURER_AMD)
return false;
@ -1025,13 +1026,13 @@ static bool BogusZeroCopy(const vout_display_t *vd)
TODO : seperate out into smaller functions like createshaders */
static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_format_t *fmt)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
HRESULT hr;
sys->legacy_shader = sys->d3d_dev->feature_level < D3D_FEATURE_LEVEL_10_0 || !CanUseTextureArray(vd) ||
BogusZeroCopy(vd) || !is_d3d11_opaque(fmt->i_chroma);
d3d_shader_blob pPSBlob[DXGI_MAX_RENDER_TARGET] = { 0 };
d3d_shader_blob pPSBlob[DXGI_MAX_RENDER_TARGET] = { };
hr = D3D11_CompilePixelShaderBlob(vd, &sys->shaders, sys->d3d_dev,
&sys->display, fmt->transfer,
fmt->color_range == COLOR_RANGE_FULL,
@ -1061,12 +1062,11 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
return VLC_EGENERIC;
}
RECT source_rect = {
.left = fmt->i_x_offset,
.right = fmt->i_x_offset + fmt->i_visible_width,
.top = fmt->i_y_offset,
.bottom = fmt->i_y_offset + fmt->i_visible_height,
};
RECT source_rect;
source_rect.left = fmt->i_x_offset;
source_rect.right = fmt->i_x_offset + fmt->i_visible_width;
source_rect.top = fmt->i_y_offset;
source_rect.bottom = fmt->i_y_offset + fmt->i_visible_height;
if (!D3D11_UpdateQuadPosition(vd, sys->d3d_dev, &sys->picQuad, &source_rect, vd->source->orientation))
{
msg_Err(vd, "Could not set quad picture position.");
@ -1079,12 +1079,10 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
(float) vd->cfg->display.width / vd->cfg->display.height );
if (is_d3d11_opaque(fmt->i_chroma)) {
ID3D10Multithread *pMultithread;
hr = ID3D11Device_QueryInterface( sys->d3d_dev->d3ddevice, &IID_ID3D10Multithread, (void **)&pMultithread);
if (SUCCEEDED(hr)) {
ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
ID3D10Multithread_Release(pMultithread);
}
ComPtr<ID3D10Multithread> pMultithread;
hr = sys->d3d_dev->d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(pMultithread.GetAddressOf()));
if (SUCCEEDED(hr))
pMultithread->SetMultithreadProtected(TRUE);
}
return UpdateStaging(vd, fmt);
@ -1094,34 +1092,23 @@ static int Direct3D11CreateFormatResources(vout_display_t *vd, const video_forma
static HRESULT InitRenderFence(vout_display_sys_t *sys)
{
HRESULT hr;
ComPtr<ID3D11Device5> d3ddev5;
hr = sys->d3d_dev->d3ddevice->QueryInterface(IID_GRAPHICS_PPV_ARGS(d3ddev5.GetAddressOf()));
if (FAILED(hr))
goto error;
hr = d3ddev5->CreateFence(sys->renderFence, D3D11_FENCE_FLAG_NONE, IID_GRAPHICS_PPV_ARGS(sys->d3dRenderFence.GetAddressOf()));
if (FAILED(hr))
goto error;
hr = sys->d3d_dev->d3dcontext->QueryInterface(IID_GRAPHICS_PPV_ARGS(sys->d3dcontext4.GetAddressOf()));
if (FAILED(hr))
goto error;
sys->renderFinished = CreateEvent(NULL, TRUE, FALSE, NULL);
if (unlikely(sys->renderFinished == NULL))
return S_FALSE;
ID3D11Device5 *d3ddev5 = NULL;
hr = ID3D11DeviceContext_QueryInterface(sys->d3d_dev->d3dcontext, &IID_ID3D11DeviceContext4, (void**)&sys->d3dcontext4);
if (FAILED(hr))
goto error;
hr = ID3D11Device_QueryInterface(sys->d3d_dev->d3ddevice, &IID_ID3D11Device5, (void**)&d3ddev5);
if (FAILED(hr))
goto error;
hr = ID3D11Device5_CreateFence(d3ddev5, sys->renderFence, D3D11_FENCE_FLAG_NONE, &IID_ID3D11Fence, (void**)&sys->d3dRenderFence);
if (FAILED(hr))
goto error;
ID3D11Device5_Release(d3ddev5);
return hr;
return S_OK;
error:
if (d3ddev5)
ID3D11Device5_Release(d3ddev5);
if (sys->d3dRenderFence)
{
ID3D11Fence_Release(sys->d3dRenderFence);
sys->d3dRenderFence = NULL;
}
if (sys->d3dcontext4)
{
ID3D11DeviceContext4_Release(sys->d3dcontext4);
sys->d3dcontext4 = NULL;
}
sys->d3dRenderFence.Reset();
sys->d3dcontext4.Reset();
CloseHandle(sys->renderFinished);
return hr;
}
@ -1129,7 +1116,7 @@ error:
static int Direct3D11CreateGenericResources(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
HRESULT hr;
#ifdef HAVE_D3D11_4_H
@ -1140,8 +1127,8 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
}
#endif
ID3D11BlendState *pSpuBlendState;
D3D11_BLEND_DESC spuBlendDesc = { 0 };
ComPtr<ID3D11BlendState> pSpuBlendState;
D3D11_BLEND_DESC spuBlendDesc = { };
spuBlendDesc.RenderTarget[0].BlendEnable = TRUE;
spuBlendDesc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL;
/* output colors */
@ -1153,31 +1140,27 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
spuBlendDesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; /* keep source intact */
spuBlendDesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; /* discard */
hr = ID3D11Device_CreateBlendState(sys->d3d_dev->d3ddevice, &spuBlendDesc, &pSpuBlendState);
hr = sys->d3d_dev->d3ddevice->CreateBlendState(&spuBlendDesc, pSpuBlendState.GetAddressOf());
if (FAILED(hr)) {
msg_Err(vd, "Could not create SPU blend state. (hr=0x%lX)", hr);
return VLC_EGENERIC;
}
ID3D11DeviceContext_OMSetBlendState(sys->d3d_dev->d3dcontext, pSpuBlendState, NULL, 0xFFFFFFFF);
ID3D11BlendState_Release(pSpuBlendState);
sys->d3d_dev->d3dcontext->OMSetBlendState(pSpuBlendState.Get(), NULL, 0xFFFFFFFF);
/* disable depth testing as we're only doing 2D
* see https://msdn.microsoft.com/en-us/library/windows/desktop/bb205074%28v=vs.85%29.aspx
* see http://rastertek.com/dx11tut11.html
*/
D3D11_DEPTH_STENCIL_DESC stencilDesc;
ZeroMemory(&stencilDesc, sizeof(stencilDesc));
D3D11_DEPTH_STENCIL_DESC stencilDesc = { };
ID3D11DepthStencilState *pDepthStencilState;
hr = ID3D11Device_CreateDepthStencilState(sys->d3d_dev->d3ddevice, &stencilDesc, &pDepthStencilState );
if (SUCCEEDED(hr)) {
ID3D11DeviceContext_OMSetDepthStencilState(sys->d3d_dev->d3dcontext, pDepthStencilState, 0);
ID3D11DepthStencilState_Release(pDepthStencilState);
}
ComPtr<ID3D11DepthStencilState> pDepthStencilState;
hr = sys->d3d_dev->d3ddevice->CreateDepthStencilState(&stencilDesc, pDepthStencilState.GetAddressOf() );
if (SUCCEEDED(hr))
sys->d3d_dev->d3dcontext->OMSetDepthStencilState(pDepthStencilState.Get(), 0);
if (sys->regionQuad.generic.textureFormat != NULL)
{
d3d_shader_blob pPSBlob[DXGI_MAX_RENDER_TARGET] = { 0 };
d3d_shader_blob pPSBlob[DXGI_MAX_RENDER_TARGET] = { };
hr = D3D11_CompilePixelShaderBlob(vd, &sys->shaders, sys->d3d_dev,
&sys->display, TRANSFER_FUNC_SRGB, true,
&sys->regionQuad, pPSBlob);
@ -1195,7 +1178,7 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
}
}
d3d_shader_blob VSBlob = { 0 };
d3d_shader_blob VSBlob = { };
hr = D3D11_CompileVertexShaderBlob(VLC_OBJECT(vd), &sys->shaders, sys->d3d_dev, true, &VSBlob);
if(FAILED(hr)) {
msg_Err(vd, "Failed to compile the flat vertex shader. (hr=0x%lX)", hr);
@ -1219,12 +1202,11 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
return VLC_EGENERIC;
}
RECT rect_dst = {
.left = sys->area.place.x,
.right = sys->area.place.x + sys->area.place.width,
.top = sys->area.place.y,
.bottom = sys->area.place.y + sys->area.place.height
};
RECT rect_dst;
rect_dst.left = sys->area.place.x;
rect_dst.right = sys->area.place.x + sys->area.place.width;
rect_dst.top = sys->area.place.y;
rect_dst.bottom = sys->area.place.y + sys->area.place.height;
D3D11_UpdateViewport( &sys->picQuad, &rect_dst, sys->display.pixelFormat );
@ -1243,7 +1225,7 @@ static int Direct3D11CreateGenericResources(vout_display_t *vd)
static void Direct3D11DestroyResources(vout_display_t *vd)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
D3D11_ReleaseQuad(&sys->picQuad);
Direct3D11DeleteRegions(sys->d3dregion_count, sys->d3dregions);
@ -1256,12 +1238,10 @@ static void Direct3D11DestroyResources(vout_display_t *vd)
D3D11_ReleaseVertexShader(&sys->projectionVShader);
#ifdef HAVE_D3D11_4_H
if (sys->d3dcontext4)
if (sys->d3dcontext4.Get())
{
ID3D11Fence_Release(sys->d3dRenderFence);
sys->d3dRenderFence = NULL;
ID3D11DeviceContext4_Release(sys->d3dcontext4);
sys->d3dcontext4 = NULL;
sys->d3dRenderFence.Reset();
sys->d3dcontext4.Reset();
CloseHandle(sys->renderFinished);
sys->renderFinished = NULL;
}
@ -1288,7 +1268,7 @@ static void DestroyPictureQuad(picture_t *p_picture)
static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_count,
picture_t ***region, subpicture_t *subpicture)
{
vout_display_sys_t *sys = vd->sys;
vout_display_sys_t *sys = static_cast<vout_display_sys_t *>(vd->sys);
D3D11_MAPPED_SUBRESOURCE mappedResource;
D3D11_TEXTURE2D_DESC texDesc;
HRESULT hr;
@ -1301,7 +1281,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
for (subpicture_region_t *r = subpicture->p_region; r; r = r->p_next)
count++;
*region = calloc(count, sizeof(picture_t *));
*region = static_cast<picture_t**>(calloc(count, sizeof(picture_t *)));
if (unlikely(*region==NULL))
return VLC_ENOMEM;
*subpicture_region_count = count;
@ -1314,7 +1294,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
for (int j = 0; j < sys->d3dregion_count; j++) {
picture_t *cache = sys->d3dregions[j];
if (cache != NULL && ((d3d11_quad_t *) cache->p_sys)->picSys.texture[KNOWN_DXGI_INDEX]) {
ID3D11Texture2D_GetDesc( ((d3d11_quad_t *) cache->p_sys)->picSys.texture[KNOWN_DXGI_INDEX], &texDesc );
((d3d11_quad_t *) cache->p_sys)->picSys.texture[KNOWN_DXGI_INDEX]->GetDesc(&texDesc );
if (texDesc.Format == sys->regionQuad.generic.textureFormat->formatTexture &&
texDesc.Width == r->p_picture->format.i_width &&
texDesc.Height == r->p_picture->format.i_height) {
@ -1328,10 +1308,10 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
picture_t *quad_picture = (*region)[i];
d3d11_quad_t *quad;
if (quad_picture != NULL)
quad = quad_picture->p_sys;
quad = static_cast<d3d11_quad_t*>(quad_picture->p_sys);
else
{
d3d11_quad_t *d3dquad = calloc(1, sizeof(*d3dquad));
d3d11_quad_t *d3dquad = static_cast<d3d11_quad_t *>(calloc(1, sizeof(*d3dquad)));
if (unlikely(d3dquad==NULL)) {
continue;
}
@ -1341,7 +1321,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
r->fmt.i_visible_width, r->fmt.i_visible_height);
for (int j=0; j<DXGI_MAX_SHADER_VIEW; j++)
if (d3dquad->picSys.texture[j])
ID3D11Texture2D_Release(d3dquad->picSys.texture[j]);
d3dquad->picSys.texture[j]->Release();
free(d3dquad);
continue;
}
@ -1392,17 +1372,17 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
if (sys->regionQuad.d3dpixelShader[j])
{
d3dquad->d3dpixelShader[j] = sys->regionQuad.d3dpixelShader[j];
ID3D11PixelShader_AddRef(d3dquad->d3dpixelShader[j]);
d3dquad->d3dpixelShader[j]->AddRef();
}
}
}
hr = ID3D11DeviceContext_Map(sys->d3d_dev->d3dcontext, ((d3d11_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
hr = sys->d3d_dev->d3dcontext->Map(((d3d11_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if( SUCCEEDED(hr) ) {
err = picture_UpdatePlanes(quad_picture, mappedResource.pData, mappedResource.RowPitch);
err = picture_UpdatePlanes(quad_picture, static_cast<uint8_t*>(mappedResource.pData), mappedResource.RowPitch);
if (err != VLC_SUCCESS) {
msg_Err(vd, "Failed to set the buffer on the SPU picture" );
ID3D11DeviceContext_Unmap(sys->d3d_dev->d3dcontext, ((d3d11_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0);
sys->d3d_dev->d3dcontext->Unmap(((d3d11_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0);
picture_Release(quad_picture);
if ((*region)[i] == quad_picture)
(*region)[i] = NULL;
@ -1411,7 +1391,7 @@ static int Direct3D11MapSubpicture(vout_display_t *vd, int *subpicture_region_co
picture_CopyPixels(quad_picture, r->p_picture);
ID3D11DeviceContext_Unmap(sys->d3d_dev->d3dcontext, ((d3d11_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0);
sys->d3d_dev->d3dcontext->Unmap(((d3d11_quad_t *) quad_picture->p_sys)->picSys.resource[KNOWN_DXGI_INDEX], 0);
} else {
msg_Err(vd, "Failed to map the SPU texture (hr=0x%lX)", hr );
picture_Release(quad_picture);

View File

@ -25,7 +25,7 @@
# include "config.h"
#endif
#include <assert.h>
#include <cassert>
#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0601 // _WIN32_WINNT_WIN7
# undef _WIN32_WINNT
@ -34,10 +34,8 @@
#include <vlc_es.h>
#define COBJMACROS
#ifdef HAVE_DCOMP_H
# include "dcomp_wrapper.h"
#if defined(HAVE_DCOMP_H) && !VLC_WINSTORE_APP
# include <dcomp.h>
#endif
#include <initguid.h>
@ -49,6 +47,12 @@
#include "../../video_chroma/dxgi_fmt.h"
#include <new>
#include <wrl/client.h>
using Microsoft::WRL::ComPtr;
typedef enum video_color_axis {
COLOR_AXIS_RGB,
COLOR_AXIS_YCBCR,
@ -71,30 +75,30 @@ typedef struct {
struct dxgi_swapchain
{
vlc_object_t *obj;
vlc_object_t *obj = nullptr;
const d3d_format_t *pixelFormat;
const dxgi_color_space *colorspace;
const d3d_format_t *pixelFormat = nullptr;
const dxgi_color_space *colorspace = nullptr;
swapchain_surface_type swapchainSurfaceType;
union {
#if !VLC_WINSTORE_APP
union {
HWND hwnd;
#endif /* !VLC_WINSTORE_APP */
#ifdef HAVE_DCOMP_H
#if defined(HAVE_DCOMP_H)
struct {
void* device; // IDCompositionDevice
void* visual; // IDCompositionVisual
IDCompositionDevice *device;
IDCompositionVisual *visual;
} dcomp;
#endif // HAVE_DCOMP_H
} swapchainSurface;
#endif /* !VLC_WINSTORE_APP */
IDXGISwapChain1 *dxgiswapChain; /* DXGI 1.2 swap chain */
IDXGISwapChain4 *dxgiswapChain4; /* DXGI 1.5 for HDR metadata */
ComPtr<IDXGISwapChain1> dxgiswapChain; /* DXGI 1.2 swap chain */
ComPtr<IDXGISwapChain4> dxgiswapChain4; /* DXGI 1.5 for HDR metadata */
bool send_metadata;
DXGI_HDR_METADATA_HDR10 hdr10;
bool logged_capabilities;
bool logged_capabilities = false;
};
DEFINE_GUID(GUID_SWAPCHAIN_WIDTH, 0xf1b59347, 0x1643, 0x411a, 0xad, 0x6b, 0xc7, 0x80, 0x17, 0x7a, 0x06, 0xb6);
@ -135,7 +139,7 @@ static const dxgi_color_space color_spaces[] = {
DXGIMAP(YCBCR, STUDIO, HLG, TOPLEFT, 2020)
DXGIMAP(YCBCR, FULL, HLG, TOPLEFT, 2020)
/*DXGIMAP(YCBCR, FULL, 22, NONE, 2020, 601)*/
{DXGI_COLOR_SPACE_RESERVED, NULL, 0, 0, 0, 0, 0},
{DXGI_COLOR_SPACE_RESERVED, NULL, COLOR_AXIS_RGB, COLOR_PRIMARIES_UNDEF, TRANSFER_FUNC_UNDEF, COLOR_SPACE_UNDEF, 0},
#undef DXGIMAP
};
@ -152,14 +156,16 @@ static bool canHandleConversion(const dxgi_color_space *src, const dxgi_color_sp
}
#endif
void DXGI_SelectSwapchainColorspace(struct dxgi_swapchain *display, const libvlc_video_render_cfg_t *cfg)
void DXGI_SelectSwapchainColorspace(dxgi_swapchain *display, const libvlc_video_render_cfg_t *cfg)
{
HRESULT hr;
int best = 0;
int score, best_score = 0;
UINT support;
IDXGISwapChain3 *dxgiswapChain3 = NULL;
hr = IDXGISwapChain_QueryInterface( display->dxgiswapChain, &IID_IDXGISwapChain3, (void **)&dxgiswapChain3);
ComPtr<IDXGISwapChain3> dxgiswapChain3;
ComPtr<IDXGIOutput> dxgiOutput;
hr = display->dxgiswapChain.As(&dxgiswapChain3);
if (FAILED(hr)) {
msg_Warn(display->obj, "could not get a IDXGISwapChain3");
goto done;
@ -170,7 +176,7 @@ void DXGI_SelectSwapchainColorspace(struct dxgi_swapchain *display, const libvlc
best = -1;
for (int i=0; color_spaces[i].name; ++i)
{
hr = IDXGISwapChain3_CheckColorSpaceSupport(dxgiswapChain3, color_spaces[i].dxgi, &support);
hr = dxgiswapChain3->CheckColorSpaceSupport(color_spaces[i].dxgi, &support);
if (SUCCEEDED(hr) && support) {
if (!display->logged_capabilities)
msg_Dbg(display->obj, "supports colorspace %s", color_spaces[i].name);
@ -181,7 +187,7 @@ void DXGI_SelectSwapchainColorspace(struct dxgi_swapchain *display, const libvlc
score += 2; /* we don't want to translate color spaces */
if (color_spaces[i].transfer == (video_transfer_func_t) cfg->transfer ||
/* favor 2084 output for HLG source */
(color_spaces[i].transfer == TRANSFER_FUNC_SMPTE_ST2084 && cfg->transfer == TRANSFER_FUNC_HLG))
(color_spaces[i].transfer == TRANSFER_FUNC_SMPTE_ST2084 && cfg->transfer == libvlc_video_transfer_func_HLG))
score++;
if (color_spaces[i].b_full_range == cfg->full_range)
score++;
@ -199,18 +205,16 @@ void DXGI_SelectSwapchainColorspace(struct dxgi_swapchain *display, const libvlc
msg_Warn(display->obj, "no matching colorspace found force %s", color_spaces[best].name);
}
IDXGISwapChain_QueryInterface( display->dxgiswapChain, &IID_IDXGISwapChain4, (void **)&display->dxgiswapChain4);
display->dxgiswapChain.As(&display->dxgiswapChain4);
#ifdef HAVE_DXGI1_6_H
IDXGIOutput *dxgiOutput = NULL;
if (SUCCEEDED(IDXGISwapChain_GetContainingOutput( display->dxgiswapChain, &dxgiOutput )))
if (SUCCEEDED(display->dxgiswapChain->GetContainingOutput(dxgiOutput.GetAddressOf())))
{
IDXGIOutput6 *dxgiOutput6 = NULL;
if (SUCCEEDED(IDXGIOutput_QueryInterface( dxgiOutput, &IID_IDXGIOutput6, (void **)&dxgiOutput6 )))
ComPtr<IDXGIOutput6> dxgiOutput6;
if (SUCCEEDED(dxgiOutput.As(&dxgiOutput6)))
{
DXGI_OUTPUT_DESC1 desc1;
if (SUCCEEDED(IDXGIOutput6_GetDesc1( dxgiOutput6, &desc1 )))
if (SUCCEEDED(dxgiOutput6->GetDesc1(&desc1 )))
{
const dxgi_color_space *csp = NULL;
for (int i=0; color_spaces[i].name; ++i)
@ -231,13 +235,11 @@ void DXGI_SelectSwapchainColorspace(struct dxgi_swapchain *display, const libvlc
msg_Dbg(display->obj, "Output max luminance: %.1f, colorspace %s, bits per pixel %d", desc1.MaxFullFrameLuminance, csp?csp->name:"unknown", desc1.BitsPerColor);
//sys->display.luminance_peak = desc1.MaxFullFrameLuminance;
}
IDXGIOutput6_Release( dxgiOutput6 );
}
IDXGIOutput_Release( dxgiOutput );
}
#endif
hr = IDXGISwapChain3_SetColorSpace1(dxgiswapChain3, color_spaces[best].dxgi);
hr = dxgiswapChain3->SetColorSpace1(color_spaces[best].dxgi);
if (SUCCEEDED(hr))
msg_Dbg(display->obj, "using colorspace %s", color_spaces[best].name);
else
@ -247,12 +249,10 @@ done:
display->send_metadata = color_spaces[best].transfer == (video_transfer_func_t) cfg->transfer &&
color_spaces[best].primaries == (video_color_primaries_t) cfg->primaries &&
color_spaces[best].color == (video_color_space_t) cfg->colorspace;
if (dxgiswapChain3)
IDXGISwapChain3_Release(dxgiswapChain3);
}
#if !VLC_WINSTORE_APP
static void FillSwapChainDesc(struct dxgi_swapchain *display, UINT width, UINT height, DXGI_SWAP_CHAIN_DESC1 *out)
static void FillSwapChainDesc(dxgi_swapchain *display, UINT width, UINT height, DXGI_SWAP_CHAIN_DESC1 *out)
{
ZeroMemory(out, sizeof(*out));
out->BufferCount = DXGI_SWAP_FRAME_COUNT;
@ -285,7 +285,7 @@ static void FillSwapChainDesc(struct dxgi_swapchain *display, UINT width, UINT h
}
}
static void DXGI_CreateSwapchainHwnd(struct dxgi_swapchain *display,
static void DXGI_CreateSwapchainHwnd(dxgi_swapchain *display,
IDXGIAdapter *dxgiadapter, IUnknown *pFactoryDevice,
UINT width, UINT height)
{
@ -299,38 +299,37 @@ static void DXGI_CreateSwapchainHwnd(struct dxgi_swapchain *display,
DXGI_SWAP_CHAIN_DESC1 scd;
FillSwapChainDesc(display, width, height, &scd);
IDXGIFactory2 *dxgifactory;
HRESULT hr = IDXGIAdapter_GetParent(dxgiadapter, &IID_IDXGIFactory2, (void **)&dxgifactory);
ComPtr<IDXGIFactory2> dxgifactory;
HRESULT hr = dxgiadapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgifactory.GetAddressOf()));
if (FAILED(hr)) {
msg_Err(display->obj, "Could not get the DXGI Factory. (hr=0x%lX)", hr);
return;
}
hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, pFactoryDevice,
hr = dxgifactory->CreateSwapChainForHwnd(pFactoryDevice,
display->swapchainSurface.hwnd, &scd,
NULL, NULL, &display->dxgiswapChain);
NULL, NULL, display->dxgiswapChain.GetAddressOf());
if (hr == DXGI_ERROR_INVALID_CALL && scd.Format == DXGI_FORMAT_R10G10B10A2_UNORM)
{
msg_Warn(display->obj, "10 bits swapchain failed, try 8 bits");
scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
hr = IDXGIFactory2_CreateSwapChainForHwnd(dxgifactory, pFactoryDevice,
hr = dxgifactory->CreateSwapChainForHwnd(pFactoryDevice,
display->swapchainSurface.hwnd, &scd,
NULL, NULL, &display->dxgiswapChain);
NULL, NULL, display->dxgiswapChain.GetAddressOf());
}
IDXGIFactory2_Release(dxgifactory);
if (FAILED(hr)) {
msg_Err(display->obj, "Could not create the SwapChain. (hr=0x%lX)", hr);
}
}
#ifdef HAVE_DCOMP_H
static void DXGI_CreateSwapchainDComp(struct dxgi_swapchain *display,
#if defined(HAVE_DCOMP_H)
static void DXGI_CreateSwapchainDComp(dxgi_swapchain *display,
IDXGIAdapter *dxgiadapter, IUnknown *pFactoryDevice,
UINT width, UINT height)
{
vlc_assert(display->swapchainSurfaceType == SWAPCHAIN_SURFACE_DCOMP);
if (display->swapchainSurface.dcomp.device == NULL || display->swapchainSurface.dcomp.visual == NULL)
if (!display->swapchainSurface.dcomp.device || !display->swapchainSurface.dcomp.visual)
{
msg_Err(display->obj, "missing a HWND to create the swapchain");
return;
@ -342,28 +341,26 @@ static void DXGI_CreateSwapchainDComp(struct dxgi_swapchain *display,
scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
scd.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
IDXGIFactory2 *dxgifactory;
HRESULT hr = IDXGIAdapter_GetParent(dxgiadapter, &IID_IDXGIFactory2, (void **)&dxgifactory);
ComPtr<IDXGIFactory2> dxgifactory;
HRESULT hr = dxgiadapter->GetParent(IID_GRAPHICS_PPV_ARGS(dxgifactory.GetAddressOf()));
if (FAILED(hr)) {
msg_Err(display->obj, "Could not get the DXGI Factory. (hr=0x%lX)", hr);
return;
}
hr = IDXGIFactory2_CreateSwapChainForComposition(dxgifactory, pFactoryDevice,
&scd, NULL, &display->dxgiswapChain);
hr = dxgifactory->CreateSwapChainForComposition(pFactoryDevice,
&scd, NULL, display->dxgiswapChain.GetAddressOf());
if (hr == DXGI_ERROR_INVALID_CALL && scd.Format == DXGI_FORMAT_R10G10B10A2_UNORM)
{
msg_Warn(display->obj, "10 bits swapchain failed, try 8 bits");
scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
hr = IDXGIFactory2_CreateSwapChainForComposition(dxgifactory, pFactoryDevice,
&scd, NULL, &display->dxgiswapChain);
hr = dxgifactory->CreateSwapChainForComposition(pFactoryDevice,
&scd, NULL, display->dxgiswapChain.GetAddressOf());
}
IDXGIFactory2_Release(dxgifactory);
if (SUCCEEDED(hr)) {
IDCompositionVisual_SetContent(display->swapchainSurface.dcomp.visual, (IUnknown *)display->dxgiswapChain);
IDCompositionDevice_Commit(display->swapchainSurface.dcomp.device);
}
if (FAILED(hr)) {
display->swapchainSurface.dcomp.visual->SetContent(display->dxgiswapChain.Get());
display->swapchainSurface.dcomp.device->Commit();
} else {
msg_Err(display->obj, "Could not create the SwapChain. (hr=0x%lX)", hr);
}
}
@ -371,11 +368,11 @@ static void DXGI_CreateSwapchainDComp(struct dxgi_swapchain *display,
#endif /* !VLC_WINSTORE_APP */
void DXGI_LocalSwapchainSwap( struct dxgi_swapchain *display )
void DXGI_LocalSwapchainSwap( dxgi_swapchain *display )
{
DXGI_PRESENT_PARAMETERS presentParams = { 0 };
DXGI_PRESENT_PARAMETERS presentParams = { };
HRESULT hr = IDXGISwapChain1_Present1( display->dxgiswapChain, 0, 0, &presentParams );
HRESULT hr = display->dxgiswapChain->Present1(0, 0, &presentParams );
if ( hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET )
{
/* TODO device lost */
@ -383,14 +380,14 @@ void DXGI_LocalSwapchainSwap( struct dxgi_swapchain *display )
}
}
void DXGI_LocalSwapchainSetMetadata( struct dxgi_swapchain *display, libvlc_video_metadata_type_t type, const void *metadata )
void DXGI_LocalSwapchainSetMetadata( dxgi_swapchain *display, libvlc_video_metadata_type_t type, const void *metadata )
{
assert(type == libvlc_video_metadata_frame_hdr10);
if ( type == libvlc_video_metadata_frame_hdr10 && metadata &&
display->send_metadata && display->dxgiswapChain4 )
display->send_metadata && display->dxgiswapChain4.Get() )
{
const libvlc_video_frame_hdr10_metadata_t *p_hdr10 = metadata;
DXGI_HDR_METADATA_HDR10 hdr10 = { 0 };
const libvlc_video_frame_hdr10_metadata_t *p_hdr10 = static_cast<const libvlc_video_frame_hdr10_metadata_t *>(metadata);
DXGI_HDR_METADATA_HDR10 hdr10 = { };
hdr10.GreenPrimary[0] = p_hdr10->GreenPrimary[0];
hdr10.GreenPrimary[1] = p_hdr10->GreenPrimary[1];
hdr10.BluePrimary[0] = p_hdr10->BluePrimary[0];
@ -406,15 +403,15 @@ void DXGI_LocalSwapchainSetMetadata( struct dxgi_swapchain *display, libvlc_vide
if (memcmp(&display->hdr10, &hdr10, sizeof(hdr10)))
{
memcpy(&display->hdr10, &hdr10, sizeof(hdr10));
IDXGISwapChain4_SetHDRMetaData( display->dxgiswapChain4, DXGI_HDR_METADATA_TYPE_HDR10,
display->dxgiswapChain4->SetHDRMetaData(DXGI_HDR_METADATA_TYPE_HDR10,
sizeof( &display->hdr10 ), &display->hdr10 );
}
}
}
struct dxgi_swapchain *DXGI_CreateLocalSwapchainHandleHwnd(vlc_object_t *o, HWND hwnd)
dxgi_swapchain *DXGI_CreateLocalSwapchainHandleHwnd(vlc_object_t *o, HWND hwnd)
{
struct dxgi_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
dxgi_swapchain *display = new (std::nothrow) dxgi_swapchain();
if (unlikely(display == NULL))
return NULL;
@ -429,37 +426,28 @@ struct dxgi_swapchain *DXGI_CreateLocalSwapchainHandleHwnd(vlc_object_t *o, HWND
return display;
}
#ifdef HAVE_DCOMP_H
struct dxgi_swapchain *DXGI_CreateLocalSwapchainHandleDComp(vlc_object_t *o, void* dcompDevice, void* dcompVisual)
#if defined(HAVE_DCOMP_H) && !VLC_WINSTORE_APP
dxgi_swapchain *DXGI_CreateLocalSwapchainHandleDComp(vlc_object_t *o, void* dcompDevice, void* dcompVisual)
{
struct dxgi_swapchain *display = vlc_obj_calloc(o, 1, sizeof(*display));
dxgi_swapchain *display = new (std::nothrow) dxgi_swapchain();
if (unlikely(display == NULL))
return NULL;
display->obj = o;
display->swapchainSurfaceType = SWAPCHAIN_SURFACE_DCOMP;
display->swapchainSurface.dcomp.device = dcompDevice;
display->swapchainSurface.dcomp.visual = dcompVisual;
display->swapchainSurface.dcomp.device = static_cast<IDCompositionDevice*>(dcompDevice);
display->swapchainSurface.dcomp.visual = static_cast<IDCompositionVisual*>(dcompVisual);
return display;
}
#endif
void DXGI_LocalSwapchainCleanupDevice( struct dxgi_swapchain *display )
void DXGI_LocalSwapchainCleanupDevice( dxgi_swapchain *display )
{
if (display->dxgiswapChain4)
{
IDXGISwapChain4_Release(display->dxgiswapChain4);
display->dxgiswapChain4 = NULL;
}
if (display->dxgiswapChain)
{
IDXGISwapChain_Release(display->dxgiswapChain);
display->dxgiswapChain = NULL;
}
delete display;
}
void DXGI_SwapchainUpdateOutput( struct dxgi_swapchain *display, libvlc_video_output_cfg_t *out )
void DXGI_SwapchainUpdateOutput( dxgi_swapchain *display, libvlc_video_output_cfg_t *out )
{
out->dxgi_format = display->pixelFormat->formatTexture;
out->full_range = display->colorspace->b_full_range;
@ -468,45 +456,44 @@ void DXGI_SwapchainUpdateOutput( struct dxgi_swapchain *display, libvlc_video_ou
out->transfer = (libvlc_video_transfer_func_t) display->colorspace->transfer;
}
bool DXGI_UpdateSwapChain( struct dxgi_swapchain *display, IDXGIAdapter *dxgiadapter,
bool DXGI_UpdateSwapChain( dxgi_swapchain *display, IDXGIAdapter *dxgiadapter,
IUnknown *pFactoryDevice,
const d3d_format_t *newPixelFormat, const libvlc_video_render_cfg_t *cfg )
{
#if !VLC_WINSTORE_APP
if (display->dxgiswapChain != NULL && display->pixelFormat != newPixelFormat)
if (display->dxgiswapChain.Get() && display->pixelFormat != newPixelFormat)
{
// the pixel format changed, we need a new swapchain
IDXGISwapChain_Release(display->dxgiswapChain);
display->dxgiswapChain = NULL;
display->dxgiswapChain.Reset();
display->logged_capabilities = false;
}
if ( display->dxgiswapChain == NULL )
if ( !display->dxgiswapChain.Get() )
{
display->pixelFormat = newPixelFormat;
#ifdef HAVE_DCOMP_H
#if defined(HAVE_DCOMP_H)
if (display->swapchainSurfaceType == SWAPCHAIN_SURFACE_DCOMP)
DXGI_CreateSwapchainDComp(display, dxgiadapter, pFactoryDevice,
cfg->width, cfg->height);
else // SWAPCHAIN_TARGET_HWND
#endif
#endif // HAVE_DCOMP_H
DXGI_CreateSwapchainHwnd(display, dxgiadapter, pFactoryDevice,
cfg->width, cfg->height);
}
#else /* VLC_WINSTORE_APP */
if ( display->dxgiswapChain == NULL )
if ( !display->dxgiswapChain.Get() )
{
display->dxgiswapChain = (void*)(uintptr_t)var_InheritInteger(display->obj, "winrt-swapchain");
display->dxgiswapChain = static_cast<IDXGISwapChain1*>((void*)(uintptr_t)var_InheritInteger(display->obj, "winrt-swapchain"));
}
#endif /* VLC_WINSTORE_APP */
if (display->dxgiswapChain == NULL)
if ( !display->dxgiswapChain.Get() )
return false;
/* TODO detect is the size is the same as the output and switch to fullscreen mode */
HRESULT hr;
hr = IDXGISwapChain_ResizeBuffers( display->dxgiswapChain, 0, cfg->width, cfg->height,
hr = display->dxgiswapChain->ResizeBuffers(0, cfg->width, cfg->height,
DXGI_FORMAT_UNKNOWN, 0 );
if ( FAILED( hr ) ) {
msg_Err( display->obj, "Failed to resize the backbuffer. (hr=0x%lX)", hr );
@ -517,17 +504,17 @@ bool DXGI_UpdateSwapChain( struct dxgi_swapchain *display, IDXGIAdapter *dxgiada
return true;
}
IDXGISwapChain1 *DXGI_GetSwapChain1( struct dxgi_swapchain *display )
Microsoft::WRL::ComPtr<IDXGISwapChain1> & DXGI_GetSwapChain1( dxgi_swapchain *display )
{
return display->dxgiswapChain;
}
IDXGISwapChain4 *DXGI_GetSwapChain4( struct dxgi_swapchain *display )
Microsoft::WRL::ComPtr<IDXGISwapChain4> & DXGI_GetSwapChain4( dxgi_swapchain *display )
{
return display->dxgiswapChain4;
}
const d3d_format_t *DXGI_GetPixelFormat( struct dxgi_swapchain *display )
const d3d_format_t *DXGI_GetPixelFormat( dxgi_swapchain *display )
{
return display->pixelFormat;
}

View File

@ -32,23 +32,30 @@
#include <vlc/libvlc_renderer_discoverer.h>
#include <vlc/libvlc_media_player.h>
#include <wrl/client.h>
#include <dxgi1_5.h>
#include "../../video_chroma/dxgi_fmt.h"
#ifndef IID_GRAPHICS_PPV_ARGS
#define IID_GRAPHICS_PPV_ARGS(ppType) IID_PPV_ARGS(ppType)
#endif
#define DXGI_SWAP_FRAME_COUNT 3
struct dxgi_swapchain;
struct dxgi_swapchain *DXGI_CreateLocalSwapchainHandleHwnd(vlc_object_t *, HWND);
#ifdef HAVE_DCOMP_H
#if defined(HAVE_DCOMP_H) && !VLC_WINSTORE_APP
struct dxgi_swapchain *DXGI_CreateLocalSwapchainHandleDComp(vlc_object_t *,
void /*IDCompositionDevice*/ * dcompDevice,
void /*IDCompositionVisual*/ * dcompVisual);
#endif
IDXGISwapChain1 *DXGI_GetSwapChain1( struct dxgi_swapchain * );
IDXGISwapChain4 *DXGI_GetSwapChain4( struct dxgi_swapchain * );
Microsoft::WRL::ComPtr<IDXGISwapChain1> & DXGI_GetSwapChain1( struct dxgi_swapchain * );
Microsoft::WRL::ComPtr<IDXGISwapChain4> & DXGI_GetSwapChain4( struct dxgi_swapchain * );
const d3d_format_t *DXGI_GetPixelFormat( struct dxgi_swapchain * );
void DXGI_SelectSwapchainColorspace( struct dxgi_swapchain *, const libvlc_video_render_cfg_t * );
@ -61,4 +68,4 @@ bool DXGI_UpdateSwapChain( struct dxgi_swapchain *, IDXGIAdapter *,
void DXGI_LocalSwapchainSwap( struct dxgi_swapchain * );
void DXGI_LocalSwapchainSetMetadata( struct dxgi_swapchain *, libvlc_video_metadata_type_t, const void * );
#endif /* VLC_D3D11_SWAPCHAIN_H */
#endif /* VLC_DXGI_SWAPCHAIN_H */

View File

@ -1310,7 +1310,7 @@ modules/video_output/opengl/display.c
modules/video_output/opengl/egl.c
modules/video_output/opengl/vout_helper.h
modules/video_output/win32/direct3d9.c
modules/video_output/win32/direct3d11.c
modules/video_output/win32/direct3d11.cpp
modules/video_output/win32/drawable.c
modules/video_output/win32/events.c
modules/video_output/win32/glwin32.c