mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-08 08:10:30 -10:00
win32: the window can be kept across a video driver restart
A restart of the video driver - content loaded or closed, a setting
changed - destroyed the window and made another. The window vanished
and came back, lost its place in front of other windows (cd6b6b5ad
works around that), and the driver that came back was nearly always
the one that had left, with no need of a new window at all.
With RETROARCH_WINDOW_KEEP=1 in the environment, the context being
freed leaves its window up, win32_window_keep(), and
win32_window_create() takes it instead of making one: the style, place
and size it would have been created with are applied to it, and what
creating a window sets up for the video family - the Vulkan surface -
is done for it. A windowed window stays where it is.
A window belongs to the thread that made it. With threaded video that
is the video thread, which is now held for the next driver (the commit
before this). Where the next driver cannot take the window - it runs
on another thread, it is of another family, none comes - the window is
taken down by its own thread: at once if that is the thread making the
new window, otherwise by win32_window_release_kept(), which the
frontend calls when the next driver is up or has failed to come up,
and which ends a held video thread to do it. Destroying a window that
was left up is not taken for the program being closed, which
WM_DESTROY otherwise means.
Kept by the Vulkan and the GDI families. Not kept when the program is
shutting down, nor from exclusive fullscreen with the display's mode
changed.
It is off unless asked for because it has not been run on Windows. On
Windows the next step, once it has, is to make it the default and take
the foreground workaround out.
win32_window_init() no longer fails when the window class is still
registered, which it is while a window is kept.
samples/input/windows_wine_smoke, three more scenarios, through a
fullscreen toggle and a content close: the window left up and taken
back twice, with threaded video and without; and left up and not taken
(RETROARCH_WINDOW_KEEP=2, which exists for this), where it is
destroyed, a new one made, and RetroArch keeps running. All eight
scenarios pass with retroarch.exe built from this. Under Wine the
window's position and size at each stage are the same kept as new,
windowed to fullscreen and back.
That is GDI under Wine. Vulkan on the kept window - a surface made on
a window that has had one - has not been run anywhere.
This commit is contained in:
1 parent
7e65caf284
commit
2cb7874f78
8 files changed
+294
-5
No files matched your search
@@ -15,6 +15,9 @@ name: CI Windows raw input under Wine
|
||||
# (the default); restarted with the video driver
|
||||
# (RETROARCH_INPUT_KEEP=0); threaded video off; the raw driver as it
|
||||
# was before any of this (RETROARCH_RAWINPUT_POLL=0); and DirectInput.
|
||||
# Three more are about the window: left up across both restarts and
|
||||
# taken back, with threaded video and without
|
||||
# (RETROARCH_WINDOW_KEEP=1), and left up and then not taken (=2).
|
||||
# See samples/input/windows_wine_smoke/run.sh.
|
||||
#
|
||||
# Wine is not Windows: what this holds is that the frontend, the pump,
|
||||
|
||||
+243
-2
@@ -132,6 +132,10 @@ typedef char win32_dwm_timing_info_size_check[
|
||||
#include "../../paths.h"
|
||||
#include "../../retroarch.h"
|
||||
#include "../video_driver.h"
|
||||
#ifdef HAVE_THREADS
|
||||
#include "../video_thread_wrapper.h"
|
||||
#endif
|
||||
#include "../../runloop.h"
|
||||
#include "../../audio/audio_driver.h"
|
||||
#include "../../tasks/task_content.h"
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
@@ -191,6 +195,17 @@ const GUID GUID_DEVINTERFACE_HID = { 0x4d1e55b2, 0xf16f, 0x11Cf, { 0x88, 0xcb, 0
|
||||
static HDEVNOTIFY notification_handler;
|
||||
#endif
|
||||
|
||||
/* A window left up across a driver restart (see win32_window_keep()),
|
||||
* and one of those on its way out: destroying it is not the program
|
||||
* being closed. */
|
||||
static HWND win32_kept_hwnd;
|
||||
static DWORD win32_kept_tid;
|
||||
static int win32_kept_family;
|
||||
static HWND win32_retiring_hwnd;
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x501
|
||||
static HDEVNOTIFY win32_kept_notification;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DINPUT
|
||||
extern bool dinput_handle_message(void *dinput, UINT message,
|
||||
WPARAM wParam, LPARAM lParam);
|
||||
@@ -976,6 +991,10 @@ static LRESULT CALLBACK wnd_proc_common(
|
||||
case WM_CLOSE:
|
||||
case WM_DESTROY:
|
||||
case WM_QUIT:
|
||||
/* a window that was left up for a driver that did not take
|
||||
* it, being taken down */
|
||||
if (hwnd && hwnd == win32_retiring_hwnd)
|
||||
break;
|
||||
#if !defined(_XBOX)
|
||||
win32_sizemove_abort();
|
||||
#endif
|
||||
@@ -1641,6 +1660,168 @@ void win32_window_proc_setup(enum win32_window_family family)
|
||||
(void)settings;
|
||||
}
|
||||
|
||||
/* The window across a driver restart.
|
||||
*
|
||||
* A restart of the video driver - content loaded or closed, a setting
|
||||
* changed - used to destroy the window and make another: the window
|
||||
* vanished and came back, lost its place in front of other windows,
|
||||
* and anything tied to it went with it. The driver that comes back is
|
||||
* nearly always the one that left, and has no need of a new window.
|
||||
*
|
||||
* So the context being freed may leave its window up
|
||||
* (win32_window_keep()), and win32_window_create() takes it instead of
|
||||
* making one: the style, place and size it would have been created
|
||||
* with are applied to it, and what creating a window sets up for the
|
||||
* video family - for Vulkan, the surface - is done for it.
|
||||
*
|
||||
* A window belongs to the thread that made it: only that thread can
|
||||
* take it back, or destroy it, and it goes when the thread ends. With
|
||||
* threaded video that thread is the video thread, which used to end
|
||||
* with the driver; it is held for the next one
|
||||
* (video_thread_host_hold()). If the driver that comes next runs on
|
||||
* another thread, or is of another kind, or does not come, the window
|
||||
* is taken down: win32_window_release_kept(), which the frontend
|
||||
* calls once the next driver is up.
|
||||
*
|
||||
* For the Vulkan and the GDI families, for now - the ones whose
|
||||
* window sets up nothing a second driver of the same family cannot
|
||||
* set up again on the same window - and only with
|
||||
* RETROARCH_WINDOW_KEEP=1 in the environment until it has been run on
|
||||
* Windows. Never when the program is shutting down. */
|
||||
static bool win32_window_family_keeps(void)
|
||||
{
|
||||
return win32_wnd_family == WIN32_WINDOW_VULKAN
|
||||
|| win32_wnd_family == WIN32_WINDOW_GDI;
|
||||
}
|
||||
|
||||
static void win32_window_destroy_kept(HWND hwnd)
|
||||
{
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x501
|
||||
if (win32_kept_notification)
|
||||
UnregisterDeviceNotification(win32_kept_notification);
|
||||
win32_kept_notification = NULL;
|
||||
#endif
|
||||
win32_retiring_hwnd = hwnd;
|
||||
DestroyWindow(hwnd);
|
||||
win32_retiring_hwnd = NULL;
|
||||
}
|
||||
|
||||
/* RETROARCH_WINDOW_KEEP: 1 leaves the window up and takes it back; 2
|
||||
* leaves it up and then does not take it, so that the way out for a
|
||||
* window nothing takes can be run (the tests do); anything else, or
|
||||
* nothing, destroys it with the driver as before. */
|
||||
static int win32_window_keep_mode(void)
|
||||
{
|
||||
const char *env = getenv("RETROARCH_WINDOW_KEEP");
|
||||
if (env && (env[0] == '1' || env[0] == '2'))
|
||||
return env[0] - '0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* the hook of video_thread_host_hold(): the video thread is ending
|
||||
* with the kept window still on it */
|
||||
static void win32_window_kept_thread_ends(void)
|
||||
{
|
||||
HWND hwnd = win32_kept_hwnd;
|
||||
if (hwnd && win32_kept_tid == GetCurrentThreadId())
|
||||
{
|
||||
win32_kept_hwnd = NULL;
|
||||
win32_window_destroy_kept(hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
bool win32_window_keep(void)
|
||||
{
|
||||
HWND hwnd = main_window.hwnd;
|
||||
|
||||
if ( !hwnd
|
||||
|| win32_kept_hwnd
|
||||
|| !win32_window_keep_mode()
|
||||
|| !win32_window_family_keeps()
|
||||
/* the display's mode was changed for it: put back as ever */
|
||||
|| (g_win32_flags & WIN32_CMN_FLAG_RESTORE_DESKTOP)
|
||||
|| (runloop_get_flags() & RUNLOOP_FLAG_SHUTDOWN_INITIATED))
|
||||
return false;
|
||||
/* it lasts only as long as its thread does */
|
||||
if (!task_is_on_main_thread())
|
||||
{
|
||||
#ifdef HAVE_THREADS
|
||||
if (!video_thread_host_hold(win32_window_kept_thread_ends))
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
win32_monitor_last = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
win32_kept_hwnd = hwnd;
|
||||
win32_kept_tid = GetCurrentThreadId();
|
||||
win32_kept_family = (int)win32_wnd_family;
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x501
|
||||
win32_kept_notification = notification_handler;
|
||||
notification_handler = NULL;
|
||||
#endif
|
||||
main_window.hwnd = NULL;
|
||||
video_driver_window_set(0);
|
||||
RARCH_LOG("[Win32] The window is left up for the next video driver.\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void win32_window_release_kept(void)
|
||||
{
|
||||
HWND hwnd = win32_kept_hwnd;
|
||||
|
||||
if (!hwnd)
|
||||
return;
|
||||
if (!IsWindow(hwnd))
|
||||
win32_kept_hwnd = NULL;
|
||||
else if (win32_kept_tid == GetCurrentThreadId())
|
||||
{
|
||||
win32_kept_hwnd = NULL;
|
||||
win32_window_destroy_kept(hwnd);
|
||||
}
|
||||
#ifdef HAVE_THREADS
|
||||
else if (video_thread_host_is_held())
|
||||
/* its thread takes it down as it ends */
|
||||
video_thread_host_stop();
|
||||
#endif
|
||||
else
|
||||
return; /* its own thread's to let go of */
|
||||
|
||||
RARCH_LOG("[Win32] The window left up was not taken: destroyed.\n");
|
||||
if (!main_window.hwnd)
|
||||
UnregisterClass("RetroArch", GetModuleHandle(NULL));
|
||||
}
|
||||
|
||||
/* The kept window, if this thread can have it and the family is the
|
||||
* one it was kept by. One this thread cannot use but can destroy
|
||||
* goes here. */
|
||||
static HWND win32_window_take_kept(void)
|
||||
{
|
||||
HWND hwnd = win32_kept_hwnd;
|
||||
|
||||
if (!hwnd)
|
||||
return NULL;
|
||||
if (!IsWindow(hwnd))
|
||||
{
|
||||
win32_kept_hwnd = NULL;
|
||||
return NULL;
|
||||
}
|
||||
if (win32_kept_tid != GetCurrentThreadId())
|
||||
return NULL;
|
||||
win32_kept_hwnd = NULL;
|
||||
if ( (int)win32_wnd_family != win32_kept_family
|
||||
|| win32_window_keep_mode() != 1)
|
||||
{
|
||||
win32_window_destroy_kept(hwnd);
|
||||
RARCH_LOG("[Win32] The window left up is not one this driver takes: destroyed.\n");
|
||||
return NULL;
|
||||
}
|
||||
#if defined(_WIN32_WINNT) && _WIN32_WINNT >= 0x501
|
||||
notification_handler = win32_kept_notification;
|
||||
win32_kept_notification = NULL;
|
||||
#endif
|
||||
return hwnd;
|
||||
}
|
||||
|
||||
static bool win32_window_create(void *data, unsigned style,
|
||||
RECT *mon_rect, unsigned width,
|
||||
unsigned height, bool fullscreen)
|
||||
@@ -1663,11 +1844,58 @@ static bool win32_window_create(void *data, unsigned style,
|
||||
wchar_t *title_local = utf8_to_utf16_string_alloc(new_label);
|
||||
#endif
|
||||
|
||||
bool reused = false;
|
||||
|
||||
if (window_save_positions && !fullscreen)
|
||||
{
|
||||
user_width = VIDEO_SCALE_W(g_win32->pos_dims);
|
||||
user_height = VIDEO_SCALE_H(g_win32->pos_dims);
|
||||
}
|
||||
|
||||
if ((main_window.hwnd = win32_window_take_kept()))
|
||||
{
|
||||
HWND hwnd = main_window.hwnd;
|
||||
HMENU menu = GetMenu(hwnd);
|
||||
bool was_popup = (GetWindowLongPtr(hwnd, GWL_STYLE) & WS_POPUP) != 0;
|
||||
UINT swp = SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED;
|
||||
int x = mon_rect->left;
|
||||
int y = mon_rect->top;
|
||||
|
||||
reused = true;
|
||||
free(title_local);
|
||||
|
||||
/* win32_set_window() gives a windowed window its menu again */
|
||||
if (menu)
|
||||
{
|
||||
SetMenu(hwnd, NULL);
|
||||
DestroyMenu(menu);
|
||||
}
|
||||
/* The style, place and size it would have been created with. A
|
||||
* windowed window stays where it is - unless it was fullscreen,
|
||||
* and is put where a new one would have been as far as that can
|
||||
* be said: at its saved position, or over the monitor's corner. */
|
||||
if (!fullscreen)
|
||||
{
|
||||
if (!was_popup)
|
||||
swp |= SWP_NOMOVE;
|
||||
else if (g_win32->pos_set)
|
||||
{
|
||||
x = VIDEO_POS_X(g_win32->pos);
|
||||
y = VIDEO_POS_Y(g_win32->pos);
|
||||
}
|
||||
}
|
||||
SetWindowLongPtr(hwnd, GWL_STYLE,
|
||||
(LONG_PTR)style
|
||||
| (IsWindowVisible(hwnd) ? WS_VISIBLE : 0));
|
||||
SetWindowPos(hwnd, NULL, x, y, user_width, user_height, swp);
|
||||
|
||||
/* what creating it sets up for the video family */
|
||||
g_win32_flags &= ~WIN32_CMN_FLAG_INITED;
|
||||
win32_window_proc(hwnd, WM_CREATE, 0, 0);
|
||||
RARCH_LOG("[Win32] Took the window left up by the last video driver.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef LEGACY_WIN32
|
||||
main_window.hwnd = CreateWindowEx(0,
|
||||
"RetroArch", title_local,
|
||||
@@ -1686,6 +1914,7 @@ static bool win32_window_create(void *data, unsigned style,
|
||||
user_height,
|
||||
NULL, NULL, NULL, data);
|
||||
free(title_local);
|
||||
}
|
||||
if (!main_window.hwnd)
|
||||
return false;
|
||||
|
||||
@@ -1699,8 +1928,10 @@ static bool win32_window_create(void *data, unsigned style,
|
||||
notification_filter.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
||||
notification_filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
notification_filter.dbcc_classguid = GUID_DEVINTERFACE_HID;
|
||||
notification_handler = RegisterDeviceNotification(
|
||||
main_window.hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
/* a window taken back is still registered */
|
||||
if (!reused)
|
||||
notification_handler = RegisterDeviceNotification(
|
||||
main_window.hwnd, ¬ification_filter, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
|
||||
if (!notification_handler)
|
||||
RARCH_ERR("[Win32] Error registering for notifications.\n");
|
||||
@@ -2683,6 +2914,16 @@ bool win32_window_init(WNDCLASSEX *wndclass,
|
||||
d3dkmt_init();
|
||||
#endif
|
||||
|
||||
/* still registered, for a window left up across the restart
|
||||
* (win32_window_keep()): one procedure serves every family, so
|
||||
* the class is the same one */
|
||||
{
|
||||
WNDCLASSEX has;
|
||||
has.cbSize = sizeof(has);
|
||||
if (GetClassInfoEx(wndclass->hInstance, wndclass->lpszClassName, &has))
|
||||
return true;
|
||||
}
|
||||
|
||||
return RegisterClassEx(wndclass);
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,15 @@ void win32_window_reset(void);
|
||||
|
||||
void win32_destroy_window(void);
|
||||
|
||||
/* Leaves the window up for the video driver that comes next instead of
|
||||
* destroying it; win32_set_video_mode() then takes it rather than make
|
||||
* one. False if it cannot be left - the caller destroys it as before. */
|
||||
bool win32_window_keep(void);
|
||||
|
||||
/* A window left up that the next driver did not take goes. Called
|
||||
* once that driver is up, or has failed to come up. */
|
||||
void win32_window_release_kept(void);
|
||||
|
||||
uint8_t win32_get_flags(void);
|
||||
|
||||
/* Re-read the synchronous keyboard state and publish it as a
|
||||
|
||||
@@ -2337,7 +2337,8 @@ static void gfx_ctx_gdi_destroy(void)
|
||||
win32_gdi_hdc = NULL;
|
||||
}
|
||||
|
||||
if (window)
|
||||
/* left up for the driver that comes next, where it can be */
|
||||
if (window && !win32_window_keep())
|
||||
{
|
||||
win32_monitor_from_window();
|
||||
win32_destroy_window();
|
||||
|
||||
@@ -162,7 +162,8 @@ static void gfx_ctx_w_vk_destroy(void *data)
|
||||
slock_free(win32_vk.context.queue_lock);
|
||||
memset(&win32_vk, 0, sizeof(win32_vk));
|
||||
|
||||
if (window)
|
||||
/* left up for the driver that comes next, where it can be */
|
||||
if (window && !win32_window_keep())
|
||||
{
|
||||
win32_monitor_from_window();
|
||||
win32_destroy_window();
|
||||
|
||||
@@ -170,6 +170,14 @@ static void video_driver_read_vp_params(struct video_vp_param_snap *ps);
|
||||
void gfx_ctx_wl_release_kept(void);
|
||||
#endif
|
||||
|
||||
/* A window the last driver left up for this one
|
||||
* (gfx/common/win32_common.c): it goes if this one did not take it. */
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) && !defined(WINAPI_FAMILY)
|
||||
#define VIDEO_WIN32_RELEASE_KEPT_WINDOW() win32_window_release_kept()
|
||||
#else
|
||||
#define VIDEO_WIN32_RELEASE_KEPT_WINDOW() ((void)0)
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
VIDEO_NOINLINE static void video_driver_scanline_before_frame(video_driver_state_t *video_st, uint16_t frame_time_target, uint16_t core_run_time);
|
||||
VIDEO_NOINLINE static void video_driver_scanline_after_frame(video_driver_state_t *video_st, uint16_t frame_time_target, uint16_t core_run_time);
|
||||
@@ -6180,6 +6188,7 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
#ifdef HAVE_WAYLAND
|
||||
gfx_ctx_wl_release_kept();
|
||||
#endif
|
||||
VIDEO_WIN32_RELEASE_KEPT_WINDOW();
|
||||
RARCH_ERR("[Video] Cannot open threaded video driver. Exiting...\n");
|
||||
return false;
|
||||
}
|
||||
@@ -6196,6 +6205,8 @@ bool video_driver_init_internal(bool *video_is_threaded, bool verbosity_enabled)
|
||||
* take back goes now that the new one is up. */
|
||||
gfx_ctx_wl_release_kept();
|
||||
#endif
|
||||
/* and so does a Windows one */
|
||||
VIDEO_WIN32_RELEASE_KEPT_WINDOW();
|
||||
|
||||
if (!video_st->data)
|
||||
{
|
||||
|
||||
@@ -43,6 +43,15 @@
|
||||
# can get, with its joypad driver:
|
||||
# started by the same code, restarted
|
||||
# with the video driver, works.
|
||||
# RETROARCH_WINDOW_KEEP=1 the window is left up across both
|
||||
# restarts and taken back by the driver
|
||||
# that comes next, with threaded video
|
||||
# (where the video thread is held for
|
||||
# it) and without.
|
||||
# RETROARCH_WINDOW_KEEP=2 the window is left up and then not
|
||||
# taken: it is destroyed, a new one is
|
||||
# made, and RetroArch does not take the
|
||||
# destroying of it for being closed.
|
||||
#
|
||||
# (The core is given only the key-up of Z and F, never the key-down:
|
||||
# the frontend keeps the key-down of a key that is bound to something
|
||||
@@ -161,7 +170,7 @@ failures=0
|
||||
# passes through
|
||||
scenario() {
|
||||
local name=$1 threaded=$2 want_bulk=$3 want_joy=$4 nomsg=$5
|
||||
local log="$work/$name.log" try rc video bulk joy msg ok b_down b_up j_seq stale
|
||||
local log="$work/$name.log" try rc video bulk joy msg ok b_down b_up j_seq stale win
|
||||
write_cfg "$threaded" "${6:-raw}" "${7:-winraw_joypad}"
|
||||
# key delivery on a virtual display with no window manager is not
|
||||
# exact: a scenario gets a second go before it counts as failed
|
||||
@@ -189,6 +198,8 @@ scenario() {
|
||||
[ "$nomsg" != nomsg ] || [ "$msg" = 0 ] || ok=no
|
||||
# the old path measures the wait the new one removes; the new
|
||||
# one has nothing to measure
|
||||
win="$(count "$log" 'window is left up') $(count "$log" 'Took the window left up') $(count "$log" 'not one this driver takes')"
|
||||
[ "$win" = "${WANT_WINDOW:-0 0 0}" ] || ok=no
|
||||
stale=$(count "$log" "Taken by the window's thread: at the poll")
|
||||
if [ "$name" = "RETROARCH_RAWINPUT_POLL=0" ]; then
|
||||
[ "$stale" = 3 ] || ok=no
|
||||
@@ -207,6 +218,7 @@ scenario() {
|
||||
"video driver started $video (want 3), input driver by the poll $bulk (want $want_bulk)," \
|
||||
"joypad driver started $joy (want $want_joy);" \
|
||||
"lines on how old the state was at the poll: $stale;" \
|
||||
"window left up, taken, not taken: $win (want ${WANT_WINDOW:-0 0 0});" \
|
||||
"the core saw B pressed $b_down and released $b_up (want 2 and 2), J: ${j_seq:-nothing}(want down up down up)" \
|
||||
"$([ "$nomsg" = nomsg ] && echo ", driver instances with reports taken as messages: $msg (want 0)")"
|
||||
sed 's/\x1b\[[0-9;]*m//g' "$log" | tr -d '\r' | grep -av "ALSA lib\|Playlist\]" | tail -25
|
||||
@@ -219,6 +231,9 @@ RETROARCH_INPUT_KEEP=0 scenario "RETROARCH_INPUT_KEEP=0" true 3 3 nomsg
|
||||
scenario "video not threaded" false 1 1 any
|
||||
RETROARCH_RAWINPUT_POLL=0 scenario "RETROARCH_RAWINPUT_POLL=0" true 0 3 any
|
||||
scenario "DirectInput" true 0 3 any dinput dinput
|
||||
WANT_WINDOW="2 2 0" RETROARCH_WINDOW_KEEP=1 scenario "window kept" true 1 1 nomsg
|
||||
WANT_WINDOW="2 2 0" RETROARCH_WINDOW_KEEP=1 scenario "window kept, video not threaded" false 1 1 any
|
||||
WANT_WINDOW="2 0 2" RETROARCH_WINDOW_KEEP=2 scenario "window left up and not taken" true 1 1 nomsg
|
||||
|
||||
if [ "$failures" != 0 ]; then
|
||||
echo "FAIL windows_wine_smoke: $failures"
|
||||
|
||||
@@ -78,6 +78,10 @@
|
||||
/* gfx/common/wayland_common.c */
|
||||
void gfx_ctx_wl_release_kept(void);
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) && !defined(WINAPI_FAMILY)
|
||||
/* gfx/common/win32_common.c */
|
||||
void win32_window_release_kept(void);
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
||||
#include "../menu/menu_shader.h"
|
||||
@@ -2337,6 +2341,10 @@ static void content_load_step(struct content_load_job *job,
|
||||
* reinit: hand it back, and webOS returns to its
|
||||
* dashboard rather than a window nothing draws into. */
|
||||
gfx_ctx_wl_release_kept();
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__) && !defined(WINAPI_FAMILY)
|
||||
/* nor for a Windows one */
|
||||
win32_window_release_kept();
|
||||
#endif
|
||||
content_load_finish(job, p_content);
|
||||
break;
|
||||
|
||||
Reference in new issue
Block a user