diff options
author | James Ross-Gowan <rossy@jrg.systems> | 2017-09-16 01:37:28 +1000 |
---|---|---|
committer | Niklas Haas <git@haasn.xyz> | 2017-09-21 15:01:17 +0200 |
commit | 75c0c06640da677477a0cfd08deee1d4e23a4361 (patch) | |
tree | 2053c8bf0097c3fc5142799cad67d49ecce981b1 /video/out/opengl/context_dxinterop.c | |
parent | 65979986a923a8f08019b257c3fe72cd5e8ecf68 (diff) | |
download | mpv-75c0c06640da677477a0cfd08deee1d4e23a4361.tar.bz2 mpv-75c0c06640da677477a0cfd08deee1d4e23a4361.tar.xz |
vo_gpu: convert windows/osx hwdecs/contexts to new API
Diffstat (limited to 'video/out/opengl/context_dxinterop.c')
-rw-r--r-- | video/out/opengl/context_dxinterop.c | 187 |
1 files changed, 100 insertions, 87 deletions
diff --git a/video/out/opengl/context_dxinterop.c b/video/out/opengl/context_dxinterop.c index 507c150d15..85d84bf677 100644 --- a/video/out/opengl/context_dxinterop.c +++ b/video/out/opengl/context_dxinterop.c @@ -22,6 +22,7 @@ #include "osdep/windows_utils.h" #include "video/out/w32_common.h" #include "context.h" +#include "utils.h" // For WGL_ACCESS_WRITE_DISCARD_NV, etc. #include <GL/wglext.h> @@ -35,6 +36,8 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase; #endif struct priv { + GL gl; + HMODULE d3d9_dll; HRESULT (WINAPI *Direct3DCreate9Ex)(UINT SDKVersion, IDirect3D9Ex **ppD3D); @@ -54,6 +57,7 @@ struct priv { // OpenGL resources GLuint texture; + GLuint main_fb; // Did we lose the device? bool lost_device; @@ -63,7 +67,7 @@ struct priv { int width, height, swapinterval; }; -static __thread struct MPGLContext *current_ctx; +static __thread struct ra_ctx *current_ctx; static void pump_message_loop(void) { @@ -84,10 +88,11 @@ static void *w32gpa(const GLubyte *procName) return GetProcAddress(oglmod, procName); } -static int os_ctx_create(struct MPGLContext *ctx) +static int os_ctx_create(struct ra_ctx *ctx) { static const wchar_t os_wnd_class[] = L"mpv offscreen gl"; struct priv *p = ctx->priv; + GL *gl = &p->gl; HGLRC legacy_context = NULL; RegisterClassExW(&(WNDCLASSEXW) { @@ -190,8 +195,8 @@ static int os_ctx_create(struct MPGLContext *ctx) goto fail; } - mpgl_load_functions(ctx->gl, w32gpa, wgl_exts, ctx->vo->log); - if (!(ctx->gl->mpgl_caps & MPGL_CAP_DXINTEROP)) { + mpgl_load_functions(gl, w32gpa, wgl_exts, ctx->vo->log); + if (!(gl->mpgl_caps & MPGL_CAP_DXINTEROP)) { MP_FATAL(ctx->vo, "WGL_NV_DX_interop is not supported\n"); goto fail; } @@ -205,7 +210,7 @@ fail: return -1; } -static void os_ctx_destroy(MPGLContext *ctx) +static void os_ctx_destroy(struct ra_ctx *ctx) { struct priv *p = ctx->priv; @@ -219,10 +224,10 @@ static void os_ctx_destroy(MPGLContext *ctx) DestroyWindow(p->os_wnd); } -static int d3d_size_dependent_create(MPGLContext *ctx) +static int d3d_size_dependent_create(struct ra_ctx *ctx) { struct priv *p = ctx->priv; - struct GL *gl = ctx->gl; + GL *gl = &p->gl; HRESULT hr; IDirect3DSwapChain9 *sw9; @@ -294,7 +299,7 @@ static int d3d_size_dependent_create(MPGLContext *ctx) return -1; } - gl->BindFramebuffer(GL_FRAMEBUFFER, ctx->main_fb); + gl->BindFramebuffer(GL_FRAMEBUFFER, p->main_fb); gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p->texture, 0); gl->BindFramebuffer(GL_FRAMEBUFFER, 0); @@ -302,10 +307,10 @@ static int d3d_size_dependent_create(MPGLContext *ctx) return 0; } -static void d3d_size_dependent_destroy(MPGLContext *ctx) +static void d3d_size_dependent_destroy(struct ra_ctx *ctx) { struct priv *p = ctx->priv; - struct GL *gl = ctx->gl; + GL *gl = &p->gl; if (p->rtarget_h) { gl->DXUnlockObjectsNV(p->device_h, 1, &p->rtarget_h); @@ -321,7 +326,8 @@ static void d3d_size_dependent_destroy(MPGLContext *ctx) SAFE_RELEASE(p->swapchain); } -static void fill_presentparams(MPGLContext *ctx, D3DPRESENT_PARAMETERS *pparams) +static void fill_presentparams(struct ra_ctx *ctx, + D3DPRESENT_PARAMETERS *pparams) { struct priv *p = ctx->priv; @@ -338,13 +344,9 @@ static void fill_presentparams(MPGLContext *ctx, D3DPRESENT_PARAMETERS *pparams) .Windowed = TRUE, .BackBufferWidth = ctx->vo->dwidth ? ctx->vo->dwidth : 1, .BackBufferHeight = ctx->vo->dheight ? ctx->vo->dheight : 1, - // The length of the backbuffer queue shouldn't affect latency because - // swap_buffers() always uses the backbuffer at the head of the queue - // and presents it immediately. MSDN says there is a performance - // penalty for having a short backbuffer queue and this seems to be - // true, at least on Nvidia, where less than four backbuffers causes - // very high CPU usage. Use six to be safe. - .BackBufferCount = 6, + // Add one frame for the backbuffer and one frame of "slack" to reduce + // contention with the window manager when acquiring the backbuffer + .BackBufferCount = ctx->opts.swapchain_depth + 2, .SwapEffect = IsWindows7OrGreater() ? D3DSWAPEFFECT_FLIPEX : D3DSWAPEFFECT_FLIP, // Automatically get the backbuffer format from the display format .BackBufferFormat = D3DFMT_UNKNOWN, @@ -353,10 +355,10 @@ static void fill_presentparams(MPGLContext *ctx, D3DPRESENT_PARAMETERS *pparams) }; } -static int d3d_create(MPGLContext *ctx) +static int d3d_create(struct ra_ctx *ctx) { struct priv *p = ctx->priv; - struct GL *gl = ctx->gl; + GL *gl = &p->gl; HRESULT hr; p->d3d9_dll = LoadLibraryW(L"d3d9.dll"); @@ -396,8 +398,7 @@ static int d3d_create(MPGLContext *ctx) return -1; } - // mpv expects frames to be presented right after swap_buffers() returns - IDirect3DDevice9Ex_SetMaximumFrameLatency(p->device, 1); + IDirect3DDevice9Ex_SetMaximumFrameLatency(p->device, ctx->opts.swapchain_depth); // Register the Direct3D device with WGL_NV_dx_interop p->device_h = gl->DXOpenDeviceNV(p->device); @@ -410,10 +411,10 @@ static int d3d_create(MPGLContext *ctx) return 0; } -static void d3d_destroy(MPGLContext *ctx) +static void d3d_destroy(struct ra_ctx *ctx) { struct priv *p = ctx->priv; - struct GL *gl = ctx->gl; + GL *gl = &p->gl; if (p->device_h) gl->DXCloseDeviceNV(p->device_h); @@ -423,8 +424,9 @@ static void d3d_destroy(MPGLContext *ctx) FreeLibrary(p->d3d9_dll); } -static void dxinterop_uninit(MPGLContext *ctx) +static void dxgl_uninit(struct ra_ctx *ctx) { + ra_gl_ctx_uninit(ctx); d3d_size_dependent_destroy(ctx); d3d_destroy(ctx); os_ctx_destroy(ctx); @@ -433,7 +435,7 @@ static void dxinterop_uninit(MPGLContext *ctx) pump_message_loop(); } -static void dxinterop_reset(struct MPGLContext *ctx) +static void dxgl_reset(struct ra_ctx *ctx) { struct priv *p = ctx->priv; HRESULT hr; @@ -468,18 +470,18 @@ static void dxinterop_reset(struct MPGLContext *ctx) p->lost_device = false; } -static int GLAPIENTRY dxinterop_swap_interval(int interval) +static int GLAPIENTRY dxgl_swap_interval(int interval) { if (!current_ctx) return 0; struct priv *p = current_ctx->priv; p->requested_swapinterval = interval; - dxinterop_reset(current_ctx); + dxgl_reset(current_ctx); return 1; } -static void * GLAPIENTRY dxinterop_get_native_display(const char *name) +static void * GLAPIENTRY dxgl_get_native_display(const char *name) { if (!current_ctx || !name) return NULL; @@ -493,60 +495,17 @@ static void * GLAPIENTRY dxinterop_get_native_display(const char *name) return NULL; } -static int dxinterop_init(struct MPGLContext *ctx, int flags) -{ - struct priv *p = ctx->priv; - struct GL *gl = ctx->gl; - - p->requested_swapinterval = 1; - - if (!vo_w32_init(ctx->vo)) - goto fail; - if (os_ctx_create(ctx) < 0) - goto fail; - - // Create the shared framebuffer - gl->GenFramebuffers(1, &ctx->main_fb); - - current_ctx = ctx; - gl->SwapInterval = dxinterop_swap_interval; - gl->MPGetNativeDisplay = dxinterop_get_native_display; - - if (d3d_create(ctx) < 0) - goto fail; - if (d3d_size_dependent_create(ctx) < 0) - goto fail; - - // The OpenGL and Direct3D coordinate systems are flipped vertically - // relative to each other. Flip the video during rendering so it can be - // copied to the Direct3D backbuffer with a simple (and fast) StretchRect. - ctx->flip_v = true; - - DwmEnableMMCSS(TRUE); - - return 0; -fail: - dxinterop_uninit(ctx); - return -1; -} - -static int dxinterop_reconfig(struct MPGLContext *ctx) -{ - vo_w32_config(ctx->vo); - return 0; -} - -static void dxinterop_swap_buffers(MPGLContext *ctx) +static void dxgl_swap_buffers(struct ra_ctx *ctx) { struct priv *p = ctx->priv; - struct GL *gl = ctx->gl; + GL *gl = &p->gl; HRESULT hr; pump_message_loop(); // If the device is still lost, try to reset it again if (p->lost_device) - dxinterop_reset(ctx); + dxgl_reset(ctx); if (p->lost_device) return; @@ -571,7 +530,7 @@ static void dxinterop_swap_buffers(MPGLContext *ctx) case D3DERR_DEVICEHUNG: MP_VERBOSE(ctx->vo, "Direct3D device lost! Resetting.\n"); p->lost_device = true; - dxinterop_reset(ctx); + dxgl_reset(ctx); return; default: if (FAILED(hr)) @@ -584,21 +543,75 @@ static void dxinterop_swap_buffers(MPGLContext *ctx) } } -static int dxinterop_control(MPGLContext *ctx, int *events, int request, +static bool dxgl_init(struct ra_ctx *ctx) +{ + struct priv *p = ctx->priv = talloc_zero(ctx, struct priv); + GL *gl = &p->gl; + + p->requested_swapinterval = 1; + + if (!vo_w32_init(ctx->vo)) + goto fail; + if (os_ctx_create(ctx) < 0) + goto fail; + + // Create the shared framebuffer + gl->GenFramebuffers(1, &p->main_fb); + + current_ctx = ctx; + gl->SwapInterval = dxgl_swap_interval; + gl->MPGetNativeDisplay = dxgl_get_native_display; + + if (d3d_create(ctx) < 0) + goto fail; + if (d3d_size_dependent_create(ctx) < 0) + goto fail; + + static const struct ra_swapchain_fns empty_swapchain_fns = {0}; + struct ra_gl_ctx_params params = { + .swap_buffers = dxgl_swap_buffers, + .flipped = true, + .external_swapchain = &empty_swapchain_fns, + }; + + if (!ra_gl_ctx_init(ctx, gl, params)) + goto fail; + + DwmEnableMMCSS(TRUE); + return true; +fail: + dxgl_uninit(ctx); + return false; +} + +static void resize(struct ra_ctx *ctx) +{ + struct priv *p = ctx->priv; + dxgl_reset(ctx); + ra_gl_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight, p->main_fb); +} + +static bool dxgl_reconfig(struct ra_ctx *ctx) +{ + vo_w32_config(ctx->vo); + resize(ctx); + return true; +} + +static int dxgl_control(struct ra_ctx *ctx, int *events, int request, void *arg) { - int r = vo_w32_control(ctx->vo, events, request, arg); + int ret = vo_w32_control(ctx->vo, events, request, arg); if (*events & VO_EVENT_RESIZE) - dxinterop_reset(ctx); - return r; + resize(ctx); + return ret; } -const struct mpgl_driver mpgl_driver_dxinterop = { +const struct ra_ctx_fns ra_ctx_dxgl = { + .type = "opengl", .name = "dxinterop", - .priv_size = sizeof(struct priv), - .init = dxinterop_init, - .reconfig = dxinterop_reconfig, - .swap_buffers = dxinterop_swap_buffers, - .control = dxinterop_control, - .uninit = dxinterop_uninit, + .init = dxgl_init, + .reconfig = dxgl_reconfig, + .control = dxgl_control, + .uninit = dxgl_uninit, }; |