1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-23 11:47:45 +00:00

opengl: win32 - add option 'dwmflush' to sync in DWM

This could help in cases where the DWM (Windows desktop compositor) adds another
layer of bufferring and therefore the SwapBuffers timing could get messed up.

Signed-off-by: wm4 <wm4@nowhere>
This commit is contained in:
Avi Halachmi (:avih) 2015-03-17 01:15:28 +02:00 committed by wm4
parent c97f014576
commit 843bc822a8
4 changed files with 69 additions and 0 deletions

View File

@ -548,6 +548,16 @@ Available video output drivers are:
X11/GLX only.
``dwmflush``
Calls ``DwmFlush`` after swapping buffers on Windows (default: 0).
It also sets ``SwapInterval(0)`` to ignore the OpenGL timing. Values
are: 0 (disabled), 1 (only in windowed mode), 2 (also in full screen).
This may help getting more consistent frame intervals, especially with
high-fps clips - which might also reduce dropped frames. Typically a
value of 1 should be enough since full screen may bypass the DWM.
Windows only.
``sw``
Continue even if a software renderer is detected.

View File

@ -93,6 +93,12 @@ typedef struct MPGLContext {
void (*releaseGlContext)(struct MPGLContext *);
void (*set_current)(struct MPGLContext *, bool current);
// Used on windows only, tries to vsync with the DWM, and modifies SwapInterval
// when it does so. Returns the possibly modified swapinterval value.
int (*DwmFlush)(struct MPGLContext *, int opt_dwmflush,
int opt_swapinterval, int current_swapinterval);
// Resize the window, or create a new window if there isn't one yet.
// On the first call, it creates a GL context according to what's specified
// in MPGLContext.requested_gl_version. This is just a hint, and if the

View File

@ -24,10 +24,15 @@
#include "w32_common.h"
#include "gl_common.h"
typedef HRESULT (WINAPI *DwmFlush_t)(void);
struct w32_context {
HGLRC context;
HDC hdc;
int flags;
HINSTANCE dwmapi_dll;
DwmFlush_t dwmflush;
};
static bool create_dc(struct MPGLContext *ctx, int flags)
@ -202,6 +207,11 @@ static void create_ctx(void *ptr)
create_context_w32_gl3(ctx);
if (!w32_ctx->context)
create_context_w32_old(ctx);
w32_ctx->dwmapi_dll = LoadLibrary(L"Dwmapi.dll");
if (w32_ctx->dwmapi_dll)
w32_ctx->dwmflush = (DwmFlush_t)GetProcAddress(w32_ctx->dwmapi_dll, "DwmFlush");
wglMakeCurrent(w32_ctx->hdc, NULL);
}
@ -240,6 +250,11 @@ static void releaseGlContext_w32(MPGLContext *ctx)
if (w32_ctx->context)
wglMakeCurrent(w32_ctx->hdc, 0);
vo_w32_run_on_thread(ctx->vo, destroy_gl, ctx);
w32_ctx->dwmflush = NULL;
if (w32_ctx->dwmapi_dll)
FreeLibrary(w32_ctx->dwmapi_dll);
w32_ctx->dwmapi_dll = NULL;
}
static void swapGlBuffers_w32(MPGLContext *ctx)
@ -248,6 +263,32 @@ static void swapGlBuffers_w32(MPGLContext *ctx)
SwapBuffers(w32_ctx->hdc);
}
// opt_dwmflush: 0 - never DwmFlush, 1 - only in windowed mode, 2 - always
// return: the current (applied if modified) SwapInterval value.
// DwmFlush waits on DWM vsync similar to SwapBuffers but a bit more noisy.
// SwapBuffers still needs to be called, but we SwapInterval(0) when DwmFLush is
// used (will get applied for the following SwapBuffers calls)
static int DwmFlush_w32(MPGLContext *ctx, int opt_dwmflush,
int opt_swapinterval, int current_swapinterval)
{
struct w32_context *w32_ctx = ctx->priv;
int new_swapinterval = opt_swapinterval; // default if we don't DwmFLush
if (w32_ctx->dwmflush &&
(opt_dwmflush == 2 || (opt_dwmflush == 1 && !ctx->vo->opts->fullscreen)) &&
S_OK == w32_ctx->dwmflush())
{
new_swapinterval = 0;
}
if ((new_swapinterval != current_swapinterval) && ctx->gl->SwapInterval) {
ctx->gl->SwapInterval(new_swapinterval);
MP_VERBOSE(ctx->vo, "DwmFlush: set SwapInterval(%d)\n", new_swapinterval);
}
return new_swapinterval;
}
void mpgl_set_backend_w32(MPGLContext *ctx)
{
ctx->priv = talloc_zero(ctx, struct w32_context);
@ -257,4 +298,5 @@ void mpgl_set_backend_w32(MPGLContext *ctx)
ctx->vo_init = vo_w32_init;
ctx->vo_uninit = vo_w32_uninit;
ctx->vo_control = vo_w32_control;
ctx->DwmFlush = DwmFlush_w32;
}

View File

@ -72,6 +72,9 @@ struct gl_priv {
int use_gl_debug;
int allow_sw;
int swap_interval;
int current_swap_interval;
int dwm_flush;
char *backend;
int vo_flipped;
@ -154,6 +157,12 @@ static void flip_page(struct vo *vo)
}
}
if (p->glctx->DwmFlush) {
p->current_swap_interval = p->glctx->DwmFlush(p->glctx, p->dwm_flush,
p->swap_interval,
p->current_swap_interval);
}
mpgl_unlock(p->glctx);
}
@ -463,6 +472,7 @@ static int preinit(struct vo *vo)
} else {
MP_VERBOSE(vo, "swap_control extension missing.\n");
}
p->current_swap_interval = p->swap_interval;
p->renderer = gl_video_init(p->gl, vo->log);
if (!p->renderer)
@ -498,6 +508,7 @@ static const struct m_option options[] = {
OPT_FLAG("glfinish", use_glFinish, 0),
OPT_FLAG("waitvsync", waitvsync, 0),
OPT_INT("swapinterval", swap_interval, 0, OPTDEF_INT(1)),
OPT_INT("dwmflush", dwm_flush, 0, OPTDEF_INT(0)),
OPT_FLAG("debug", use_gl_debug, 0),
OPT_STRING_VALIDATE("backend", backend, 0, mpgl_validate_backend_opt),
OPT_FLAG("sw", allow_sw, 0),