mirror of https://github.com/mpv-player/mpv
vo_gpu: win: remove exclusive-fullscreen detection hack
This hack was part of a solution to VSync judder in desktop OpenGL on Windows. Rather than using blocking-SwapBuffers(), mpv could use DwmFlush() to wait for the image to be presented by the compositor. Since this would only work while the compositor was running, and the compositor was silently disabled when OpenGL entered exclusive fullscreen mode, mpv needed a way to detect exclusive fullscreen mode. The code that is being removed could detect exclusive fullscreen mode by checking the state of an undocumented mutex using undocumented native API functions, but because of how fragile it was, it was always meant to be removed when a better solution for accurate VSync in OpenGL was found. Since then, mpv got the dxinterop backend, which uses desktop OpenGL but has accurate VSync. It also got a native Direct3D 11 backend, which is a viable alternative to OpenGL on Windows. For people who are still using desktop OpenGL with WGL, there shouldn't be much of a difference, since mpv can use other API functions to detect exclusive fullscreen.
This commit is contained in:
parent
d13f9d0886
commit
3d8ca93d23
|
@ -21,7 +21,6 @@
|
||||||
|
|
||||||
#include "options/m_config.h"
|
#include "options/m_config.h"
|
||||||
#include "video/out/w32_common.h"
|
#include "video/out/w32_common.h"
|
||||||
#include "video/out/win32/exclusive_hack.h"
|
|
||||||
#include "context.h"
|
#include "context.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
@ -237,11 +236,6 @@ static bool compositor_active(struct ra_ctx *ctx)
|
||||||
if (FAILED(DwmGetCompositionTimingInfo(0, &info)))
|
if (FAILED(DwmGetCompositionTimingInfo(0, &info)))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Test if a program is running in exclusive fullscreen mode. If so, it's
|
|
||||||
// probably this one, so it's not getting redirected by the compositor.
|
|
||||||
if (mp_w32_is_in_exclusive_mode())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,97 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of mpv.
|
|
||||||
*
|
|
||||||
* mpv is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* mpv is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
#include <winternl.h>
|
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "exclusive_hack.h"
|
|
||||||
|
|
||||||
// Missing NT API definitions
|
|
||||||
typedef enum _MP_MUTANT_INFORMATION_CLASS {
|
|
||||||
MpMutantBasicInformation
|
|
||||||
} MP_MUTANT_INFORMATION_CLASS;
|
|
||||||
#define MUTANT_INFORMATION_CLASS MP_MUTANT_INFORMATION_CLASS
|
|
||||||
#define MutantBasicInformation MpMutantBasicInformation
|
|
||||||
|
|
||||||
typedef struct _MP_MUTANT_BASIC_INFORMATION {
|
|
||||||
LONG CurrentCount;
|
|
||||||
BOOLEAN OwnedByCaller;
|
|
||||||
BOOLEAN AbandonedState;
|
|
||||||
} MP_MUTANT_BASIC_INFORMATION;
|
|
||||||
#define MUTANT_BASIC_INFORMATION MP_MUTANT_BASIC_INFORMATION
|
|
||||||
|
|
||||||
static pthread_once_t internal_api_load_ran = PTHREAD_ONCE_INIT;
|
|
||||||
static bool internal_api_loaded = false;
|
|
||||||
|
|
||||||
static HANDLE excl_mode_mutex;
|
|
||||||
static NTSTATUS (NTAPI *pNtQueryMutant)(HANDLE MutantHandle,
|
|
||||||
MUTANT_INFORMATION_CLASS MutantInformationClass, PVOID MutantInformation,
|
|
||||||
ULONG MutantInformationLength, PULONG ReturnLength);
|
|
||||||
|
|
||||||
static void internal_api_load(void)
|
|
||||||
{
|
|
||||||
HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");
|
|
||||||
if (!ntdll)
|
|
||||||
return;
|
|
||||||
pNtQueryMutant = (void*)GetProcAddress(ntdll, "NtQueryMutant");
|
|
||||||
if (!pNtQueryMutant)
|
|
||||||
return;
|
|
||||||
excl_mode_mutex = OpenMutexW(MUTANT_QUERY_STATE, FALSE,
|
|
||||||
L"Local\\__DDrawExclMode__");
|
|
||||||
if (!excl_mode_mutex)
|
|
||||||
return;
|
|
||||||
|
|
||||||
internal_api_loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mp_w32_is_in_exclusive_mode(void)
|
|
||||||
{
|
|
||||||
pthread_once(&internal_api_load_ran, internal_api_load);
|
|
||||||
if (!internal_api_loaded)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// As far as we can tell, there is no way to know if a specific OpenGL
|
|
||||||
// program is being redirected by the DWM. It is possible, however, to
|
|
||||||
// know if some program on the computer is unredirected by the DWM, that
|
|
||||||
// is, whether some program is in exclusive fullscreen mode. Exclusive
|
|
||||||
// fullscreen programs acquire an undocumented mutex: __DDrawExclMode__. If
|
|
||||||
// this is acquired, it's probably by mpv. Even if it isn't, the penalty
|
|
||||||
// for incorrectly guessing true (dropped frames) is better than the
|
|
||||||
// penalty for incorrectly guessing false (tearing.)
|
|
||||||
|
|
||||||
// Testing this mutex is another problem. There is no public function for
|
|
||||||
// testing a mutex without attempting to acquire it, but that method won't
|
|
||||||
// work because if mpv is in fullscreen, the mutex will already be acquired
|
|
||||||
// by this thread (in ddraw.dll) and Windows will happily let it be
|
|
||||||
// acquired again. Instead, use the undocumented NtQueryMutant function to
|
|
||||||
// test the mutex.
|
|
||||||
|
|
||||||
// Note: SHQueryUserNotificationState uses this mutex internally, but it is
|
|
||||||
// probably not suitable because it sends a message to the shell instead of
|
|
||||||
// testing the mutex directly. mpv will check for exclusive mode once per
|
|
||||||
// frame, so if the shell is not running or not responding, it may cause
|
|
||||||
// performance issues.
|
|
||||||
|
|
||||||
MUTANT_BASIC_INFORMATION mbi;
|
|
||||||
NTSTATUS s = pNtQueryMutant(excl_mode_mutex, MutantBasicInformation, &mbi,
|
|
||||||
sizeof mbi, NULL);
|
|
||||||
if (!NT_SUCCESS(s))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return !mbi.CurrentCount;
|
|
||||||
}
|
|
|
@ -1,26 +0,0 @@
|
||||||
/*
|
|
||||||
* This file is part of mpv.
|
|
||||||
*
|
|
||||||
* mpv is free software; you can redistribute it and/or
|
|
||||||
* modify it under the terms of the GNU Lesser General Public
|
|
||||||
* License as published by the Free Software Foundation; either
|
|
||||||
* version 2.1 of the License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* mpv is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Lesser General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
|
||||||
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MP_WIN32_EXCLUSIVE_HACK_H_
|
|
||||||
#define MP_WIN32_EXCLUSIVE_HACK_H_
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
|
|
||||||
// Returns true if any program on the computer is in exclusive fullscreen mode
|
|
||||||
bool mp_w32_is_in_exclusive_mode(void);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -458,7 +458,6 @@ def build(ctx):
|
||||||
( "video/out/vulkan/context_wayland.c", "vulkan && wayland" ),
|
( "video/out/vulkan/context_wayland.c", "vulkan && wayland" ),
|
||||||
( "video/out/vulkan/context_win.c", "vulkan && win32-desktop" ),
|
( "video/out/vulkan/context_win.c", "vulkan && win32-desktop" ),
|
||||||
( "video/out/vulkan/spirv_nvidia.c", "vulkan" ),
|
( "video/out/vulkan/spirv_nvidia.c", "vulkan" ),
|
||||||
( "video/out/win32/exclusive_hack.c", "gl-win32" ),
|
|
||||||
( "video/out/wayland_common.c", "wayland" ),
|
( "video/out/wayland_common.c", "wayland" ),
|
||||||
( "video/out/wayland/xdg-shell-v6.c", "wayland" ),
|
( "video/out/wayland/xdg-shell-v6.c", "wayland" ),
|
||||||
( "video/out/wayland/idle-inhibit-v1.c", "wayland" ),
|
( "video/out/wayland/idle-inhibit-v1.c", "wayland" ),
|
||||||
|
|
Loading…
Reference in New Issue