mirror of
https://github.com/mpv-player/mpv
synced 2025-01-09 00:19:32 +00:00
vo_opengl: win32: try to enable DwmFlush by default
Enable it by default, but not unconditionally. Add an "auto" mode, which disable DwmFlush if the compositor is (probably) inactive. Let's see how this goes. Since I accidentally enabled DwmFlush always by default (more or less) in a previous commit touching this code, this is probably mostly just cargo-culting, and it's uncertain whether it does anything. Note that I still got bad vsync behavior when fullscreening mpv, and making another window visible on the same screen. This happens even if forcing DWM.
This commit is contained in:
parent
f1e767b6a2
commit
30a6106477
@ -676,11 +676,15 @@ Available video output drivers are:
|
||||
the number of frames the GPU queues ahead (which also has an influence
|
||||
on vsync).
|
||||
|
||||
``dwmflush=<no|windowed|yes>``
|
||||
Calls ``DwmFlush`` after swapping buffers on Windows (default: no).
|
||||
``dwmflush=<no|windowed|yes|auto>``
|
||||
Calls ``DwmFlush`` after swapping buffers on Windows (default: auto).
|
||||
It also sets ``SwapInterval(0)`` to ignore the OpenGL timing. Values
|
||||
are: no (disabled), windowed (only in windowed mode), yes (also in
|
||||
full screen).
|
||||
|
||||
The value ``auto`` will try to determine whether the compositor is
|
||||
active, and calls ``DwmFlush`` only if it seems to be.
|
||||
|
||||
This may help getting more consistent frame intervals, especially with
|
||||
high-fps clips - which might also reduce dropped frames. Typically a
|
||||
value of ``windowed`` should be enough since full screen may bypass the
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <Dwmapi.h>
|
||||
#include "video/out/w32_common.h"
|
||||
#include "common.h"
|
||||
|
||||
@ -36,7 +37,11 @@ struct w32_context {
|
||||
int flags;
|
||||
|
||||
HINSTANCE dwmapi_dll;
|
||||
HRESULT (WINAPI *dwmflush)(void);
|
||||
HRESULT (WINAPI *pDwmFlush)(void);
|
||||
HRESULT (WINAPI *pDwmIsCompositionEnabled)(BOOL *pfEnabled);
|
||||
HRESULT (WINAPI *pDwmEnableMMCSS)(BOOL fEnableMMCSS);
|
||||
HRESULT (WINAPI *pDwmGetCompositionTimingInfo)
|
||||
(HWND hwnd, DWM_TIMING_INFO *pTimingInfo);
|
||||
};
|
||||
|
||||
static void w32_uninit(MPGLContext *ctx);
|
||||
@ -223,8 +228,15 @@ static void create_ctx(void *ptr)
|
||||
create_context_w32_old(ctx);
|
||||
|
||||
w32_ctx->dwmapi_dll = LoadLibrary(L"Dwmapi.dll");
|
||||
if (w32_ctx->dwmapi_dll)
|
||||
w32_ctx->dwmflush = (void *)GetProcAddress(w32_ctx->dwmapi_dll, "DwmFlush");
|
||||
if (w32_ctx->dwmapi_dll) {
|
||||
w32_ctx->pDwmFlush = (void *)GetProcAddress(w32_ctx->dwmapi_dll, "DwmFlush");
|
||||
w32_ctx->pDwmIsCompositionEnabled =
|
||||
(void *)GetProcAddress(w32_ctx->dwmapi_dll, "DwmIsCompositionEnabled");
|
||||
w32_ctx->pDwmGetCompositionTimingInfo =
|
||||
(void *)GetProcAddress(w32_ctx->dwmapi_dll, "DwmGetCompositionTimingInfo");
|
||||
w32_ctx->pDwmEnableMMCSS =
|
||||
(void *)GetProcAddress(w32_ctx->dwmapi_dll, "DwmEnableMMCSS");
|
||||
}
|
||||
|
||||
wglMakeCurrent(w32_ctx->hdc, NULL);
|
||||
}
|
||||
@ -289,6 +301,28 @@ static void w32_uninit(MPGLContext *ctx)
|
||||
vo_w32_uninit(ctx->vo);
|
||||
}
|
||||
|
||||
static bool compositor_active(MPGLContext *ctx)
|
||||
{
|
||||
struct w32_context *w32_ctx = ctx->priv;
|
||||
|
||||
if (!w32_ctx->pDwmIsCompositionEnabled || !w32_ctx->pDwmGetCompositionTimingInfo)
|
||||
return false;
|
||||
|
||||
// For Windows 7.
|
||||
BOOL enabled = 0;
|
||||
if (FAILED(w32_ctx->pDwmIsCompositionEnabled(&enabled)) || !enabled)
|
||||
return false;
|
||||
|
||||
// This works at least on Windows 8.1: it returns an error in fullscreen,
|
||||
// which is also when we get consistent timings without DwmFlush. Might
|
||||
// be cargo-cult.
|
||||
DWM_TIMING_INFO info = { .cbSize = sizeof(DWM_TIMING_INFO) };
|
||||
if (FAILED(w32_ctx->pDwmGetCompositionTimingInfo(0, &info)))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void w32_swap_buffers(MPGLContext *ctx)
|
||||
{
|
||||
struct w32_context *w32_ctx = ctx->priv;
|
||||
@ -297,11 +331,14 @@ static void w32_swap_buffers(MPGLContext *ctx)
|
||||
// default if we don't DwmFLush
|
||||
int new_swapinterval = w32_ctx->opt_swapinterval;
|
||||
|
||||
if (w32_ctx->dwmflush && w32_ctx->dwmflush() == S_OK &&
|
||||
((ctx->dwm_flush_opt == 1 && !ctx->vo->opts->fullscreen) ||
|
||||
ctx->dwm_flush_opt == 2))
|
||||
{
|
||||
new_swapinterval = 0;
|
||||
if (ctx->dwm_flush_opt >= 0) {
|
||||
if ((ctx->dwm_flush_opt == 1 && !ctx->vo->opts->fullscreen) ||
|
||||
(ctx->dwm_flush_opt == 2) ||
|
||||
(ctx->dwm_flush_opt == 0 && compositor_active(ctx)))
|
||||
{
|
||||
if (w32_ctx->pDwmFlush && w32_ctx->pDwmFlush() == S_OK)
|
||||
new_swapinterval = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (new_swapinterval != w32_ctx->current_swapinterval &&
|
||||
|
@ -460,7 +460,7 @@ static const struct m_option options[] = {
|
||||
OPT_FLAG("waitvsync", waitvsync, 0),
|
||||
OPT_INT("swapinterval", swap_interval, 0, OPTDEF_INT(1)),
|
||||
OPT_CHOICE("dwmflush", dwm_flush, 0,
|
||||
({"no", 0}, {"windowed", 1}, {"yes", 2})),
|
||||
({"no", -1}, {"auto", 0}, {"windowed", 1}, {"yes", 2})),
|
||||
OPT_FLAG("debug", use_gl_debug, 0),
|
||||
OPT_STRING_VALIDATE("backend", backend, 0, mpgl_validate_backend_opt),
|
||||
OPT_FLAG("sw", allow_sw, 0),
|
||||
|
Loading…
Reference in New Issue
Block a user