mirror of https://code.videolan.org/videolan/vlc
d3d11 vout plugin
Signed-off-by: Jean-Baptiste Kempf <jb@videolan.org>
This commit is contained in:
parent
f309e6438b
commit
63be579eea
2
NEWS
2
NEWS
|
@ -55,6 +55,8 @@ Video ouput:
|
|||
* Large rework of the Android video outputs: there is now Surface (2.1, 2.2)
|
||||
NativeWindow (2.3+, supports hw rotation, subpicture blending, opaque)
|
||||
* Support rotation in Android NativeWindow output and hardware decoders
|
||||
* Renamed the Direct3D output module to Direct3D9
|
||||
* Added Direct3D11 video mode supporting both Windows desktop and WinRT modes.
|
||||
|
||||
Video filter:
|
||||
* Hardware deinterlacing on the rPI, using MMAL
|
||||
|
|
|
@ -3241,7 +3241,12 @@ AS_IF([test "${enable_directx}" != "no"], [
|
|||
#include <GL/gl.h>
|
||||
])
|
||||
|
||||
dnl Direct3D
|
||||
dnl Direct3D11
|
||||
AC_CHECK_HEADERS(d3d11.h, [
|
||||
VLC_ADD_PLUGIN([direct3d11])
|
||||
])
|
||||
|
||||
dnl Direct3D9
|
||||
AC_CHECK_HEADERS(d3d9.h, [
|
||||
VLC_ADD_PLUGIN([direct3d9])
|
||||
])
|
||||
|
|
|
@ -98,6 +98,7 @@ $Id$
|
|||
* diracsys: BBC Dirac demuxer
|
||||
* direct2d: video output module using the Direct2D API
|
||||
* direct3d9: video output module using the Direct3D9 API
|
||||
* direct3d11: video output module using the Direct3D11 API
|
||||
* directdraw: video output module using the DirectDraw API
|
||||
* directfb: Direct Framebuffer video output
|
||||
* directsound: audio output module using the DirectSound API
|
||||
|
|
|
@ -181,6 +181,22 @@ libdirect3d9_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
|
|||
vout_LTLIBRARIES += $(LTLIBdirect3d9)
|
||||
EXTRA_LTLIBRARIES += libdirect3d9_plugin.la
|
||||
|
||||
libdirect3d11_plugin_la_SOURCES = video_output/msw/direct3d11.c \
|
||||
video_output/msw/common.c video_output/msw/common.h \
|
||||
video_output/msw/events.c video_output/msw/events.h \
|
||||
video_output/msw/builtin_shaders.h \
|
||||
video_output/msw/win32touch.c video_output/msw/win32touch.h
|
||||
libdirect3d11_plugin_la_CPPFLAGS = $(AM_CPPFLAGS) \
|
||||
-DMODULE_NAME_IS_direct3d11
|
||||
if !HAVE_WINSTORE
|
||||
libdirect3d11_plugin_la_LIBADD = -lgdi32 -lole32 -luuid
|
||||
else
|
||||
libdirect3d11_plugin_la_LIBADD = -ld3dcompiler -lole32 -luuid
|
||||
endif
|
||||
libdirect3d11_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(voutdir)'
|
||||
vout_LTLIBRARIES += $(LTLIBdirect3d11)
|
||||
EXTRA_LTLIBRARIES += libdirect3d11_plugin.la
|
||||
|
||||
libdirectdraw_plugin_la_SOURCES = video_output/msw/directdraw.c \
|
||||
video_output/msw/common.c video_output/msw/common.h \
|
||||
video_output/msw/events.c video_output/msw/events.h \
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* $Id$
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@videolan.org>
|
||||
* Martell Malone <martellmalone@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -117,6 +118,13 @@ void CommonClean(vout_display_t *vd)
|
|||
RestoreScreensaver(vd);
|
||||
}
|
||||
|
||||
/* */
|
||||
picture_pool_t *CommonPool(vout_display_t *vd, unsigned count)
|
||||
{
|
||||
VLC_UNUSED(count);
|
||||
return vd->sys->pool;
|
||||
}
|
||||
|
||||
void CommonManage(vout_display_t *vd)
|
||||
{
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
|
@ -214,6 +222,25 @@ int CommonUpdatePicture(picture_t *picture, picture_t **fallback,
|
|||
picture->p->i_pitch = pitch;
|
||||
picture->p->i_lines = picture->format.i_visible_height;
|
||||
|
||||
/* Fill chroma planes for biplanar YUV */
|
||||
if (picture->format.i_chroma == VLC_CODEC_NV12 ||
|
||||
picture->format.i_chroma == VLC_CODEC_NV21) {
|
||||
|
||||
for (int n = 1; n < picture->i_planes; n++) {
|
||||
const plane_t *o = &picture->p[n-1];
|
||||
plane_t *p = &picture->p[n];
|
||||
|
||||
p->p_pixels = o->p_pixels + o->i_lines * o->i_pitch;
|
||||
p->i_pitch = pitch;
|
||||
p->i_lines = picture->format.i_visible_height;
|
||||
}
|
||||
/* The dx/d3d buffer is always allocated as NV12 */
|
||||
if (vlc_fourcc_AreUVPlanesSwapped(picture->format.i_chroma, VLC_CODEC_NV12)) {
|
||||
/* TODO : Swap NV21 UV planes to match NV12 */
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fill chroma planes for planar YUV */
|
||||
if (picture->format.i_chroma == VLC_CODEC_I420 ||
|
||||
picture->format.i_chroma == VLC_CODEC_J420 ||
|
||||
|
@ -348,7 +375,7 @@ void UpdateRects(vout_display_t *vd,
|
|||
SWP_NOCOPYBITS|SWP_NOZORDER|SWP_ASYNCWINDOWPOS);
|
||||
|
||||
/* Destination image position and dimensions */
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct2d)
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11) || defined(MODULE_NAME_IS_direct2d)
|
||||
rect_dest.left = 0;
|
||||
rect_dest.right = place.width;
|
||||
rect_dest.top = 0;
|
||||
|
@ -425,7 +452,7 @@ void UpdateRects(vout_display_t *vd,
|
|||
/* Apply overlay hardware constraints */
|
||||
if (sys->use_overlay)
|
||||
AlignRect(&rect_src_clipped, sys->i_align_src_boundary, sys->i_align_src_size);
|
||||
#elif defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct2d)
|
||||
#elif defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11) || defined(MODULE_NAME_IS_direct2d)
|
||||
/* Needed at least with YUV content */
|
||||
rect_src_clipped.left &= ~1;
|
||||
rect_src_clipped.right &= ~1;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*
|
||||
* Authors: Gildas Bazin <gbazin@videolan.org>
|
||||
* Damien Fouilleul <damienf@videolan.org>
|
||||
* Martell Malone <martellmalone@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -25,6 +26,15 @@
|
|||
#ifdef MODULE_NAME_IS_directdraw
|
||||
# include <ddraw.h>
|
||||
#endif
|
||||
#ifdef MODULE_NAME_IS_direct3d11
|
||||
# include <d3d11.h>
|
||||
# if VLC_WINSTORE_APP
|
||||
# include <dxgi1_2.h>
|
||||
# else
|
||||
# include <dxgi.h>
|
||||
#endif
|
||||
# include <d3dcompiler.h>
|
||||
#endif
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
# include <d3d9.h>
|
||||
# include <d3dx9effect.h>
|
||||
|
@ -135,6 +145,38 @@ struct vout_display_sys_t
|
|||
ID2D1Bitmap *d2_bitmap; /* D2 bitmap */
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_NAME_IS_direct3d11
|
||||
#if !VLC_WINSTORE_APP
|
||||
HINSTANCE hdxgi_dll; /* handle of the opened dxgi dll */
|
||||
HINSTANCE hd3d11_dll; /* handle of the opened d3d11 dll */
|
||||
HINSTANCE hd3dcompiler_dll; /* handle of the opened d3dcompiler dll */
|
||||
IDXGIAdapter *dxgiadapter; /* DXGI adapter */
|
||||
IDXGIFactory *dxgifactory; /* DXGI factory */
|
||||
IDXGISwapChain *dxgiswapChain; /* DXGI 1.0 swap chain */
|
||||
/* We should find a better way to store this or atleast a shorter name */
|
||||
PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN OurD3D11CreateDeviceAndSwapChain;
|
||||
PFN_D3D11_CREATE_DEVICE OurD3D11CreateDevice;
|
||||
pD3DCompile OurD3DCompile;
|
||||
#else
|
||||
IDXGISwapChain1 *dxgiswapChain; /* DXGI 1.1 swap chain */
|
||||
#endif
|
||||
ID3D11Device *d3ddevice; /* D3D device */
|
||||
ID3D11DeviceContext *d3dcontext; /* D3D context */
|
||||
ID3D11Texture2D *d3dtexture;
|
||||
ID3D11ShaderResourceView *d3dresViewY;
|
||||
ID3D11ShaderResourceView *d3dresViewUV;
|
||||
ID3D11RenderTargetView *d3drenderTargetView;
|
||||
ID3D11DepthStencilView *d3ddepthStencilView;
|
||||
ID3D11VertexShader *d3dvertexShader;
|
||||
ID3D11PixelShader *d3dpixelShader;
|
||||
ID3D11InputLayout *d3dvertexLayout;
|
||||
ID3D11SamplerState *d3dsampState;
|
||||
picture_sys_t *picsys;
|
||||
D3D_FEATURE_LEVEL d3dfeaturelevel;
|
||||
DXGI_FORMAT d3dFormat;
|
||||
vlc_fourcc_t vlcFormat;
|
||||
#endif
|
||||
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
bool allow_hw_yuv; /* Should we use hardware YUV->RGB conversions */
|
||||
/* show video on desktop window ? */
|
||||
|
@ -209,6 +251,8 @@ void UpdateRects (vout_display_t *,
|
|||
bool is_forced);
|
||||
void AlignRect(RECT *, int align_boundary, int align_size);
|
||||
|
||||
picture_pool_t *CommonPool(vout_display_t *, unsigned);
|
||||
|
||||
/*****************************************************************************
|
||||
* Constants
|
||||
*****************************************************************************/
|
||||
|
|
|
@ -0,0 +1,930 @@
|
|||
/*****************************************************************************
|
||||
* direct3d11.c: Windows Direct3D11 video output module
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2014-2015 VLC authors and VideoLAN
|
||||
*
|
||||
* Authors: Martell Malone <martellmalone@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
||||
#include <vlc_common.h>
|
||||
#include <vlc_plugin.h>
|
||||
#include <vlc_vout_display.h>
|
||||
|
||||
#define COBJMACROS
|
||||
#include <d3d11.h>
|
||||
|
||||
/* avoided until we can pass ISwapchainPanel without c++/cx mode
|
||||
# define INITGUID
|
||||
# include <windows.ui.xaml.media.dxinterop.h> */
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#if !VLC_WINSTORE_APP
|
||||
# define D3D11CreateDeviceAndSwapChain(args...) sys->OurD3D11CreateDeviceAndSwapChain(args)
|
||||
# define D3D11CreateDevice(args...) sys->OurD3D11CreateDevice(args)
|
||||
# define D3DCompile(args...) sys->OurD3DCompile(args)
|
||||
#else
|
||||
# define IDXGISwapChain_Present(args...) IDXGISwapChain_Present1(args)
|
||||
# define IDXGIFactory_CreateSwapChain(a,b,c,d) IDXGIFactory2_CreateSwapChainForComposition(a,b,c,NULL,d)
|
||||
# define DXGI_SWAP_CHAIN_DESC DXGI_SWAP_CHAIN_DESC1
|
||||
#endif
|
||||
|
||||
static int Open(vlc_object_t *);
|
||||
static void Close(vlc_object_t *);
|
||||
|
||||
#define D3D11_HELP N_("Recommended video output for Windows 8 and later versions")
|
||||
|
||||
vlc_module_begin ()
|
||||
set_shortname("Direct3D11")
|
||||
set_description(N_("Direct3D11 video output"))
|
||||
set_help(D3D11_HELP)
|
||||
set_category(CAT_VIDEO)
|
||||
set_subcategory(SUBCAT_VIDEO_VOUT)
|
||||
set_capability("vout display", 240)
|
||||
add_shortcut("direct3d11")
|
||||
set_callbacks(Open, Close)
|
||||
vlc_module_end ()
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *name;
|
||||
DXGI_FORMAT format;
|
||||
vlc_fourcc_t fourcc;
|
||||
} d3d_format_t;
|
||||
|
||||
static const d3d_format_t d3d_formats[] = {
|
||||
{ "NV12", DXGI_FORMAT_NV12, VLC_CODEC_NV12 },
|
||||
{ "RGBA", DXGI_FORMAT_R8G8B8A8_UNORM, VLC_CODEC_RGBA },
|
||||
{ NULL, 0, 0 }
|
||||
};
|
||||
|
||||
static const vlc_fourcc_t d3d_subpicture_chromas[] = {
|
||||
VLC_CODEC_RGBA,
|
||||
0
|
||||
};
|
||||
|
||||
struct picture_sys_t
|
||||
{
|
||||
ID3D11Texture2D *texture;
|
||||
ID3D11DeviceContext *context;
|
||||
};
|
||||
|
||||
static int Open(vlc_object_t *);
|
||||
static void Close(vlc_object_t *object);
|
||||
|
||||
static void Prepare(vout_display_t *, picture_t *, subpicture_t *subpicture);
|
||||
static void Display(vout_display_t *, picture_t *, subpicture_t *subpicture);
|
||||
|
||||
static int Direct3D11Create (vout_display_t *);
|
||||
static void Direct3D11Destroy(vout_display_t *);
|
||||
|
||||
static int Direct3D11Open (vout_display_t *, video_format_t *);
|
||||
static void Direct3D11Close(vout_display_t *);
|
||||
|
||||
static int Direct3D11CreateResources (vout_display_t *, video_format_t *);
|
||||
static void Direct3D11DestroyResources(vout_display_t *);
|
||||
|
||||
static int Direct3D11MapTexture(picture_t *);
|
||||
|
||||
/* All the #if 0 contain an alternative method to setup dx11
|
||||
They both need to be benchmarked to see which performs better */
|
||||
#if 0
|
||||
/* I have no idea why MS decided dxgi headers do not define this
|
||||
As they do have prototypes for d3d11 functions */
|
||||
typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
|
||||
#endif
|
||||
|
||||
/* TODO: Move to a direct3d11_shaders header */
|
||||
static const char* globVertexShaderDefault = "\
|
||||
struct VS_INPUT\
|
||||
{\
|
||||
float4 Position : POSITION;\
|
||||
float2 Texture : TEXCOORD0;\
|
||||
};\
|
||||
\
|
||||
struct VS_OUTPUT\
|
||||
{\
|
||||
float4 Position : SV_POSITION;\
|
||||
float2 Texture : TEXCOORD0;\
|
||||
};\
|
||||
\
|
||||
VS_OUTPUT VS( VS_INPUT In )\
|
||||
{\
|
||||
VS_OUTPUT Output;\
|
||||
Output.Position = float4(In.Position.xy, 0.0f, 1.0f);\
|
||||
Output.Texture = In.Texture;\
|
||||
return Output;\
|
||||
}\
|
||||
";
|
||||
|
||||
static const char* globPixelShaderDefault = "\
|
||||
Texture2D shaderTexture;\
|
||||
SamplerState SampleType;\
|
||||
\
|
||||
struct PS_INPUT\
|
||||
{\
|
||||
float4 Position : SV_POSITION;\
|
||||
float2 Texture : TEXCOORD0;\
|
||||
};\
|
||||
\
|
||||
float4 PS( PS_INPUT In ) : SV_TARGET\
|
||||
{\
|
||||
return shaderTexture.Sample(SampleType, In.Texture);\
|
||||
}\
|
||||
";
|
||||
|
||||
static const char* globPixelShaderBiplanarYUV2RGB = "\
|
||||
Texture2D shaderTextureY;\
|
||||
Texture2D shaderTextureUV;\
|
||||
SamplerState SampleType;\
|
||||
\
|
||||
struct PS_INPUT\
|
||||
{\
|
||||
float4 Position : SV_POSITION;\
|
||||
float2 Texture : TEXCOORD0;\
|
||||
};\
|
||||
\
|
||||
float4 PS( PS_INPUT In ) : SV_TARGET\
|
||||
{\
|
||||
float3 yuv;\
|
||||
float4 rgba;\
|
||||
yuv.x = shaderTextureY.Sample(SampleType, In.Texture).x;\
|
||||
yuv.yz = shaderTextureUV.Sample(SampleType, In.Texture).xy;\
|
||||
yuv.x = 1.164 * (yuv.x-0.0625);\
|
||||
yuv.y = yuv.y - 0.5;\
|
||||
yuv.z = yuv.z - 0.5;\
|
||||
rgba.x = saturate(yuv.x + 1.596 * yuv.z);\
|
||||
rgba.y = saturate(yuv.x - 0.813 * yuv.z - 0.391 * yuv.y);\
|
||||
rgba.z = saturate(yuv.x + 2.018 * yuv.y);\
|
||||
rgba.w = 1.0;\
|
||||
return rgba;\
|
||||
}\
|
||||
";
|
||||
|
||||
static int Open(vlc_object_t *object)
|
||||
{
|
||||
vout_display_t *vd = (vout_display_t *)object;
|
||||
|
||||
if (Direct3D11Create(vd)) {
|
||||
msg_Err(vd, "Direct3D11 could not be initialized");
|
||||
Direct3D11Destroy(vd);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
if (CommonInit(vd))
|
||||
goto error;
|
||||
|
||||
/* TODO : A fallback system */
|
||||
vd->sys->d3dFormat = d3d_formats[0].format;
|
||||
vd->sys->vlcFormat = d3d_formats[0].fourcc;
|
||||
|
||||
video_format_t fmt;
|
||||
if (Direct3D11Open(vd, &fmt)) {
|
||||
msg_Err(vd, "Direct3D11 could not be opened");
|
||||
goto error;
|
||||
}
|
||||
|
||||
vout_display_info_t info = vd->info;
|
||||
info.is_slow = true;
|
||||
info.has_double_click = true;
|
||||
info.has_hide_mouse = false;
|
||||
info.has_pictures_invalid = true;
|
||||
info.has_event_thread = true;
|
||||
|
||||
/* TODO : subtitle support */
|
||||
info.subpicture_chromas = NULL;
|
||||
|
||||
video_format_Clean(&vd->fmt);
|
||||
video_format_Copy(&vd->fmt, &fmt);
|
||||
vd->info = info;
|
||||
|
||||
vd->pool = CommonPool;
|
||||
vd->prepare = Prepare;
|
||||
vd->display = Display;
|
||||
vd->control = CommonControl;
|
||||
vd->manage = CommonManage;
|
||||
|
||||
msg_Dbg(vd, "Direct3D11 Open Succeeded");
|
||||
|
||||
return VLC_SUCCESS;
|
||||
error:
|
||||
Direct3D11Close(vd);
|
||||
CommonClean(vd);
|
||||
Direct3D11Destroy(vd);
|
||||
free(vd->sys);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
static void Close(vlc_object_t *object)
|
||||
{
|
||||
vout_display_t * vd = (vout_display_t *)object;
|
||||
|
||||
Direct3D11Close(vd);
|
||||
CommonClean(vd);
|
||||
Direct3D11Destroy(vd);
|
||||
free(vd->sys);
|
||||
}
|
||||
|
||||
static void Prepare(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
|
||||
{
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
VLC_UNUSED(subpicture);
|
||||
VLC_UNUSED(picture);
|
||||
|
||||
/* float ClearColor[4] = { 1.0f, 0.125f, 0.3f, 1.0f }; */
|
||||
/* ID3D11DeviceContext_ClearRenderTargetView(sys->d3dcontext,sys->d3drenderTargetView, ClearColor); */
|
||||
ID3D11DeviceContext_ClearDepthStencilView(sys->d3dcontext,sys->d3ddepthStencilView, D3D11_CLEAR_DEPTH, 1.0f, 0);
|
||||
|
||||
/* Render the quad */
|
||||
ID3D11DeviceContext_VSSetShader(sys->d3dcontext, sys->d3dvertexShader, NULL, 0);
|
||||
ID3D11DeviceContext_PSSetShader(sys->d3dcontext, sys->d3dpixelShader, NULL, 0);
|
||||
ID3D11DeviceContext_PSSetShaderResources(sys->d3dcontext, 0, 1, &sys->d3dresViewY);
|
||||
|
||||
if (sys->vlcFormat == VLC_CODEC_NV12)
|
||||
ID3D11DeviceContext_PSSetShaderResources(sys->d3dcontext, 1, 1, &sys->d3dresViewUV);
|
||||
|
||||
ID3D11DeviceContext_PSSetSamplers(sys->d3dcontext, 0, 1, &sys->d3dsampState);
|
||||
ID3D11DeviceContext_DrawIndexed(sys->d3dcontext, 6, 0, 0);
|
||||
}
|
||||
|
||||
static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture)
|
||||
{
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
|
||||
IDXGISwapChain_Present(sys->dxgiswapChain, 0, 0);
|
||||
|
||||
picture_Release(picture);
|
||||
if (subpicture)
|
||||
subpicture_Delete(subpicture);
|
||||
|
||||
CommonDisplay(vd);
|
||||
}
|
||||
|
||||
#if !VLC_WINSTORE_APP
|
||||
static HINSTANCE Direct3D11LoadShaderLibrary(void)
|
||||
{
|
||||
HINSTANCE instance = NULL;
|
||||
/* d3dcompiler_47 is the latest on windows 8.1 */
|
||||
for (int i = 47; i > 41; --i) {
|
||||
TCHAR filename[18];
|
||||
_sntprintf(filename, 18, TEXT("D3DCOMPILER_%d.dll"), i);
|
||||
instance = LoadLibrary(filename);
|
||||
if (instance) break;
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int Direct3D11Create(vout_display_t *vd)
|
||||
{
|
||||
|
||||
#if !VLC_WINSTORE_APP
|
||||
|
||||
HINSTANCE hd3d11_dll = LoadLibrary(TEXT("D3D11.DLL"));
|
||||
if (!hd3d11_dll) {
|
||||
msg_Warn(vd, "cannot load d3d11.dll, aborting");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# if 0
|
||||
HINSTANCE hdxgi_dll = LoadLibrary(TEXT("DXGI.DLL"));
|
||||
if (!hdxgi_dll) {
|
||||
msg_Warn(vd, "cannot load dxgi.dll, aborting");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
# endif
|
||||
|
||||
HINSTANCE hd3dcompiler_dll = Direct3D11LoadShaderLibrary();
|
||||
if (!hd3dcompiler_dll) {
|
||||
msg_Err(vd, "cannot load d3dcompiler.dll, aborting");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
IDXGISwapChain1* dxgiswapChain = var_InheritInteger(vd, "winrt-dxgiswapchain");
|
||||
if (!dxgiswapChain)
|
||||
return VLC_EGENERIC;
|
||||
ID3D11Device* d3ddevice = var_InheritInteger(vd, "winrt-d3ddevice");
|
||||
if (!d3ddevice)
|
||||
return VLC_EGENERIC;
|
||||
ID3D11DeviceContext* d3dcontext = var_InheritInteger(vd, "winrt-d3dcontext");
|
||||
if (!d3dcontext)
|
||||
return VLC_EGENERIC;
|
||||
|
||||
#endif
|
||||
|
||||
vout_display_sys_t *sys = vd->sys = calloc(1, sizeof(vout_display_sys_t));
|
||||
if (!sys)
|
||||
return VLC_ENOMEM;
|
||||
|
||||
#if !VLC_WINSTORE_APP
|
||||
|
||||
sys->hd3d11_dll = hd3d11_dll;
|
||||
sys->hd3dcompiler_dll = hd3dcompiler_dll;
|
||||
|
||||
sys->OurD3DCompile = (void *)GetProcAddress(sys->hd3dcompiler_dll, "D3DCompile");
|
||||
if (!sys->OurD3DCompile) {
|
||||
msg_Err(vd, "Cannot locate reference to D3DCompile in d3dcompiler DLL");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# if 0
|
||||
|
||||
sys->hdxgi_dll = hdxgi_dll;
|
||||
|
||||
/* TODO : enable all dxgi versions from 1.3 -> 1.1 */
|
||||
PFN_CREATE_DXGI_FACTORY OurCreateDXGIFactory =
|
||||
(void *)GetProcAddress(sys->hdxgi_dll, "CreateDXGIFactory");
|
||||
if (!OurCreateDXGIFactory) {
|
||||
msg_Err(vd, "Cannot locate reference to CreateDXGIFactory in dxgi DLL");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
/* TODO : detect the directx version supported and use IID_IDXGIFactory3 or 2 */
|
||||
HRESULT hr = OurCreateDXGIFactory(&IID_IDXGIFactory, (void **)&sys->dxgifactory);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not create dxgi factory. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
sys->OurD3D11CreateDeviceAndSwapChain =
|
||||
(void *)GetProcAddress(sys->hd3d11_dll, "D3D11CreateDeviceAndSwapChain");
|
||||
if (!sys->OurD3D11CreateDeviceAndSwapChain) {
|
||||
msg_Err(vd, "Cannot locate reference to D3D11CreateDeviceAndSwapChain in d3d11 DLL");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
sys->OurD3D11CreateDevice =
|
||||
(void *)GetProcAddress(sys->hd3d11_dll, "D3D11CreateDevice");
|
||||
if (!sys->OurD3D11CreateDevice) {
|
||||
msg_Err(vd, "Cannot locate reference to D3D11CreateDevice in d3d11 DLL");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#else
|
||||
|
||||
sys->dxgiswapChain = dxgiswapChain;
|
||||
sys->d3ddevice = d3ddevice;
|
||||
sys->d3dcontext = d3dcontext;
|
||||
|
||||
#endif
|
||||
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static void Direct3D11Destroy(vout_display_t *vd)
|
||||
{
|
||||
|
||||
#if !VLC_WINSTORE_APP
|
||||
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
|
||||
# if 0
|
||||
if (sys->hdxgi_dll)
|
||||
FreeLibrary(sys->hdxgi_dll);
|
||||
# endif
|
||||
|
||||
if (sys->hd3d11_dll)
|
||||
FreeLibrary(sys->hd3d11_dll);
|
||||
if (sys->hd3dcompiler_dll)
|
||||
FreeLibrary(sys->hd3dcompiler_dll);
|
||||
|
||||
/* TODO : add release of d3d11 objects here */
|
||||
|
||||
sys->OurD3D11CreateDevice = NULL;
|
||||
sys->OurD3D11CreateDeviceAndSwapChain = NULL;
|
||||
sys->OurD3DCompile = NULL;
|
||||
sys->hdxgi_dll = NULL;
|
||||
sys->hd3d11_dll = NULL;
|
||||
sys->hd3dcompiler_dll = NULL;
|
||||
#else
|
||||
|
||||
VLC_UNUSED(vd);
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static int Direct3D11Open(vout_display_t *vd, video_format_t *fmt)
|
||||
{
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
*fmt = vd->source;
|
||||
|
||||
#if !VLC_WINSTORE_APP
|
||||
|
||||
UINT creationFlags = 0;
|
||||
HRESULT hr = S_OK;
|
||||
|
||||
static const D3D_FEATURE_LEVEL featureLevels[] =
|
||||
{
|
||||
D3D_FEATURE_LEVEL_11_1,
|
||||
D3D_FEATURE_LEVEL_11_0,
|
||||
D3D_FEATURE_LEVEL_10_1,
|
||||
D3D_FEATURE_LEVEL_10_0,
|
||||
D3D_FEATURE_LEVEL_9_3,
|
||||
D3D_FEATURE_LEVEL_9_2,
|
||||
D3D_FEATURE_LEVEL_9_1
|
||||
};
|
||||
|
||||
# ifndef NDEBUG
|
||||
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
# endif
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC scd;
|
||||
memset(&scd, 0, sizeof(scd));
|
||||
scd.BufferCount = 1;
|
||||
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
scd.SampleDesc.Count = 1;
|
||||
scd.SampleDesc.Quality = 0;
|
||||
scd.BufferDesc.Width = fmt->i_visible_width;
|
||||
scd.BufferDesc.Height = fmt->i_visible_height;
|
||||
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
|
||||
# if VLC_WINSTORE_APP
|
||||
/* TODO : check different values for performance */
|
||||
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
scd.BufferCount = 2;
|
||||
scd.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
scd.Flags = DXGI_SWAP_CHAIN_FLAG_FOREGROUND_LAYER;
|
||||
scd.AlphaMode = DXGI_ALPHA_MODE_PREMULTIPLIED;
|
||||
scd.Scaling = DXGI_SCALING_NONE;
|
||||
# else
|
||||
scd.Windowed = TRUE;
|
||||
scd.OutputWindow = sys->hvideownd;
|
||||
# endif
|
||||
|
||||
# if 0
|
||||
|
||||
/* TODO : list adapters for the user to choose from */
|
||||
hr = IDXGIFactory_EnumAdapters(sys->dxgifactory, 0, &sys->dxgiadapter);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not create find factory. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
IDXGIOutput* output;
|
||||
hr = IDXGIAdapter_EnumOutputs(sys->dxgiadapter, 0, &output);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not Enumerate DXGI Outputs. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
DXGI_MODE_DESC md;
|
||||
memset(&md, 0, sizeof(md));
|
||||
md.Width = fmt->i_visible_width;
|
||||
md.Height = fmt->i_visible_height;
|
||||
md.Format = scd.BufferDesc.Format;
|
||||
md.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
||||
|
||||
hr = IDXGIOutput_FindClosestMatchingMode(output, &md, &scd.BufferDesc, NULL);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Failed to find a supported video mode. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
/* mode desc doesn't carry over the width and height*/
|
||||
scd.BufferDesc.Width = fmt->i_visible_width;
|
||||
scd.BufferDesc.Height = fmt->i_visible_height;
|
||||
|
||||
hr = D3D11CreateDeviceAndSwapChain(sys->dxgiadapter,
|
||||
D3D_DRIVER_TYPE_UNKNOWN, NULL, creationFlags,
|
||||
featureLevels, ARRAYSIZE(featureLevels),
|
||||
D3D11_SDK_VERSION, &scd, &sys->dxgiswapChain,
|
||||
&sys->d3ddevice, &sys->d3dfeaturelevel, &sys->d3dcontext);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not Create the D3D11 device and SwapChain. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# else
|
||||
|
||||
static const D3D_DRIVER_TYPE driverAttempts[] = {
|
||||
D3D_DRIVER_TYPE_HARDWARE,
|
||||
D3D_DRIVER_TYPE_WARP,
|
||||
D3D_DRIVER_TYPE_REFERENCE,
|
||||
};
|
||||
|
||||
for (UINT driver = 0; driver < ARRAYSIZE(driverAttempts); driver++) {
|
||||
hr = D3D11CreateDevice(NULL, driverAttempts[driver], NULL, creationFlags,
|
||||
featureLevels, ARRAYSIZE(featureLevels), D3D11_SDK_VERSION,
|
||||
&sys->d3ddevice, &sys->d3dfeaturelevel, &sys->d3dcontext);
|
||||
if (SUCCEEDED(hr)) break;
|
||||
}
|
||||
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not Create the D3D11 device. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
IDXGIDevice *pDXGIDevice = NULL;
|
||||
hr = ID3D11Device_QueryInterface(sys->d3ddevice, &IID_IDXGIDevice, (void **)&pDXGIDevice);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not Query DXGI Interface. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = IDXGIDevice_GetAdapter(pDXGIDevice, &sys->dxgiadapter);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not get the DXGI Adapter. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = IDXGIAdapter_GetParent(sys->dxgiadapter, &IID_IDXGIFactory, (void **)&sys->dxgifactory);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not get the DXGI Factory. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = IDXGIFactory_CreateSwapChain(sys->dxgifactory, (IUnknown *)sys->d3ddevice, &scd, &sys->dxgiswapChain);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not create the SwapChain. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# if VLC_WINSTORE_APP /* avoided until we can pass ISwapchainPanel without c++/cx mode */
|
||||
/* TODO: figure out how to get "ISwapChainPanel ^panel" into brokenpanel in gcc */
|
||||
ISwapChainPanel *brokenpanel;
|
||||
ISwapChainPanelNative *panelNative;
|
||||
hr = ISwapChainPanelNative_QueryInterface(brokenpanel, &IID_ISwapChainPanelNative, (void **)&pDXGIDevice);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not get the Native Panel. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = ISwapChainPanelNative_SetSwapChain(panelNative, sys->dxgiswapChain);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not link the SwapChain with the Native Panel. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
UpdateRects(vd, NULL, NULL, true);
|
||||
|
||||
if (Direct3D11CreateResources(vd, fmt)) {
|
||||
msg_Err(vd, "Failed to allocate resources");
|
||||
Direct3D11DestroyResources(vd);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
EventThreadUpdateTitle(sys->event, VOUT_TITLE " (Direct3D11 output)");
|
||||
|
||||
msg_Dbg(vd, "Direct3D11 device adapter successfully initialized");
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
static void Direct3D11Close(vout_display_t *vd)
|
||||
{
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
|
||||
Direct3D11DestroyResources(vd);
|
||||
ID3D11DeviceContext_Release(sys->d3dcontext);
|
||||
ID3D11Device_Release(sys->d3ddevice);
|
||||
msg_Dbg(vd, "Direct3D11 device adapter closed");
|
||||
}
|
||||
|
||||
/* TODO : handle errors better
|
||||
TODO : seperate out into smaller functions like createshaders */
|
||||
static int Direct3D11CreateResources(vout_display_t *vd, video_format_t *fmt)
|
||||
{
|
||||
vout_display_sys_t *sys = vd->sys;
|
||||
ID3D11Texture2D* pBackBuffer = NULL;
|
||||
ID3D11Texture2D* pDepthStencil= NULL;
|
||||
HRESULT hr;
|
||||
|
||||
fmt->i_chroma = sys->vlcFormat;
|
||||
|
||||
hr = IDXGISwapChain_GetBuffer(sys->dxgiswapChain, 0, &IID_ID3D11Texture2D, (LPVOID *)&pBackBuffer);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not get the backbuffer from the Swapchain. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = ID3D11Device_CreateRenderTargetView(sys->d3ddevice, (ID3D11Resource *)pBackBuffer, NULL, &sys->d3drenderTargetView);
|
||||
|
||||
ID3D11Texture2D_Release(pBackBuffer);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not create the render view target. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
D3D11_TEXTURE2D_DESC deptTexDesc;
|
||||
memset(&deptTexDesc, 0,sizeof(deptTexDesc));
|
||||
deptTexDesc.ArraySize = 1;
|
||||
deptTexDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
|
||||
deptTexDesc.CPUAccessFlags = 0;
|
||||
deptTexDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
|
||||
deptTexDesc.Width = fmt->i_visible_width;
|
||||
deptTexDesc.Height = fmt->i_visible_height;
|
||||
deptTexDesc.MipLevels = 1;
|
||||
deptTexDesc.MiscFlags = 0;
|
||||
deptTexDesc.SampleDesc.Count = 1;
|
||||
deptTexDesc.SampleDesc.Quality = 0;
|
||||
deptTexDesc.Usage = D3D11_USAGE_DEFAULT;
|
||||
|
||||
hr = ID3D11Device_CreateTexture2D(sys->d3ddevice, &deptTexDesc, NULL, &pDepthStencil);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not create the depth stencil texture. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
D3D11_DEPTH_STENCIL_VIEW_DESC depthViewDesc;
|
||||
memset(&depthViewDesc, 0, sizeof(depthViewDesc));
|
||||
|
||||
depthViewDesc.Format = deptTexDesc.Format;
|
||||
depthViewDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
|
||||
depthViewDesc.Texture2D.MipSlice = 0;
|
||||
|
||||
hr = ID3D11Device_CreateDepthStencilView(sys->d3ddevice, (ID3D11Resource *)pDepthStencil, &depthViewDesc, &sys->d3ddepthStencilView);
|
||||
|
||||
ID3D11Texture2D_Release(pDepthStencil);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not create the depth stencil view. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
ID3D11DeviceContext_OMSetRenderTargets(sys->d3dcontext, 1, &sys->d3drenderTargetView, sys->d3ddepthStencilView);
|
||||
|
||||
D3D11_VIEWPORT vp;
|
||||
vp.Width = (FLOAT)fmt->i_visible_width;
|
||||
vp.Height = (FLOAT)fmt->i_visible_height;
|
||||
vp.MinDepth = 0.0f;
|
||||
vp.MaxDepth = 1.0f;
|
||||
vp.TopLeftX = 0;
|
||||
vp.TopLeftY = 0;
|
||||
|
||||
ID3D11DeviceContext_RSSetViewports(sys->d3dcontext, 1, &vp);
|
||||
|
||||
ID3DBlob* pVSBlob = NULL;
|
||||
|
||||
/* TODO : Match the version to the D3D_FEATURE_LEVEL */
|
||||
hr = D3DCompile(globVertexShaderDefault, strlen(globVertexShaderDefault),
|
||||
NULL, NULL, NULL, "VS", "vs_4_0_level_9_1", 0, 0, &pVSBlob, NULL);
|
||||
|
||||
if( FAILED(hr)) {
|
||||
msg_Err(vd, "The Vertex Shader is invalid.");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = ID3D11Device_CreateVertexShader(sys->d3ddevice, (void *)ID3D10Blob_GetBufferPointer(pVSBlob),
|
||||
ID3D10Blob_GetBufferSize(pVSBlob), NULL, &sys->d3dvertexShader);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
ID3D11Device_Release(pVSBlob);
|
||||
msg_Err(vd, "Failed to create the vertex shader.");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
D3D11_INPUT_ELEMENT_DESC layout[] = {
|
||||
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
};
|
||||
|
||||
ID3D11InputLayout* pVertexLayout = NULL;
|
||||
hr = ID3D11Device_CreateInputLayout(sys->d3ddevice, layout, 2, (void *)ID3D10Blob_GetBufferPointer(pVSBlob),
|
||||
ID3D10Blob_GetBufferSize(pVSBlob), &pVertexLayout);
|
||||
|
||||
ID3D10Blob_Release(pVSBlob);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
msg_Err(vd, "Failed to create the vertex input layout");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
ID3D11DeviceContext_IASetInputLayout(sys->d3dcontext, pVertexLayout);
|
||||
|
||||
ID3DBlob* pPSBlob = NULL;
|
||||
|
||||
/* TODO : Match the version to the D3D_FEATURE_LEVEL */
|
||||
if (sys->vlcFormat == VLC_CODEC_NV12)
|
||||
hr = D3DCompile(globPixelShaderBiplanarYUV2RGB, strlen(globPixelShaderBiplanarYUV2RGB),
|
||||
NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
|
||||
else
|
||||
hr = D3DCompile(globPixelShaderDefault, strlen(globPixelShaderDefault),
|
||||
NULL, NULL, NULL, "PS", "ps_4_0_level_9_1", 0, 0, &pPSBlob, NULL);
|
||||
|
||||
|
||||
if( FAILED(hr)) {
|
||||
msg_Err(vd, "The Pixel Shader is invalid.");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
hr = ID3D11Device_CreatePixelShader(sys->d3ddevice, (void *)ID3D10Blob_GetBufferPointer(pPSBlob),
|
||||
ID3D10Blob_GetBufferSize(pPSBlob), NULL, &sys->d3dpixelShader);
|
||||
|
||||
ID3D10Blob_Release(pPSBlob);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
msg_Err(vd, "Failed to create the pixel shader.");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
float vertices[] = {
|
||||
-1.0f, -1.0f, -1.0f, 0.0f, 1.0f,
|
||||
1.0f, -1.0f, -1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, -1.0f, 1.0f, 0.0f,
|
||||
-1.0f, 1.0f, -1.0f, 0.0f, 0.0f,
|
||||
};
|
||||
|
||||
D3D11_BUFFER_DESC bd;
|
||||
memset(&bd, 0, sizeof(bd));
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.ByteWidth = sizeof(float) * 5 * 4;
|
||||
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
|
||||
bd.CPUAccessFlags = 0;
|
||||
|
||||
D3D11_SUBRESOURCE_DATA InitData;
|
||||
memset(&InitData, 0, sizeof(InitData));
|
||||
InitData.pSysMem = vertices;
|
||||
|
||||
ID3D11Buffer* pVertexBuffer = NULL;
|
||||
hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, &InitData, &pVertexBuffer);
|
||||
|
||||
if(FAILED(hr)) {
|
||||
msg_Err(vd, "Failed to create vertex buffer.");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
UINT stride = sizeof(float) * 5;
|
||||
UINT offset = 0;
|
||||
ID3D11DeviceContext_IASetVertexBuffers(sys->d3dcontext, 0, 1, &pVertexBuffer, &stride, &offset);
|
||||
|
||||
ID3D11Buffer_Release(pVertexBuffer);
|
||||
|
||||
WORD indices[] = {
|
||||
3, 1, 0,
|
||||
2, 1, 3,
|
||||
};
|
||||
|
||||
bd.Usage = D3D11_USAGE_DEFAULT;
|
||||
bd.ByteWidth = sizeof(WORD)*6;
|
||||
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
|
||||
bd.CPUAccessFlags = 0;
|
||||
InitData.pSysMem = indices;
|
||||
|
||||
ID3D11Buffer* pIndexBuffer = NULL;
|
||||
hr = ID3D11Device_CreateBuffer(sys->d3ddevice, &bd, &InitData, &pIndexBuffer);
|
||||
if(FAILED(hr)) {
|
||||
msg_Err(vd, "Failed to create index buffer.");
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
ID3D11DeviceContext_IASetIndexBuffer(sys->d3dcontext, pIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
|
||||
|
||||
ID3D11Buffer_Release(pVertexBuffer);
|
||||
|
||||
ID3D11DeviceContext_IASetPrimitiveTopology(sys->d3dcontext, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
|
||||
D3D11_TEXTURE2D_DESC texDesc;
|
||||
memset(&texDesc, 0, sizeof(texDesc));
|
||||
texDesc.Width = fmt->i_visible_width;
|
||||
texDesc.Height = fmt->i_visible_height;
|
||||
texDesc.MipLevels = texDesc.ArraySize = 1;
|
||||
texDesc.Format = sys->d3dFormat;
|
||||
texDesc.SampleDesc.Count = 1;
|
||||
texDesc.Usage = D3D11_USAGE_DYNAMIC;
|
||||
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
|
||||
texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
|
||||
texDesc.MiscFlags = 0;
|
||||
|
||||
hr = ID3D11Device_CreateTexture2D(sys->d3ddevice, &texDesc, NULL, &sys->d3dtexture);
|
||||
if (FAILED(hr)) {
|
||||
msg_Err(vd, "Could not Create the D3d11 Texture. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
D3D11_SHADER_RESOURCE_VIEW_DESC resviewDesc;
|
||||
memset(&resviewDesc, 0, sizeof(resviewDesc));
|
||||
resviewDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
|
||||
resviewDesc.Texture2D.MipLevels = texDesc.MipLevels;
|
||||
|
||||
if (sys->vlcFormat == VLC_CODEC_NV12)
|
||||
resviewDesc.Format = DXGI_FORMAT_R8_UNORM;
|
||||
|
||||
hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, (ID3D11Resource *)sys->d3dtexture, &resviewDesc, &sys->d3dresViewY);
|
||||
if (FAILED(hr)) {
|
||||
if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
|
||||
msg_Err(vd, "Could not Create the Y D3d11 Texture ResoureView. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
if (sys->vlcFormat == VLC_CODEC_NV12) {
|
||||
resviewDesc.Format = DXGI_FORMAT_R8G8_UNORM;
|
||||
hr = ID3D11Device_CreateShaderResourceView(sys->d3ddevice, (ID3D11Resource *)sys->d3dtexture, &resviewDesc, &sys->d3dresViewUV);
|
||||
if (FAILED(hr)) {
|
||||
if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
|
||||
msg_Err(vd, "Could not Create the U D3d11 Texture ResoureView. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
}
|
||||
|
||||
D3D11_SAMPLER_DESC sampDesc;
|
||||
memset(&sampDesc, 0, sizeof(sampDesc));
|
||||
sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
|
||||
sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
|
||||
sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
|
||||
sampDesc.MinLOD = 0;
|
||||
sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
|
||||
|
||||
hr = ID3D11Device_CreateSamplerState(sys->d3ddevice, &sampDesc, &sys->d3dsampState);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
|
||||
msg_Err(vd, "Could not Create the D3d11 Sampler State. (hr=0x%lX)", hr);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
picture_sys_t *picsys = malloc(sizeof(*picsys));
|
||||
if (unlikely(picsys == NULL)) {
|
||||
if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
|
||||
return VLC_ENOMEM;
|
||||
}
|
||||
|
||||
picsys->texture = sys->d3dtexture;
|
||||
picsys->context = sys->d3dcontext;
|
||||
|
||||
picture_resource_t resource = { .p_sys = picsys };
|
||||
for (int i = 0; i < PICTURE_PLANE_MAX; i++)
|
||||
resource.p[i].i_lines = fmt->i_visible_height / (i > 0 ? 2 : 1);
|
||||
|
||||
picture_t *picture = picture_NewFromResource(fmt, &resource);
|
||||
if (!picture) {
|
||||
if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
|
||||
free(picsys);
|
||||
return VLC_ENOMEM;
|
||||
}
|
||||
sys->picsys = picsys;
|
||||
|
||||
picture_pool_configuration_t pool_cfg;
|
||||
memset(&pool_cfg, 0, sizeof(pool_cfg));
|
||||
pool_cfg.picture_count = 1;
|
||||
pool_cfg.picture = &picture;
|
||||
pool_cfg.lock = Direct3D11MapTexture;
|
||||
|
||||
sys->pool = picture_pool_NewExtended(&pool_cfg);
|
||||
if (!sys->pool) {
|
||||
picture_Release(picture);
|
||||
if(sys->d3dtexture) ID3D11Texture2D_Release(sys->d3dtexture);
|
||||
return VLC_ENOMEM;
|
||||
}
|
||||
|
||||
msg_Dbg(vd, "Direct3D11 resources created");
|
||||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
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);
|
||||
picture_pool_Release(sys->pool);
|
||||
}
|
||||
sys->pool = NULL;
|
||||
|
||||
msg_Dbg(vd, "Direct3D11 resources destroyed");
|
||||
}
|
||||
|
||||
static int Direct3D11MapTexture(picture_t *picture)
|
||||
{
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
ID3D11DeviceContext_Map(picture->p_sys->context, (ID3D11Resource *)picture->p_sys->texture, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
|
||||
CommonUpdatePicture(picture, NULL, mappedResource.pData, mappedResource.RowPitch);
|
||||
ID3D11DeviceContext_Unmap(picture->p_sys->context,(ID3D11Resource *)picture->p_sys->texture, 0);
|
||||
return VLC_SUCCESS;
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
* $Id$
|
||||
*
|
||||
* Authors: Gildas Bazin <gbazin@videolan.org>
|
||||
* Martell Malone <martellmalone@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -620,7 +621,7 @@ static void MouseReleased( event_thread_t *p_event, unsigned button )
|
|||
vout_display_SendEventMouseReleased( p_event->vd, button );
|
||||
}
|
||||
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11)
|
||||
static int CALLBACK
|
||||
enumWindowsProc(HWND hwnd, LPARAM lParam)
|
||||
{
|
||||
|
@ -681,7 +682,7 @@ static int Win32VoutCreateWindow( event_thread_t *p_event )
|
|||
/* Get this module's instance */
|
||||
hInstance = GetModuleHandle(NULL);
|
||||
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11)
|
||||
if( !p_event->use_desktop )
|
||||
#endif
|
||||
{
|
||||
|
@ -692,7 +693,7 @@ static int Win32VoutCreateWindow( event_thread_t *p_event )
|
|||
else
|
||||
p_event->hparent = NULL;
|
||||
}
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11)
|
||||
else
|
||||
{
|
||||
vout_display_DeleteWindow(vd, NULL);
|
||||
|
@ -719,7 +720,11 @@ static int Win32VoutCreateWindow( event_thread_t *p_event )
|
|||
wc.hIcon = p_event->vlc_icon; /* load the vlc big icon */
|
||||
wc.hCursor = p_event->is_cursor_hidden ? p_event->cursor_empty :
|
||||
p_event->cursor_arrow;
|
||||
#if !VLC_WINSTORE_APP
|
||||
wc.hbrBackground = GetStockObject(BLACK_BRUSH); /* background color */
|
||||
#else
|
||||
wc.hbrBackground = NULL;
|
||||
#endif
|
||||
wc.lpszMenuName = NULL; /* no menu */
|
||||
wc.lpszClassName = p_event->class_main; /* use a special class */
|
||||
|
||||
|
@ -865,14 +870,14 @@ static void Win32VoutCloseWindow( event_thread_t *p_event )
|
|||
vout_display_t *vd = p_event->vd;
|
||||
msg_Dbg( vd, "Win32VoutCloseWindow" );
|
||||
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11)
|
||||
DestroyWindow( p_event->hvideownd );
|
||||
#endif
|
||||
DestroyWindow( p_event->hwnd );
|
||||
if( p_event->hfswnd )
|
||||
DestroyWindow( p_event->hfswnd );
|
||||
|
||||
#ifdef MODULE_NAME_IS_direct3d9
|
||||
#if defined(MODULE_NAME_IS_direct3d9) || defined(MODULE_NAME_IS_direct3d11)
|
||||
if( !p_event->use_desktop )
|
||||
#endif
|
||||
vout_display_DeleteWindow( vd, p_event->parent_window );
|
||||
|
|
|
@ -1175,6 +1175,7 @@ modules/video_output/kva.c
|
|||
modules/video_output/macosx.m
|
||||
modules/video_output/msw/direct2d.c
|
||||
modules/video_output/msw/direct3d9.c
|
||||
modules/video_output/msw/direct3d11.c
|
||||
modules/video_output/msw/directdraw.c
|
||||
modules/video_output/msw/events.c
|
||||
modules/video_output/msw/glwin32.c
|
||||
|
|
Loading…
Reference in New Issue