summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorJames Ross-Gowan <rossy@jrg.systems>2017-09-16 01:37:28 +1000
committerNiklas Haas <git@haasn.xyz>2017-09-21 15:01:17 +0200
commit75c0c06640da677477a0cfd08deee1d4e23a4361 (patch)
tree2053c8bf0097c3fc5142799cad67d49ecce981b1 /video
parent65979986a923a8f08019b257c3fe72cd5e8ecf68 (diff)
downloadmpv-75c0c06640da677477a0cfd08deee1d4e23a4361.tar.bz2
mpv-75c0c06640da677477a0cfd08deee1d4e23a4361.tar.xz
vo_gpu: convert windows/osx hwdecs/contexts to new API
Diffstat (limited to 'video')
-rw-r--r--video/out/gpu/context.c6
-rw-r--r--video/out/opengl/context_angle.c220
-rw-r--r--video/out/opengl/context_cocoa.c70
-rw-r--r--video/out/opengl/context_dxinterop.c187
-rw-r--r--video/out/opengl/context_win.c (renamed from video/out/opengl/context_w32.c)238
-rw-r--r--video/out/opengl/hwdec_d3d11egl.c2
-rw-r--r--video/out/opengl/hwdec_d3d11eglrgb.c2
-rw-r--r--video/out/opengl/hwdec_dxva2egl.c2
-rw-r--r--video/out/opengl/hwdec_dxva2gldx.c2
9 files changed, 398 insertions, 331 deletions
diff --git a/video/out/gpu/context.c b/video/out/gpu/context.c
index dbabba8b3b..ba710ff59e 100644
--- a/video/out/gpu/context.c
+++ b/video/out/gpu/context.c
@@ -40,7 +40,7 @@ extern const struct ra_ctx_fns ra_ctx_cocoa;
extern const struct ra_ctx_fns ra_ctx_wayland_egl;
extern const struct ra_ctx_fns ra_ctx_wgl;
extern const struct ra_ctx_fns ra_ctx_angle;
-extern const struct ra_ctx_fns ra_ctx_dxinterop;
+extern const struct ra_ctx_fns ra_ctx_dxgl;
extern const struct ra_ctx_fns ra_ctx_rpi;
extern const struct ra_ctx_fns ra_ctx_mali;
extern const struct ra_ctx_fns ra_ctx_vdpauglx;
@@ -50,7 +50,6 @@ static const struct ra_ctx_fns *contexts[] = {
#if HAVE_RPI
&ra_ctx_rpi,
#endif
-/*
#if HAVE_GL_COCOA
&ra_ctx_cocoa,
#endif
@@ -61,9 +60,8 @@ static const struct ra_ctx_fns *contexts[] = {
&ra_ctx_wgl,
#endif
#if HAVE_GL_DXINTEROP
- &ra_ctx_dxinterop,
+ &ra_ctx_dxgl,
#endif
-*/
#if HAVE_GL_X11
&ra_ctx_glx_probe,
#endif
diff --git a/video/out/opengl/context_angle.c b/video/out/opengl/context_angle.c
index f249b746cb..a8051155e1 100644
--- a/video/out/opengl/context_angle.c
+++ b/video/out/opengl/context_angle.c
@@ -31,6 +31,7 @@
#include "video/out/w32_common.h"
#include "osdep/windows_utils.h"
#include "context.h"
+#include "utils.h"
#ifndef EGL_D3D_TEXTURE_ANGLE
#define EGL_D3D_TEXTURE_ANGLE 0x33A3
@@ -52,8 +53,6 @@ struct angle_opts {
int d3d11_warp;
int d3d11_feature_level;
int egl_windowing;
- int swapchain_length; // Currently only works with DXGI 1.2+
- int max_frame_latency;
int flip;
};
@@ -77,9 +76,9 @@ const struct m_sub_options angle_conf = {
({"auto", -1},
{"no", 0},
{"yes", 1})),
- OPT_INTRANGE("angle-swapchain-length", swapchain_length, 0, 2, 16),
- OPT_INTRANGE("angle-max-frame-latency", max_frame_latency, 0, 1, 16),
OPT_FLAG("angle-flip", flip, 0),
+ OPT_REPLACED("angle-max-frame-latency", "swapchain-depth"),
+ OPT_REMOVED("angle-swapchain-length", "controlled by --swapchain-depth"),
{0}
},
.defaults = &(const struct angle_opts) {
@@ -87,14 +86,14 @@ const struct m_sub_options angle_conf = {
.d3d11_warp = -1,
.d3d11_feature_level = D3D_FEATURE_LEVEL_11_0,
.egl_windowing = -1,
- .swapchain_length = 6,
- .max_frame_latency = 3,
.flip = 1,
},
.size = sizeof(struct angle_opts),
};
struct priv {
+ GL gl;
+
IDXGISwapChain *dxgi_swapchain;
ID3D11Device *d3d11_device;
@@ -110,20 +109,21 @@ struct priv {
int sc_width, sc_height; // Swap chain width and height
int swapinterval;
+ bool flipped;
struct angle_opts *opts;
};
-static __thread struct MPGLContext *current_ctx;
+static __thread struct ra_ctx *current_ctx;
-static void update_sizes(MPGLContext *ctx)
+static void update_sizes(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
p->sc_width = ctx->vo->dwidth ? ctx->vo->dwidth : 1;
p->sc_height = ctx->vo->dheight ? ctx->vo->dheight : 1;
}
-static void d3d11_backbuffer_release(MPGLContext *ctx)
+static void d3d11_backbuffer_release(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -137,7 +137,7 @@ static void d3d11_backbuffer_release(MPGLContext *ctx)
SAFE_RELEASE(p->d3d11_backbuffer);
}
-static bool d3d11_backbuffer_get(MPGLContext *ctx)
+static bool d3d11_backbuffer_get(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -168,7 +168,7 @@ static bool d3d11_backbuffer_get(MPGLContext *ctx)
return true;
}
-static void d3d11_backbuffer_resize(MPGLContext *ctx)
+static void d3d11_backbuffer_resize(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -197,7 +197,7 @@ static void d3d11_backbuffer_resize(MPGLContext *ctx)
MP_FATAL(vo, "Couldn't get back buffer after resize\n");
}
-static void d3d11_device_destroy(MPGLContext *ctx)
+static void d3d11_device_destroy(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -215,7 +215,7 @@ static void d3d11_device_destroy(MPGLContext *ctx)
SAFE_RELEASE(p->d3d11_device);
}
-static bool d3d11_device_create(MPGLContext *ctx, int flags)
+static bool d3d11_device_create(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -226,7 +226,7 @@ static bool d3d11_device_create(MPGLContext *ctx, int flags)
.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,
+ .max_frame_latency = ctx->opts.swapchain_depth,
};
if (!mp_d3d11_create_present_device(vo->log, &device_opts, &p->d3d11_device))
return false;
@@ -262,7 +262,7 @@ static bool d3d11_device_create(MPGLContext *ctx, int flags)
return true;
}
-static void d3d11_swapchain_surface_destroy(MPGLContext *ctx)
+static void d3d11_swapchain_surface_destroy(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -277,7 +277,7 @@ static void d3d11_swapchain_surface_destroy(MPGLContext *ctx)
ID3D11DeviceContext_Flush(p->d3d11_context);
}
-static bool d3d11_swapchain_surface_create(MPGLContext *ctx, int flags)
+static bool d3d11_swapchain_surface_create(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -292,7 +292,9 @@ static bool d3d11_swapchain_surface_create(MPGLContext *ctx, int flags)
.width = p->sc_width,
.height = p->sc_height,
.flip = o->flip,
- .length = o->swapchain_length,
+ // Add one frame for the backbuffer and one frame of "slack" to reduce
+ // contention with the window manager when acquiring the backbuffer
+ .length = ctx->opts.swapchain_depth + 2,
.usage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT,
};
if (!mp_d3d11_create_swapchain(p->d3d11_device, vo->log, &swapchain_opts,
@@ -301,8 +303,7 @@ static bool d3d11_swapchain_surface_create(MPGLContext *ctx, int flags)
if (!d3d11_backbuffer_get(ctx))
goto fail;
- // EGL_D3D_TEXTURE_ANGLE pbuffers are always flipped vertically
- ctx->flip_v = true;
+ p->flipped = true;
return true;
fail:
@@ -310,7 +311,7 @@ fail:
return false;
}
-static void d3d9_device_destroy(MPGLContext *ctx)
+static void d3d9_device_destroy(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
@@ -319,7 +320,7 @@ static void d3d9_device_destroy(MPGLContext *ctx)
p->egl_display = EGL_NO_DISPLAY;
}
-static bool d3d9_device_create(MPGLContext *ctx, int flags)
+static bool d3d9_device_create(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -348,7 +349,7 @@ static bool d3d9_device_create(MPGLContext *ctx, int flags)
return true;
}
-static void egl_window_surface_destroy(MPGLContext *ctx)
+static void egl_window_surface_destroy(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
if (p->egl_window) {
@@ -357,7 +358,7 @@ static void egl_window_surface_destroy(MPGLContext *ctx)
}
}
-static bool egl_window_surface_create(MPGLContext *ctx, int flags)
+static bool egl_window_surface_create(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -374,7 +375,7 @@ static bool egl_window_surface_create(MPGLContext *ctx, int flags)
EGL_SURFACE_ORIENTATION_ANGLE);
MP_TARRAY_APPEND(NULL, window_attribs, window_attribs_len,
EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
- ctx->flip_v = true;
+ p->flipped = true;
MP_VERBOSE(vo, "Rendering flipped.\n");
}
}
@@ -396,7 +397,7 @@ fail:
return false;
}
-static void context_destroy(struct MPGLContext *ctx)
+static void context_destroy(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
if (p->egl_context) {
@@ -407,7 +408,7 @@ static void context_destroy(struct MPGLContext *ctx)
p->egl_context = EGL_NO_CONTEXT;
}
-static bool context_init(struct MPGLContext *ctx, int flags)
+static bool context_init(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
struct vo *vo = ctx->vo;
@@ -421,8 +422,8 @@ static bool context_init(struct MPGLContext *ctx, int flags)
if (exts)
MP_DBG(vo, "EGL extensions: %s\n", exts);
- if (!mpegl_create_context(p->egl_display, vo->log, flags | VOFLAG_GLES,
- &p->egl_context, &p->egl_config))
+ if (!mpegl_create_context(ctx, p->egl_display, &p->egl_context,
+ &p->egl_config))
{
MP_FATAL(vo, "Could not create EGL context!\n");
goto fail;
@@ -434,10 +435,12 @@ fail:
return false;
}
-static void angle_uninit(struct MPGLContext *ctx)
+static void angle_uninit(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+ ra_gl_ctx_uninit(ctx);
+
DwmEnableMMCSS(FALSE);
// Uninit the EGL surface implementation that is being used. Note: This may
@@ -474,17 +477,56 @@ static int GLAPIENTRY angle_swap_interval(int interval)
}
}
-static int angle_init(struct MPGLContext *ctx, int flags)
+static void d3d11_swap_buffers(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+
+ // Calling Present() on a flip-sequential swap chain will silently change
+ // the underlying storage of the back buffer to point to the next buffer in
+ // the chain. This results in the RTVs for the back buffer becoming
+ // unbound. Since ANGLE doesn't know we called Present(), it will continue
+ // using the unbound RTVs, so we must save and restore them ourselves.
+ ID3D11RenderTargetView *rtvs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
+ ID3D11DepthStencilView *dsv = NULL;
+ ID3D11DeviceContext_OMGetRenderTargets(p->d3d11_context,
+ MP_ARRAY_SIZE(rtvs), rtvs, &dsv);
+
+ HRESULT hr = IDXGISwapChain_Present(p->dxgi_swapchain, p->swapinterval, 0);
+ if (FAILED(hr))
+ MP_FATAL(ctx->vo, "Couldn't present: %s\n", mp_HRESULT_to_str(hr));
+
+ // Restore the RTVs and release the objects
+ ID3D11DeviceContext_OMSetRenderTargets(p->d3d11_context,
+ MP_ARRAY_SIZE(rtvs), rtvs, dsv);
+ for (int i = 0; i < MP_ARRAY_SIZE(rtvs); i++)
+ SAFE_RELEASE(rtvs[i]);
+ SAFE_RELEASE(dsv);
+}
+
+static void egl_swap_buffers(struct ra_ctx *ctx)
+{
+ struct priv *p = ctx->priv;
+ eglSwapBuffers(p->egl_display, p->egl_window);
+}
+
+static void angle_swap_buffers(struct ra_ctx *ctx)
+{
+ struct priv *p = ctx->priv;
+ if (p->dxgi_swapchain)
+ d3d11_swap_buffers(ctx);
+ else
+ egl_swap_buffers(ctx);
+}
+
+static bool angle_init(struct ra_ctx *ctx)
+{
+ struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
struct vo *vo = ctx->vo;
+ GL *gl = &p->gl;
p->opts = mp_get_config_group(ctx, ctx->global, &angle_conf);
struct angle_opts *o = p->opts;
- // DWM MMCSS cargo-cult. The dxinterop backend also does this.
- DwmEnableMMCSS(TRUE);
-
if (!angle_load()) {
MP_VERBOSE(vo, "Failed to load LIBEGL.DLL\n");
goto fail;
@@ -493,19 +535,19 @@ static int angle_init(struct MPGLContext *ctx, int flags)
// Create the underlying EGL device implementation
bool context_ok = false;
if ((!context_ok && !o->renderer) || o->renderer == RENDERER_D3D11) {
- context_ok = d3d11_device_create(ctx, flags);
+ context_ok = d3d11_device_create(ctx);
if (context_ok) {
- context_ok = context_init(ctx, flags);
+ context_ok = context_init(ctx);
if (!context_ok)
d3d11_device_destroy(ctx);
}
}
if ((!context_ok && !o->renderer) || o->renderer == RENDERER_D3D9) {
- context_ok = d3d9_device_create(ctx, flags);
+ context_ok = d3d9_device_create(ctx);
if (context_ok) {
MP_VERBOSE(vo, "Using Direct3D 9\n");
- context_ok = context_init(ctx, flags);
+ context_ok = context_init(ctx);
if (!context_ok)
d3d9_device_destroy(ctx);
}
@@ -519,34 +561,58 @@ static int angle_init(struct MPGLContext *ctx, int flags)
// Create the underlying EGL surface implementation
bool surface_ok = false;
if ((!surface_ok && o->egl_windowing == -1) || o->egl_windowing == 0) {
- surface_ok = d3d11_swapchain_surface_create(ctx, flags);
+ surface_ok = d3d11_swapchain_surface_create(ctx);
}
if ((!surface_ok && o->egl_windowing == -1) || o->egl_windowing == 1) {
- surface_ok = egl_window_surface_create(ctx, flags);
+ surface_ok = egl_window_surface_create(ctx);
if (surface_ok)
MP_VERBOSE(vo, "Using EGL windowing\n");
}
if (!surface_ok)
goto fail;
- mpegl_load_functions(ctx->gl, vo->log);
+ mpegl_load_functions(gl, vo->log);
current_ctx = ctx;
- ctx->gl->SwapInterval = angle_swap_interval;
+ gl->SwapInterval = angle_swap_interval;
+
+ // ANGLE doesn't actually need to override any of the functions (yet)
+ static const struct ra_swapchain_fns empty_swapchain_fns = {0};
+ struct ra_gl_ctx_params params = {
+ .swap_buffers = angle_swap_buffers,
+ .flipped = p->flipped,
+ .external_swapchain = p->dxgi_swapchain ? &empty_swapchain_fns : NULL,
+ };
- return 0;
+ if (!ra_gl_ctx_init(ctx, gl, params))
+ goto fail;
+
+ DwmEnableMMCSS(TRUE); // DWM MMCSS cargo-cult. The dxgl backend also does this.
+
+ return true;
fail:
angle_uninit(ctx);
- return -1;
+ return false;
+}
+
+static void resize(struct ra_ctx *ctx)
+{
+ struct priv *p = ctx->priv;
+ if (p->dxgi_swapchain)
+ d3d11_backbuffer_resize(ctx);
+ else
+ eglWaitClient(); // Should get ANGLE to resize its swapchain
+ ra_gl_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight, 0);
}
-static int angle_reconfig(struct MPGLContext *ctx)
+static bool angle_reconfig(struct ra_ctx *ctx)
{
vo_w32_config(ctx->vo);
- return 0;
+ resize(ctx);
+ return true;
}
-static struct mp_image *d3d11_screenshot(MPGLContext *ctx)
+static struct mp_image *d3d11_screenshot(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
ID3D11Texture2D *frontbuffer = NULL;
@@ -624,10 +690,8 @@ done:
return img;
}
-static int angle_control(MPGLContext *ctx, int *events, int request, void *arg)
+static int angle_control(struct ra_ctx *ctx, int *events, int request, void *arg)
{
- struct priv *p = ctx->priv;
-
// Try a D3D11-specific method of taking a window screenshot
if (request == VOCTRL_SCREENSHOT_WIN) {
struct mp_image *img = d3d11_screenshot(ctx);
@@ -637,63 +701,17 @@ static int angle_control(MPGLContext *ctx, int *events, int request, void *arg)
}
}
- int r = vo_w32_control(ctx->vo, events, request, arg);
- if (*events & VO_EVENT_RESIZE) {
- if (p->dxgi_swapchain)
- d3d11_backbuffer_resize(ctx);
- else
- eglWaitClient(); // Should get ANGLE to resize its swapchain
- }
- return r;
-}
-
-static void d3d11_swap_buffers(MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
-
- // Calling Present() on a flip-sequential swap chain will silently change
- // the underlying storage of the back buffer to point to the next buffer in
- // the chain. This results in the RTVs for the back buffer becoming
- // unbound. Since ANGLE doesn't know we called Present(), it will continue
- // using the unbound RTVs, so we must save and restore them ourselves.
- ID3D11RenderTargetView *rtvs[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {0};
- ID3D11DepthStencilView *dsv = NULL;
- ID3D11DeviceContext_OMGetRenderTargets(p->d3d11_context,
- MP_ARRAY_SIZE(rtvs), rtvs, &dsv);
-
- HRESULT hr = IDXGISwapChain_Present(p->dxgi_swapchain, p->swapinterval, 0);
- if (FAILED(hr))
- MP_FATAL(ctx->vo, "Couldn't present: %s\n", mp_HRESULT_to_str(hr));
-
- // Restore the RTVs and release the objects
- ID3D11DeviceContext_OMSetRenderTargets(p->d3d11_context,
- MP_ARRAY_SIZE(rtvs), rtvs, dsv);
- for (int i = 0; i < MP_ARRAY_SIZE(rtvs); i++)
- SAFE_RELEASE(rtvs[i]);
- SAFE_RELEASE(dsv);
-}
-
-static void egl_swap_buffers(MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- eglSwapBuffers(p->egl_display, p->egl_window);
-}
-
-static void angle_swap_buffers(MPGLContext *ctx)
-{
- struct priv *p = ctx->priv;
- if (p->dxgi_swapchain)
- d3d11_swap_buffers(ctx);
- else
- egl_swap_buffers(ctx);
+ int ret = vo_w32_control(ctx->vo, events, request, arg);
+ if (*events & VO_EVENT_RESIZE)
+ resize(ctx);
+ return ret;
}
-const struct mpgl_driver mpgl_driver_angle = {
+const struct ra_ctx_fns ra_ctx_angle = {
+ .type = "opengl",
.name = "angle",
- .priv_size = sizeof(struct priv),
.init = angle_init,
.reconfig = angle_reconfig,
- .swap_buffers = angle_swap_buffers,
.control = angle_control,
.uninit = angle_uninit,
};
diff --git a/video/out/opengl/context_cocoa.c b/video/out/opengl/context_cocoa.c
index cdf6faffcd..585c49f9a9 100644
--- a/video/out/opengl/context_cocoa.c
+++ b/video/out/opengl/context_cocoa.c
@@ -36,6 +36,7 @@ const struct m_sub_options cocoa_conf = {
};
struct priv {
+ GL gl;
CGLPixelFormatObj pix;
CGLContextObj ctx;
@@ -62,7 +63,7 @@ static void *cocoa_glgetaddr(const char *s)
return ret;
}
-static CGLError test_gl_version(struct MPGLContext *ctx, CGLOpenGLProfile ver)
+static CGLError test_gl_version(struct ra_ctx *ctx, CGLOpenGLProfile ver)
{
struct priv *p = ctx->priv;
@@ -107,9 +108,10 @@ error_out:
return err;
}
-static bool create_gl_context(struct MPGLContext *ctx, int vo_flags)
+static bool create_gl_context(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+ GL *gl = &p->gl;
CGLError err;
CGLOpenGLProfile gl_versions[] = {
@@ -132,60 +134,82 @@ static bool create_gl_context(struct MPGLContext *ctx, int vo_flags)
vo_cocoa_set_opengl_ctx(ctx->vo, p->ctx);
CGLSetCurrentContext(p->ctx);
- if (vo_flags & VOFLAG_ALPHA)
+ if (ctx->opts.want_alpha)
CGLSetParameter(p->ctx, kCGLCPSurfaceOpacity, &(GLint){0});
- mpgl_load_functions(ctx->gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log);
+ mpgl_load_functions(gl, (void *)cocoa_glgetaddr, NULL, ctx->vo->log);
+ gl->SwapInterval = set_swap_interval;
CGLReleasePixelFormat(p->pix);
return true;
}
-static void cocoa_uninit(MPGLContext *ctx)
+static void cocoa_uninit(struct ra_ctx *ctx)
{
struct priv *p = ctx->priv;
+ ra_gl_ctx_uninit(ctx);
CGLReleaseContext(p->ctx);
vo_cocoa_uninit(ctx->vo);
}
-static int cocoa_init(MPGLContext *ctx, int vo_flags)
+static void cocoa_swap_buffers(struct ra_ctx *ctx)
{
- struct priv *p = ctx->priv;
+ GL *gl = &p->gl;
+ vo_cocoa_swap_buffers(ctx->vo);
+ gl->Flush();
+}
+
+static bool cocoa_init(struct ra_ctx *ctx)
+{
+ struct priv *p = ctx->priv = talloc_zero(ctx, struct priv);
+ GL *gl = &p->gl;
p->opts = mp_get_config_group(ctx, ctx->global, &cocoa_conf);
vo_cocoa_init(ctx->vo);
- if (!create_gl_context(ctx, vo_flags))
- return -1;
+ if (!create_gl_context(ctx))
+ goto fail;
- ctx->gl->SwapInterval = set_swap_interval;
- return 0;
+ struct ra_gl_ctx_params params = {
+ .swap_buffers = cocoa_swap_buffers,
+ };
+
+ if (!ra_gl_ctx_init(ctx, gl, params))
+ goto fail;
+
+ return true;
+
+fail:
+ cocoa_uninit(ctx);
+ return false;
}
-static int cocoa_reconfig(struct MPGLContext *ctx)
+static void resize(struct ra_ctx *ctx)
{
- vo_cocoa_config_window(ctx->vo);
- return 0;
+ ra_gl_ctx_resize(ctx->swapchain, ctx->vo->dwidth, ctx->vo->dheight, 0);
}
-static int cocoa_control(struct MPGLContext *ctx, int *events, int request,
- void *arg)
+static bool cocoa_reconfig(struct ra_ctx *ctx)
{
- return vo_cocoa_control(ctx->vo, events, request, arg);
+ vo_cocoa_config_window(ctx->vo);
+ resize(ctx);
+ return true;
}
-static void cocoa_swap_buffers(struct MPGLContext *ctx)
+static int cocoa_control(struct ra_ctx *ctx, int *events, int request,
+ void *arg)
{
- vo_cocoa_swap_buffers(ctx->vo);
- ctx->gl->Flush();
+ int ret = vo_cocoa_control(ctx->vo, events, request, arg);
+ if (*events & VO_EVENT_RESIZE)
+ resize(ctx);
+ return ret;
}
-const struct mpgl_driver mpgl_driver_cocoa = {
+const struct ra_ctx_fns ra_ctx_cocoa = {
+ .type = "opengl",
.name = "cocoa",
- .priv_size = sizeof(struct priv),
.init = cocoa_init,
.reconfig = cocoa_reconfig,
- .swap_buffers = cocoa_swap_buffers,
.control = cocoa_control,
.uninit = cocoa_uninit,
};
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;
+