summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-08-05 19:40:57 +0200
committerwm4 <wm4@nowhere>2014-08-05 20:02:23 +0200
commit210c83ab31dd69c7a47c4b89d3a5fce78d4bedf2 (patch)
treee869f6270f502dd135fb3899895efae1dee21be0
parentafcbee8305e1d5c99012a6b9880b43b27b2d411a (diff)
downloadmpv-210c83ab31dd69c7a47c4b89d3a5fce78d4bedf2.tar.bz2
mpv-210c83ab31dd69c7a47c4b89d3a5fce78d4bedf2.tar.xz
win32: create OpenGL context on the GUI thread
This fixes the fullscreen issues on Intel for me. I'm baffled by it and don't understand why this suddenly works. Intel drivers being shit? Windows being shit? HWND or HDC being only 97% thread-safe instead of 98%? Me missing something subtle that is not documented anywhere? Who knows. Now instead of creating the HDC and OpenGL context on the renderer thread, they're created on the GUI thread. The renderer thread will then only call wglMakeCurrent, SwapBuffers, and OpenGL standard functions. Probably fixes github issue #968.
-rw-r--r--video/out/gl_w32.c45
-rw-r--r--video/out/w32_common.c6
-rw-r--r--video/out/w32_common.h1
3 files changed, 40 insertions, 12 deletions
diff --git a/video/out/gl_w32.c b/video/out/gl_w32.c
index 20d453bf3f..0be8ff0165 100644
--- a/video/out/gl_w32.c
+++ b/video/out/gl_w32.c
@@ -27,6 +27,7 @@
struct w32_context {
HGLRC context;
HDC hdc;
+ int flags;
};
static bool create_dc(struct MPGLContext *ctx, int flags)
@@ -193,6 +194,21 @@ out:
return false;
}
+static void create_ctx(void *ptr)
+{
+ struct MPGLContext *ctx = ptr;
+ struct w32_context *w32_ctx = ctx->priv;
+
+ if (!create_dc(ctx, w32_ctx->flags))
+ return;
+
+ if (ctx->requested_gl_version >= MPGL_VER(3, 0))
+ create_context_w32_gl3(ctx);
+ if (!w32_ctx->context)
+ create_context_w32_old(ctx);
+ wglMakeCurrent(w32_ctx->hdc, NULL);
+}
+
static bool config_window_w32(struct MPGLContext *ctx, int flags)
{
struct w32_context *w32_ctx = ctx->priv;
@@ -202,30 +218,35 @@ static bool config_window_w32(struct MPGLContext *ctx, int flags)
if (w32_ctx->context) // reuse existing context
return true;
- if (!create_dc(ctx, flags))
- return false;
+ w32_ctx->flags = flags;
+ vo_w32_run_on_thread(ctx->vo, create_ctx, ctx);
- bool success = false;
- if (ctx->requested_gl_version >= MPGL_VER(3, 0))
- success = create_context_w32_gl3(ctx);
- if (!success)
- success = create_context_w32_old(ctx);
- return success;
+ if (w32_ctx->context)
+ wglMakeCurrent(w32_ctx->hdc, w32_ctx->context);
+ return !!w32_ctx->context;
}
-static void releaseGlContext_w32(MPGLContext *ctx)
+static void destroy_gl(void *ptr)
{
+ struct MPGLContext *ctx = ptr;
struct w32_context *w32_ctx = ctx->priv;
- if (w32_ctx->context) {
- wglMakeCurrent(w32_ctx->hdc, 0);
+ if (w32_ctx->context)
wglDeleteContext(w32_ctx->context);
- }
w32_ctx->context = 0;
if (w32_ctx->hdc)
ReleaseDC(vo_w32_hwnd(ctx->vo), w32_ctx->hdc);
w32_ctx->hdc = NULL;
}
+static void releaseGlContext_w32(MPGLContext *ctx)
+{
+ struct MPGLContext *ctx = ptr;
+ struct w32_context *w32_ctx = ctx->priv;
+ if (w32_ctx->context)
+ wglMakeCurrent(w32_ctx->hdc, 0);
+ vo_w32_run_on_thread(ctx->vo, destroy_gl, ctx);
+}
+
static void swapGlBuffers_w32(MPGLContext *ctx)
{
struct w32_context *w32_ctx = ctx->priv;
diff --git a/video/out/w32_common.c b/video/out/w32_common.c
index 33b6cdfa63..bc2a700975 100644
--- a/video/out/w32_common.c
+++ b/video/out/w32_common.c
@@ -1202,3 +1202,9 @@ HWND vo_w32_hwnd(struct vo *vo)
struct vo_w32_state *w32 = vo->w32;
return w32->window; // immutable, so no synchronization needed
}
+
+void vo_w32_run_on_thread(struct vo *vo, void (*cb)(void *ctx), void *ctx)
+{
+ struct vo_w32_state *w32 = vo->w32;
+ mp_dispatch_run(w32->dispatch, cb, ctx);
+}
diff --git a/video/out/w32_common.h b/video/out/w32_common.h
index 9e72c4f260..d5c9f072b0 100644
--- a/video/out/w32_common.h
+++ b/video/out/w32_common.h
@@ -32,5 +32,6 @@ void vo_w32_uninit(struct vo *vo);
int vo_w32_control(struct vo *vo, int *events, int request, void *arg);
int vo_w32_config(struct vo *vo, uint32_t);
HWND vo_w32_hwnd(struct vo *vo);
+void vo_w32_run_on_thread(struct vo *vo, void (*cb)(void *ctx), void *ctx);
#endif /* MPLAYER_W32_COMMON_H */