diff options
Diffstat (limited to 'video/out/opengl/context_angle.c')
-rw-r--r-- | video/out/opengl/context_angle.c | 265 |
1 files changed, 33 insertions, 232 deletions
diff --git a/video/out/opengl/context_angle.c b/video/out/opengl/context_angle.c index 13e29c410e..e09945ba2d 100644 --- a/video/out/opengl/context_angle.c +++ b/video/out/opengl/context_angle.c @@ -24,6 +24,7 @@ #include "angle_dynamic.h" #include "egl_helpers.h" +#include "d3d11_helpers.h" #include "common/common.h" #include "options/m_config.h" @@ -40,9 +41,6 @@ #define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002 #endif -// Windows 8 enum value, not present in mingw-w64 headers -#define DXGI_ADAPTER_FLAG_SOFTWARE (2) - enum { RENDERER_AUTO, RENDERER_D3D9, @@ -97,17 +95,11 @@ const struct m_sub_options angle_conf = { }; struct priv { - IDXGIFactory1 *dxgi_factory; - IDXGIFactory2 *dxgi_factory2; - IDXGIAdapter1 *dxgi_adapter; - IDXGIDevice1 *dxgi_device; IDXGISwapChain *dxgi_swapchain; - IDXGISwapChain1 *dxgi_swapchain1; ID3D11Device *d3d11_device; ID3D11DeviceContext *d3d11_context; ID3D11Texture2D *d3d11_backbuffer; - D3D_FEATURE_LEVEL d3d11_level; EGLConfig egl_config; EGLDisplay egl_display; @@ -223,19 +215,6 @@ static void d3d11_device_destroy(MPGLContext *ctx) p->egl_device = 0; SAFE_RELEASE(p->d3d11_device); - SAFE_RELEASE(p->dxgi_device); - SAFE_RELEASE(p->dxgi_adapter); - SAFE_RELEASE(p->dxgi_factory); - SAFE_RELEASE(p->dxgi_factory2); -} - -static void show_sw_adapter_msg(MPGLContext *ctx) -{ - struct priv *p = ctx->priv; - if (p->sw_adapter_msg_shown) - return; - MP_WARN(ctx->vo, "Using a software adapter\n"); - p->sw_adapter_msg_shown = true; } static bool d3d11_device_create(MPGLContext *ctx, int flags) @@ -243,96 +222,17 @@ static bool d3d11_device_create(MPGLContext *ctx, int flags) struct priv *p = ctx->priv; struct vo *vo = ctx->vo; struct angle_opts *o = p->opts; - HRESULT hr; - HMODULE d3d11_dll = LoadLibraryW(L"d3d11.dll"); - if (!d3d11_dll) { - MP_FATAL(vo, "Failed to load d3d11.dll\n"); - return false; - } - - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE) - GetProcAddress(d3d11_dll, "D3D11CreateDevice"); - if (!D3D11CreateDevice) { - MP_FATAL(vo, "D3D11CreateDevice entry point not found\n"); - return false; - } - - D3D_FEATURE_LEVEL *levels = (D3D_FEATURE_LEVEL[]) { - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, - D3D_FEATURE_LEVEL_9_3, + struct d3d11_device_opts device_opts = { + .allow_warp = o->d3d11_warp != 0, + .force_warp = o->d3d11_warp == 1, + .max_feature_level = o->d3d11_feature_level, + .min_feature_level = D3D_FEATURE_LEVEL_9_3, + .max_frame_latency = o->max_frame_latency, }; - int level_count = 4; - - // Only try feature levels less than or equal to the user specified level - while (level_count && levels[0] > o->d3d11_feature_level) { - levels++; - level_count--; - } - - // Try a HW adapter first unless WARP is forced - hr = E_FAIL; - if ((FAILED(hr) && o->d3d11_warp == -1) || o->d3d11_warp == 0) { - hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, levels, - level_count, D3D11_SDK_VERSION, &p->d3d11_device, &p->d3d11_level, - &p->d3d11_context); - } - // Try WARP if it is forced or if the HW adapter failed - if ((FAILED(hr) && o->d3d11_warp == -1) || o->d3d11_warp == 1) { - hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_WARP, NULL, 0, levels, - level_count, D3D11_SDK_VERSION, &p->d3d11_device, &p->d3d11_level, - &p->d3d11_context); - if (SUCCEEDED(hr)) - show_sw_adapter_msg(ctx); - } - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't create Direct3D 11 device: %s\n", - mp_HRESULT_to_str(hr)); + if (!mp_d3d11_create_present_device(vo->log, &device_opts, &p->d3d11_device)) return false; - } - - hr = ID3D11Device_QueryInterface(p->d3d11_device, &IID_IDXGIDevice1, - (void**)&p->dxgi_device); - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't get DXGI device\n"); - return false; - } - - IDXGIDevice1_SetMaximumFrameLatency(p->dxgi_device, o->max_frame_latency); - - hr = IDXGIDevice1_GetParent(p->dxgi_device, &IID_IDXGIAdapter1, - (void**)&p->dxgi_adapter); - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't get DXGI adapter\n"); - return false; - } - - // Query some properties of the adapter in order to warn the user if they - // are using a software adapter - DXGI_ADAPTER_DESC1 desc; - hr = IDXGIAdapter1_GetDesc1(p->dxgi_adapter, &desc); - if (SUCCEEDED(hr)) { - if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) - show_sw_adapter_msg(ctx); - - // If the primary display adapter is a software adapter, the - // DXGI_ADAPTER_FLAG_SOFTWARE won't be set, but the device IDs - // should still match the Microsoft Basic Render Driver - if (desc.VendorId == 0x1414 && desc.DeviceId == 0x8c) - show_sw_adapter_msg(ctx); - } - - hr = IDXGIAdapter1_GetParent(p->dxgi_adapter, &IID_IDXGIFactory1, - (void**)&p->dxgi_factory); - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't get DXGI factory\n"); - return false; - } - - IDXGIFactory1_QueryInterface(p->dxgi_factory, &IID_IDXGIFactory2, - (void**)&p->dxgi_factory2); + ID3D11Device_GetImmediateContext(p->d3d11_device, &p->d3d11_context); PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT = (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT"); @@ -367,119 +267,39 @@ static bool d3d11_device_create(MPGLContext *ctx, int flags) static void d3d11_swapchain_surface_destroy(MPGLContext *ctx) { struct priv *p = ctx->priv; + + bool had_swapchain = p->dxgi_swapchain; SAFE_RELEASE(p->dxgi_swapchain); - SAFE_RELEASE(p->dxgi_swapchain1); d3d11_backbuffer_release(ctx); -} - -static bool d3d11_swapchain_create_1_2(MPGLContext *ctx, int flags) -{ - struct priv *p = ctx->priv; - struct vo *vo = ctx->vo; - HRESULT hr; - - update_sizes(ctx); - DXGI_SWAP_CHAIN_DESC1 desc1 = { - .Width = p->sc_width, - .Height = p->sc_height, - .Format = DXGI_FORMAT_R8G8B8A8_UNORM, - .SampleDesc = { .Count = 1 }, - .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | - DXGI_USAGE_SHADER_INPUT, - }; - if (p->opts->flip) { - desc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; - desc1.BufferCount = p->opts->swapchain_length; - } else { - desc1.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - desc1.BufferCount = 1; - } - - hr = IDXGIFactory2_CreateSwapChainForHwnd(p->dxgi_factory2, - (IUnknown*)p->d3d11_device, vo_w32_hwnd(vo), &desc1, NULL, NULL, - &p->dxgi_swapchain1); - if (FAILED(hr) && p->opts->flip) { - // Try again without DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL - desc1.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - desc1.BufferCount = 1; - - hr = IDXGIFactory2_CreateSwapChainForHwnd(p->dxgi_factory2, - (IUnknown*)p->d3d11_device, vo_w32_hwnd(vo), &desc1, NULL, NULL, - &p->dxgi_swapchain1); - } - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't create DXGI 1.2+ swap chain: %s\n", - mp_HRESULT_to_str(hr)); - return false; - } - - hr = IDXGISwapChain1_QueryInterface(p->dxgi_swapchain1, - &IID_IDXGISwapChain, (void**)&p->dxgi_swapchain); - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't create DXGI 1.2+ swap chain\n"); - return false; - } - - return true; -} - -static bool d3d11_swapchain_create_1_1(MPGLContext *ctx, int flags) -{ - struct priv *p = ctx->priv; - struct vo *vo = ctx->vo; - HRESULT hr; - - update_sizes(ctx); - DXGI_SWAP_CHAIN_DESC desc = { - .BufferDesc = { - .Width = p->sc_width, - .Height = p->sc_height, - .Format = DXGI_FORMAT_R8G8B8A8_UNORM - }, - .SampleDesc = { .Count = 1 }, - .BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | - DXGI_USAGE_SHADER_INPUT, - .BufferCount = 1, - .OutputWindow = vo_w32_hwnd(vo), - .Windowed = TRUE, - .SwapEffect = DXGI_SWAP_EFFECT_DISCARD, - }; - - hr = IDXGIFactory1_CreateSwapChain(p->dxgi_factory, - (IUnknown*)p->d3d11_device, &desc, &p->dxgi_swapchain); - if (FAILED(hr)) { - MP_FATAL(vo, "Couldn't create DXGI 1.1 swap chain: %s\n", - mp_HRESULT_to_str(hr)); - return false; - } - - return true; + // Ensure the swapchain is destroyed by flushing the D3D11 immediate + // context. This is needed because the HWND may be reused. See: + // https://msdn.microsoft.com/en-us/library/windows/desktop/ff476425.aspx + if (had_swapchain && p->d3d11_context) + ID3D11DeviceContext_Flush(p->d3d11_context); } static bool d3d11_swapchain_surface_create(MPGLContext *ctx, int flags) { struct priv *p = ctx->priv; struct vo *vo = ctx->vo; + struct angle_opts *o = p->opts; - if (p->dxgi_factory2) { - // Create a DXGI 1.2+ (Windows 8+) swap chain if possible - if (!d3d11_swapchain_create_1_2(ctx, flags)) - goto fail; - } else if (p->dxgi_factory) { - // Fall back to DXGI 1.1 (Windows 7) - if (!d3d11_swapchain_create_1_1(ctx, flags)) - goto fail; - } else { + if (!p->d3d11_device) goto fail; - } - // Prevent DXGI from making changes to the VO window, otherwise it will - // hook the Alt+Enter keystroke and make it trigger an ugly transition to - // exclusive fullscreen mode instead of running the user-set command. - IDXGIFactory_MakeWindowAssociation(p->dxgi_factory, vo_w32_hwnd(vo), - DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER | - DXGI_MWA_NO_PRINT_SCREEN); + update_sizes(ctx); + struct d3d11_swapchain_opts swapchain_opts = { + .window = vo_w32_hwnd(vo), + .width = p->sc_width, + .height = p->sc_height, + .flip = o->flip, + .length = o->swapchain_length, + .usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT, + }; + if (!mp_d3d11_create_swapchain(p->d3d11_device, vo->log, &swapchain_opts, + &p->dxgi_swapchain)) + goto fail; if (!d3d11_backbuffer_get(ctx)) goto fail; @@ -677,10 +497,6 @@ static int angle_init(struct MPGLContext *ctx, int flags) if ((!context_ok && !o->renderer) || o->renderer == RENDERER_D3D11) { context_ok = d3d11_device_create(ctx, flags); if (context_ok) { - MP_VERBOSE(vo, "Using Direct3D 11 feature level %u_%u\n", - ((unsigned)p->d3d11_level) >> 12, - (((unsigned)p->d3d11_level) >> 8) & 0xf); - context_ok = context_init(ctx, flags); if (!context_ok) d3d11_device_destroy(ctx); @@ -706,21 +522,6 @@ static int angle_init(struct MPGLContext *ctx, int flags) bool surface_ok = false; if ((!surface_ok && o->egl_windowing == -1) || o->egl_windowing == 0) { surface_ok = d3d11_swapchain_surface_create(ctx, flags); - if (surface_ok) { - if (p->dxgi_swapchain1) { - MP_VERBOSE(vo, "Using DXGI 1.2+\n"); - - DXGI_SWAP_CHAIN_DESC1 scd = {0}; - IDXGISwapChain1_GetDesc1(p->dxgi_swapchain1, &scd); - if (scd.SwapEffect == DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) { - MP_VERBOSE(vo, "Using flip-model presentation\n"); - } else { - MP_VERBOSE(vo, "Using bitblt-model presentation\n"); - } - } else { - MP_VERBOSE(vo, "Using DXGI 1.1\n"); - } - } } if ((!surface_ok && o->egl_windowing == -1) || o->egl_windowing == 1) { surface_ok = egl_window_surface_create(ctx, flags); @@ -755,15 +556,15 @@ static struct mp_image *d3d11_screenshot(MPGLContext *ctx) struct mp_image *img = NULL; HRESULT hr; - if (!p->dxgi_swapchain1) + if (!p->dxgi_swapchain) goto done; // Validate the swap chain. This screenshot method will only work on DXGI // 1.2+ flip/sequential swap chains. It's probably not possible at all with // discard swap chains, since by definition, the backbuffer contents is // discarded on Present(). - DXGI_SWAP_CHAIN_DESC1 scd; - hr = IDXGISwapChain1_GetDesc1(p->dxgi_swapchain1, &scd); + DXGI_SWAP_CHAIN_DESC scd; + hr = IDXGISwapChain_GetDesc(p->dxgi_swapchain, &scd); if (FAILED(hr)) goto done; if (scd.SwapEffect != DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL) |