Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WGI initialization fails on Win32 #5552

Closed
cgutman opened this issue Apr 19, 2022 · 11 comments · Fixed by #5554
Closed

WGI initialization fails on Win32 #5552

cgutman opened this issue Apr 19, 2022 · 11 comments · Fixed by #5554
Assignees
Milestone

Comments

@cgutman
Copy link
Collaborator

cgutman commented Apr 19, 2022

While retesting #4915, I discovered that WGI initialization now deterministically fails (since 8ebef12) unless the application calls CoInitializeEx(NULL, COINIT_MULTITHREADED) prior to initializing the joystick stubsystem.

Our RoInitialize() call fails due to incompatible concurrency model (RPC_E_CHANGED_MODE) with a previous CoInitializeEx() call.

The first call to CoInitializeEx() comes from DirectInput:

 # Child-SP          RetAddr               Call Site
00 000000c8`dcbef458 00007ff9`92968059     SDL2!WIN_CoInitialize [C:\Users\camer\SDL\src\core\windows\SDL_windows.c @ 86] 
01 000000c8`dcbef460 00007ff9`92970dd9     SDL2!SDL_DINPUT_JoystickInit+0x9 [C:\Users\camer\SDL\src\joystick\windows\SDL_dinputjoystick.c @ 400] 
02 000000c8`dcbef4b0 00007ff9`929628f3     SDL2!WINDOWS_JoystickInit+0x9 [C:\Users\camer\SDL\src\joystick\windows\SDL_windowsjoystick.c @ 442] 
03 000000c8`dcbef4e0 00007ff9`92a0f4c8     SDL2!SDL_JoystickInit+0x83 [C:\Users\camer\SDL\src\joystick\SDL_joystick.c @ 247] 
04 000000c8`dcbef520 00007ff9`92910002     SDL2!SDL_InitSubSystem_REAL+0x198 [C:\Users\camer\SDL\src\SDL.c @ 260] 
05 000000c8`dcbef560 00007ff7`b13a17ba     SDL2!SDL_InitSubSystem+0x12 [C:\Users\camer\SDL\src\dynapi\SDL_dynapi_procs.h @ 86] 
06 000000c8`dcbef590 00007ff7`b13a1d19     JoystickCrashTest!main+0x2a [C:\Users\camer\source\repos\JoystickCrashTest\JoystickCrashTest.cpp @ 15] 
07 000000c8`dcbef6c0 00007ff7`b13a1bbe     JoystickCrashTest!invoke_main+0x39 [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 
08 000000c8`dcbef710 00007ff7`b13a1a7e     JoystickCrashTest!__scrt_common_main_seh+0x12e [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 
09 000000c8`dcbef780 00007ff7`b13a1dae     JoystickCrashTest!__scrt_common_main+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 
0a 000000c8`dcbef7b0 00007ffa`6eed54e0     JoystickCrashTest!mainCRTStartup+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 
0b 000000c8`dcbef7e0 00007ffa`6f76485b     KERNEL32!BaseThreadInitThunk+0x10
0c 000000c8`dcbef810 00000000`00000000     ntdll!RtlUserThreadStart+0x2b

WIN_CoInitialize() tries to use an apartment threading model if COM is not already initialized:

    /* SDL handles any threading model, so initialize with the default, which
       is compatible with OLE and if that doesn't work, try multi-threaded mode.

       If you need multi-threaded mode, call CoInitializeEx() before SDL_Init()
    */
    HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (hr == RPC_E_CHANGED_MODE) {
        hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
    }

So we will end up with apartment threading unless the application has already initialized COM outside of SDL.

Next we will try to call RoInitialize(RO_INIT_MULTITHREADED), which is a conflicting concurrency model with apartment threading that we used earlier.

 # Child-SP          RetAddr               Call Site
00 000000c8`dcbef448 00007ff9`9297250e     SDL2!WIN_RoInitialize [C:\Users\camer\SDL\src\core\windows\SDL_windows.c @ 144] 
01 000000c8`dcbef450 00007ff9`929628f3     SDL2!WGI_JoystickInit+0x1e [C:\Users\camer\SDL\src\joystick\windows\SDL_windows_gaming_input.c @ 443] 
02 000000c8`dcbef4e0 00007ff9`92a0f4c8     SDL2!SDL_JoystickInit+0x83 [C:\Users\camer\SDL\src\joystick\SDL_joystick.c @ 247] 
03 000000c8`dcbef520 00007ff9`92910002     SDL2!SDL_InitSubSystem_REAL+0x198 [C:\Users\camer\SDL\src\SDL.c @ 260] 
04 000000c8`dcbef560 00007ff7`b13a17ba     SDL2!SDL_InitSubSystem+0x12 [C:\Users\camer\SDL\src\dynapi\SDL_dynapi_procs.h @ 86] 
05 000000c8`dcbef590 00007ff7`b13a1d19     JoystickCrashTest!main+0x2a [C:\Users\camer\source\repos\JoystickCrashTest\JoystickCrashTest.cpp @ 15] 
06 000000c8`dcbef6c0 00007ff7`b13a1bbe     JoystickCrashTest!invoke_main+0x39 [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 79] 
07 000000c8`dcbef710 00007ff7`b13a1a7e     JoystickCrashTest!__scrt_common_main_seh+0x12e [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 288] 
08 000000c8`dcbef780 00007ff7`b13a1dae     JoystickCrashTest!__scrt_common_main+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl @ 331] 
09 000000c8`dcbef7b0 00007ffa`6eed54e0     JoystickCrashTest!mainCRTStartup+0xe [d:\a01\_work\43\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp @ 17] 
0a 000000c8`dcbef7e0 00007ffa`6f76485b     KERNEL32!BaseThreadInitThunk+0x10
0b 000000c8`dcbef810 00000000`00000000     ntdll!RtlUserThreadStart+0x2b

This fails with RPC_E_CHANGED_MODE and causes us to fail to initialize the WGI joystick driver. It looks like RO_INIT_SINGLETHREADED is equivalent to COINIT_APARTMENTTHREADED, so we should probably try that like WIN_CoInitialize() does.

@slouken
Copy link
Collaborator

slouken commented Apr 19, 2022

The WGI documentation says specifically to use RO_INIT_MULTITHREADED, so we should probably change WIN_CoInitialize() instead. Can you try that and create a PR if it looks good?

@cgutman
Copy link
Collaborator Author

cgutman commented Apr 19, 2022

The WGI documentation says specifically to use RO_INIT_MULTITHREADED, so we should probably change WIN_CoInitialize() instead.

Oh interesting, do you have a link to the page that said that? The comments for each class in windows.gaming.input.h say "Class Threading Model: Both Single and Multi Threaded" which seems to indicate WGI doesn't care.

Your info does seem to be accurate though because using COINIT_MULTITHREADED fixes the crash in #5270.

Can you try that and create a PR if it looks good?

I can change WIN_CoInitialize() to default to COINIT_MULTITHREADED, but I think that may introduce some nasty issues. It'll be changing the default threading model for most SDL applications, so anyone that uses OLE or other interfaces that need STA will break.

@slouken
Copy link
Collaborator

slouken commented Apr 19, 2022

The WGI documentation says specifically to use RO_INIT_MULTITHREADED, so we should probably change WIN_CoInitialize() instead.

Oh interesting, do you have a link to the page that said that? The comments for each class in windows.gaming.input.h say "Class Threading Model: Both Single and Multi Threaded" which seems to indicate WGI doesn't care.

Your info does seem to be accurate though because using COINIT_MULTITHREADED fixes the crash in #5270.

I thought I read it elsewhere as well, but it may have been this:
#5270 (comment)

I can change WIN_CoInitialize() to default to COINIT_MULTITHREADED, but I think that may introduce some nasty issues. It'll be changing the default threading model for most SDL applications, so anyone that uses OLE or other interfaces that need STA will break.

That's a good point. Maybe we should add a hint for this, and default it to multi-threaded so SDL itself will work correctly? :)

@cgutman
Copy link
Collaborator Author

cgutman commented Apr 19, 2022

That's a good point. Maybe we should add a hint for this, and default it to multi-threaded so SDL itself will work correctly? :)

Upon further inspection, even SDL itself isn't fully MTA-safe.

Our implementation of SDL_SYS_OpenURL() requires an STA to be compatible with certain shell extensions per MSDN docs for ShellExecute.

In addition, our IME code requires an STA, otherwise we fail with REGDB_E_IIDNOTREG on this line:

if (SUCCEEDED(source->lpVtbl->AdviseSink(source, &IID_ITfUIElementSink, (IUnknown *)videodata->ime_uielemsink, &videodata->ime_uielemsinkcookie))) {

I'm going to poke around with WGI more tomorrow to see if maybe we're leaking a reference to something and that's why we crash when Windows.Gaming.Input.dll unloads. If not, we could be stuck having to do something annoying like running WGI on its own thread with an MTA.

@slouken
Copy link
Collaborator

slouken commented Apr 19, 2022

Good catches, thanks!

@cgutman
Copy link
Collaborator Author

cgutman commented Apr 20, 2022

OK, this rabbit hole goes deep, but I think I got somewhat to the bottom of what's going on in #5270.

(4ae8.33ec): Access violation - code c0000005 (first/second chance not available)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
Time Travel Position: 5C9306:0
Windows_Gaming_Input!GameController::~GameController+0x76:
00007ffe`c38862f6 488b4040        mov     rax,qword ptr [rax+40h] ds:00007ffe`c2c81790=????????????????
0:000> k
 # Child-SP          RetAddr               Call Site
00 00000078`6210ee90 00007ffe`c3886254     Windows_Gaming_Input!GameController::~GameController+0x76
01 00000078`6210eec0 00007ffe`c3888a40     Windows_Gaming_Input!GameController::`vector deleting destructor'+0x14
02 00000078`6210eef0 00007ffe`c388a8f0     Windows_Gaming_Input!Microsoft::WRL::Details::RuntimeClassImpl<Microsoft::WRL::RuntimeClassFlags<1>,1,1,0,Windows::Gaming::Input::IGameController,Windows::Gaming::Input::IGameControllerBatteryInfo,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Internal::IGameControllerPrivate>,Microsoft::WRL::FtmBase>::Release+0x80
03 00000078`6210ef20 00007ffe`c38644da     Windows_Gaming_Input!Windows::Gaming::Input::Custom::Details::AggregableRuntimeClass<Windows::Gaming::Input::IGamepad,Windows::Gaming::Input::IGamepad2,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Custom::IGameControllerInputSink>,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Custom::IGipGameControllerInputSink>,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Custom::IHidGameControllerInputSink>,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Custom::IXusbGameControllerInputSink>,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil,Microsoft::WRL::Details::Nil>::Release+0x40
04 00000078`6210ef50 00007ffe`c38d9051     Windows_Gaming_Input!Microsoft::WRL::ComPtr<Windows::Foundation::IAsyncOperation<enum Windows::Gaming::Input::ForceFeedback::ForceFeedbackLoadEffectResult> >::~ComPtr<Windows::Foundation::IAsyncOperation<enum Windows::Gaming::Input::ForceFeedback::ForceFeedbackLoadEffectResult> >+0x2a
05 00000078`6210ef80 00007ffe`c3877119     Windows_Gaming_Input!`eh vector destructor iterator'+0x5d
06 00000078`6210efe0 00007ffe`c3877094     Windows_Gaming_Input!Windows::Gaming::Input::Custom::Details::GameControllerCollection<Windows::Gaming::Input::RawGameController,Windows::Gaming::Input::IRawGameController>::~GameControllerCollection<Windows::Gaming::Input::RawGameController,Windows::Gaming::Input::IRawGameController>+0x59
07 00000078`6210f010 00007ffe`c386afb0     Windows_Gaming_Input!Windows::Gaming::Input::Custom::Details::GameControllerCollection<Windows::Gaming::Input::RawGameController,Windows::Gaming::Input::IRawGameController>::`vector deleting destructor'+0x14
08 00000078`6210f040 00007ffe`c387cacb     Windows_Gaming_Input!Microsoft::WRL::Details::RuntimeClassImpl<Microsoft::WRL::RuntimeClassFlags<1>,1,1,0,Windows::Foundation::Collections::IIterable<Windows::Gaming::Input::ArcadeStick * __ptr64>,Windows::Foundation::Collections::IVectorView<Windows::Gaming::Input::ArcadeStick * __ptr64>,Microsoft::WRL::FtmBase>::Release+0x80
09 00000078`6210f070 00007ffe`c387ca44     Windows_Gaming_Input!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase<Windows::Gaming::Input::FlightStick,Windows::Gaming::Input::FlightStick,Windows::Gaming::Input::IFlightStick,Windows::Gaming::Input::IFlightStickStatics,Microsoft::WRL::Details::Nil>::~CustomGameControllerFactoryBase<Windows::Gaming::Input::FlightStick,Windows::Gaming::Input::FlightStick,Windows::Gaming::Input::IFlightStick,Windows::Gaming::Input::IFlightStickStatics,Microsoft::WRL::Details::Nil>+0x5b
0a 00000078`6210f0a0 00007ffe`c386e451     Windows_Gaming_Input!Windows::Gaming::Input::Custom::Details::CustomGameControllerFactoryBase<Windows::Gaming::Input::FlightStick,Windows::Gaming::Input::FlightStick,Windows::Gaming::Input::IFlightStick,Windows::Gaming::Input::IFlightStickStatics,Microsoft::WRL::Details::Nil>::`vector deleting destructor'+0x14
0b 00000078`6210f0d0 00007ffe`c387b771     Windows_Gaming_Input!Microsoft::WRL::ActivationFactory<Microsoft::WRL::Implements<Microsoft::WRL::FtmBase,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Custom::ICustomGameControllerFactory> >,Windows::Gaming::Input::IFlightStickStatics,Microsoft::WRL::Details::Nil,0>::Release+0x51
0c 00000078`6210f100 00007ffe`c387b55c     Windows_Gaming_Input!FactoryManager::FactoryListEntry::~FactoryListEntry+0x79
0d 00000078`6210f130 00007ffe`c3879985     Windows_Gaming_Input!NtList<FactoryManager::FactoryListEntry>::~NtList<FactoryManager::FactoryListEntry>+0x34
0e 00000078`6210f160 00007ffe`c3879944     Windows_Gaming_Input!FactoryManager::~FactoryManager+0x15
0f 00000078`6210f190 00007ffe`c3878481     Windows_Gaming_Input!FactoryManager::`vector deleting destructor'+0x14
10 00000078`6210f1c0 00007ffe`c3878d88     Windows_Gaming_Input!Microsoft::WRL::ActivationFactory<Microsoft::WRL::Implements<Microsoft::WRL::FtmBase,Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics>,Windows::Gaming::Input::Custom::IGameControllerFactoryManagerStatics2,Microsoft::WRL::CloakedIid<Windows::Gaming::Input::Internal::IGameControllerFactoryManagerStaticsPrivate>,0>::Release+0x51
11 00000078`6210f1f0 00007ffe`c3872d71     Windows_Gaming_Input!Microsoft::WRL::Details::TerminateMap+0x138
12 00000078`6210f230 00007ffe`c38dbb70     Windows_Gaming_Input!Microsoft::WRL::Details::DefaultModule<1>::`vector deleting destructor'+0x21
13 00000078`6210f260 00007ffe`c38d8999     Windows_Gaming_Input!`dynamic atexit destructor for 'Microsoft::WRL::Details::StaticStorage<Microsoft::WRL::Details::DefaultModule<1>,0,int>::instance_''+0x30
14 00000078`6210f290 00007ffe`c38d8d50     Windows_Gaming_Input!CRT_INIT+0xcd
15 00000078`6210f2d0 00007ffe`d059fd17     Windows_Gaming_Input!__DllMainCRTStartup+0x1dc
16 00000078`6210f440 00007ffe`d05b2a3f     ntdll!LdrpCallInitRoutine+0x6b
17 00000078`6210f4b0 00007ffe`d05b242f     ntdll!LdrpProcessDetachNode+0x13b
18 00000078`6210f580 00007ffe`d05b23cf     ntdll!LdrpUnloadNode+0x3f
19 00000078`6210f5d0 00007ffe`d05981fc     ntdll!LdrpDecrementModuleLoadCountEx+0x5b
1a 00000078`6210f600 00007ffe`cdfa9c8e     ntdll!LdrUnloadDll+0xcc
1b 00000078`6210f640 00007ffe`cf6e3e0a     KERNELBASE!FreeLibrary+0x1e
1c 00000078`6210f670 00007ffe`cf71d3b8     combase!CClassCache::CDllPathEntry::CFinishObject::Finish+0x2a [onecore\com\combase\objact\dllcache.cxx @ 2801] 
1d 00000078`6210f6a0 00007ffe`cf6e2b64     combase!CClassCache::CFinishComposite::Finish+0x54 [onecore\com\combase\objact\dllcache.cxx @ 2915] 
1e 00000078`6210f6d0 00007ffe`cf6e1cb5     combase!CClassCache::CleanUpDllsForProcess+0x12c [onecore\com\combase\objact\dllcache.cxx @ 5869] 
1f (Inline Function) --------`--------     combase!CCCleanUpDllsForProcess+0xe [onecore\com\combase\objact\dllcache.cxx @ 7600] 
20 00000078`6210f910 00007ffe`cf71cdd8     combase!ProcessUninitialize+0x1f1 [onecore\com\combase\class\compobj.cxx @ 2181] 
21 00000078`6210f940 00007ffe`cf71cf4b     combase!DecrementProcessInitializeCount+0x5c [onecore\com\combase\class\compobj.cxx @ 984] 
22 00000078`6210f970 00007ffe`cf7316db     combase!wCoUninitialize+0xc7 [onecore\com\combase\class\compobj.cxx @ 4057] 
23 00000078`6210f9c0 00007ffe`244845aa     combase!CoUninitialize+0xeb [onecore\com\combase\class\compobj.cxx @ 3887] 

We only have a single apartment in our process, so the final call to CoUninitialize() on the main thread results in COM being uninitialized for the entire process. As part of that process-wide uninitialization, COM unloads DLLs for all in-proc COM servers. That unload is what is crashing here.

It turns out I was wrong that using an MTA solves the problem. It appears that using an MTA in combination with the partial failure of the IME code (mentioned in my last comment) causes the MTA to stick around beyond our last CoUninitialize() call. This is probably a bug somewhere in the IME code, but I haven't tracked it down. In any case, since an apartment still exists in the process, the process-wide deinitialization of COM never happens and so no crash. The crash still happens with an MTA if you build SDL with SDL_DISABLE_WINDOWS_IME defined.

Using time-travel debugging, I was able to figure out that the pointer WGI is trying to read used to belong to the vtable for Windows::System::UserDeviceAssociationImpl:

Time Travel Position: 5C833F:54
combase!CoUninitialize:
00007ffe`cf7315f0 48895c2408      mov     qword ptr [rsp+8],rbx ss:00000078`6210fab0=0000000000000000
0:000> dps 00007ffe`c2c81730 L10
00007ffe`c2c81730  00007ffe`c2c77e30 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::InternalGetRuntimeClassNameStatic
00007ffe`c2c81738  00007ffe`c2c77e20 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::InternalGetTrustLevelStatic
00007ffe`c2c81740  00007ffe`c2c887b8 Windows_System_UserDeviceAssociation!__objectFactory__UserDeviceAssociationImpl
00007ffe`c2c81748  00000000`00000000
00007ffe`c2c81750  00007ffe`c2c76a20 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::QueryInterface
00007ffe`c2c81758  00007ffe`c2c76a60 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::AddRef
00007ffe`c2c81760  00007ffe`c2c768a0 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::Release
00007ffe`c2c81768  00007ffe`c2c76a80 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::GetIids
00007ffe`c2c81770  00007ffe`c2c76780 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::GetRuntimeClassName
00007ffe`c2c81778  00007ffe`c2c769a0 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::GetTrustLevel
00007ffe`c2c81780  00007ffe`c2c72d00 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::FindUserFromDeviceId
00007ffe`c2c81788  00007ffe`c2c72d90 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::add_UserDeviceAssociationChanged
00007ffe`c2c81790  00007ffe`c2c72fe0 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::remove_UserDeviceAssociationChanged
00007ffe`c2c81798  00007ffe`c2c769e0 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::QueryInterface
00007ffe`c2c817a0  00007ffe`c2c76a40 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::AddRef
00007ffe`c2c817a8  00007ffe`c2c76840 Windows_System_UserDeviceAssociation!Windows::System::UserDeviceAssociationImpl::Release

Based on what the old vtable looked like prior to the unload, It appears that Windows_Gaming_Input!GameController::~GameController() is trying to invoke Windows::System::UserDeviceAssociationImpl::remove_UserDeviceAssociationChanged to unregister a UserDeviceAssociateChanged callback, however Windows.System.UserDeviceAssociation.dll has already been unloaded at this point. This looks eerily similar to The case of the C++/WinRT cached factories that pointed into freed memory except the cause is different.

Windows.System.UserDeviceAssociation.dll was loaded by Windows.Gaming.Input.dll in response to our request for Windows.Gaming.Input.RawGameController. It's something specific to that class in particular, which is why it only triggers when using the WGI joystick driver, rather than RawInput (which also uses WGI under the hood).

WGI is directly loading Windows.System.UserDeviceAssociation.dll, so I can't see how this is anything we're doing wrong:

ModLoad: 00007ffe`c2c70000 00007ffe`c2c8c000   C:\Windows\System32\Windows.System.UserDeviceAssociation.dll
ntdll!NtMapViewOfSection+0x14:
00007ffe`d0603c54 c3              ret

 # Child-SP          RetAddr               Call Site
0b 00000042`38dff1e0 00007ffe`cf723aed     KERNELBASE!LoadLibraryExW+0x172
0c 00000042`38dff250 00007ffe`cf723a30     combase!LoadLibraryWithLogging+0x2d [onecore\com\combase\common\internal\loadfree.cxx @ 160] 
0d (Inline Function) --------`--------     combase!CClassCache::CDllPathEntry::LoadDll::__l4::<lambda_eebf69f5a3250f8786ebc7c3378db176>::operator()+0x15 [onecore\com\combase\objact\dllcache.cxx @ 2054] 
0e (Inline Function) --------`--------     combase!DoImmediateCallback+0x1e [onecore\com\combase\inc\ImmediateCallback.hpp @ 55] 
0f 00000042`38dff290 00007ffe`cf723829     combase!CClassCache::CDllPathEntry::LoadDll+0x50 [onecore\com\combase\objact\dllcache.cxx @ 2054] 
10 00000042`38dff2e0 00007ffe`cf7382c0     combase!CClassCache::CDllPathEntry::Create+0x6d [onecore\com\combase\objact\dllcache.cxx @ 1967] 
11 (Inline Function) --------`--------     combase!CClassCache::GetOrLoadDllPathEntryForWinrt+0x50a [onecore\com\combase\objact\dllcache.cxx @ 3896] 
12 00000042`38dff390 00007ffe`cf7371c8     combase!CClassCache::GetOrLoadWinRTInprocClass+0x620 [onecore\com\combase\objact\dllcache.cxx @ 4027] 
13 (Inline Function) --------`--------     combase!CCGetOrLoadWinRTInprocClass+0x1f [onecore\com\combase\objact\dllcache.cxx @ 7055] 
14 (Inline Function) --------`--------     combase!WinRTGetActivationFactoryOfInprocClass+0x4e [onecore\com\combase\objact\objact.cxx @ 2235] 
15 00000042`38dff500 00007ffe`c3886797     combase!_RoGetActivationFactory+0x478 [onecore\com\combase\winrtbase\winrtbase.cpp @ 963] 
16 00000042`38dff920 00007ffe`c387aa73     Windows_Gaming_Input!GameController::RuntimeClassInitialize+0x35f
17 00000042`38dff9b0 00007ffe`c3879e19     Windows_Gaming_Input!FactoryManager::CreateControllerForProvider+0x307
18 00000042`38dffa10 00007ffe`c38bcf13     Windows_Gaming_Input!FactoryManager::OnProviderAdded+0xf9
19 00000042`38dffa50 00007ffe`c38acf38     Windows_Gaming_Input!ProviderManagerWorker::OnProviderAdded+0x7f
1a 00000042`38dffa80 00007ffe`c38bcb60     Windows_Gaming_Input!HidClient::CreateProvider+0x1a0
1b 00000042`38dffb00 00007ffe`c38bb34a     Windows_Gaming_Input!ProviderManagerWorker::OnPnpDeviceAdded+0xc8
1c 00000042`38dffb60 00007ffe`c38baa2d     Windows_Gaming_Input!PnpDeviceWatcher::StartDeviceObject+0x142
1d 00000042`38dffb90 00007ffe`c38bd1e0     Windows_Gaming_Input!PnpDeviceWatcher::ProcessDeviceNotifications+0x24d
1e 00000042`38dffbd0 00007ffe`c38bd02c     Windows_Gaming_Input!ProviderManagerWorker::WorkerThreadProc+0x170
1f 00000042`38dffe60 00007ffe`cfb354e0     Windows_Gaming_Input!ProviderManagerWorker::WorkerThreadProcThunk+0x1c
20 00000042`38dffe90 00007ffe`d056485b     KERNEL32!BaseThreadInitThunk+0x10
21 00000042`38dffec0 00000000`00000000     ntdll!RtlUserThreadStart+0x2b

I don't know enough about COM to know whether Windows.Gaming.Input or Windows.System.UserDeviceAssociation is at fault for this but it certainly seems to be an OS bug either way.

I'm not sure if there's a better workaround, but I did find that keeping the MTA around (even if nobody is using it) will prevent COM from uninitializing for the entire process and avoid unloading those DLLs. That can be done by calling CoIncrementMTAUsage() after RoInitialize() (even if the current thread has a STA).

@slouken
Copy link
Collaborator

slouken commented Apr 20, 2022

That's awesome debugging, and we should implement that workaround, but it still doesn't solve the fact that SDL uses multiple COM threading models. Or does this mean we can actually initialize WGI with apartment threaded model?

@cgutman
Copy link
Collaborator Author

cgutman commented Apr 20, 2022

STA or MTA doesn't seem to make a difference as far as the crash is concerned. We still hit it either way, so I think it's safe to use either once we decide on a workaround for the bug.

@slouken
Copy link
Collaborator

slouken commented Apr 20, 2022

Let's go ahead and implement the CoIncrementMTAUsage() workaround for now. Can you submit a PR that implements that and uses the correct flags for CoInitialize() and RoInitialize() so everything works?

@slouken
Copy link
Collaborator

slouken commented Apr 20, 2022

@walbourn, @cgutman tracked down the CoUninitialize() crash in WGI, and it looks like it may be unrelated to whether we use RoInitialize(). The details are in #5552 (comment).

@cgutman
Copy link
Collaborator Author

cgutman commented Apr 21, 2022

Let's go ahead and implement the CoIncrementMTAUsage() workaround for now. Can you submit a PR that implements that and uses the correct flags for CoInitialize() and RoInitialize() so everything works?

Yep, I updated PR #5554 with the workaround.

@walbourn, @cgutman tracked down the CoUninitialize() crash in WGI, and it looks like it may be unrelated to whether we use RoInitialize(). The details are in #5552 (comment).

I made a small reproducer for the bug by just adding a couple WGI calls to the default Win32 application template that Visual Studio generates, so I can definitely confirm SDL isn't involved at all.

If anyone at Microsoft wants to investigate, you can build and run the attached project. You must have a PS4 controller connected to the PC (possibly other non-Xbox gamepads may work) and you must leave the app running for at least around 30 seconds to hit the crash.

WGICrash2.zip

madebr pushed a commit to madebr/SDL that referenced this issue Mar 19, 2023
* Make Win32 fullscreen and borderless windows minimizable

* reduced a few ifdefs, fixed an unused warning if built w/o SDL_HAVE_YUV.

* rawinput: Fix double detection of gamepads on some 3rd party X360 wireless receivers

The name that the Raw Input joystick driver pulls from the HID stack comes
from USB string descriptors contained on the device. For official wireless
receivers, this always contains "Xbox 360 Wireless Receiver for Windows"
which matches the friendly name that WGI provides.

3rd party Xbox 360 wireless receivers may have different strings in their
USB string descriptors (one uses "XBOX 360 For Windows" instead). This
fails to match WGI's name and causes Raw Input and WGI to both report the
same gamepad.

Since wireless Xbox 360 controllers seem to have a consistent VID/PID
regardless of the adapter enumerating them, we can also match on that to
catch these.

The duplicate case reported to me was:
Controller (XBOX 360 For Windows) - 030000005e040000a102000000007200
Xbox 360 Wireless Receiver for Windows - 030000005e0400000000000000007701

* Makefile.os2: fixed setting OS2DEBUG in CFLAGS.

* minor os/2 clean-ups.

* emscripten: Don't prevent default on filtered key events

* IME Composition Truncation + SDL_IsTextInputShown + SDL_ClearComposition (libsdl-org#5398)

* Fixes for IME Composition Truncation + Addition of SDL_ClearComposition, SDL_IsTextInputShown

* Fixed: Documentation and code style issues raised during code review.

* Sync wiki -> header

* SDL_windowskeyboard.c (IME_IsTextInputShown): remove unused local vars.

* cmake: Make test code use proper C main functions.

Fixes libsdl-org#5021.

* SDL_blit_N.c: removed duplicated const (fixes bug libsdl-org#5401)

* SDL_endian.h: use endian predefs from newer gcc and clang versions.

Closes: libsdl-org#5403

* Android: add comment to set render target to NULL when going to background (bug libsdl-org#4041)

* Make SDL_VIDEO_OPENGL_EGL optional on Android

* Fixed: Incorrect assumption that mouse button is released when window is allocated

* SDL_audiocvt.c: Don't byteswap 8-bit streams

Otherwise, this results an assert on big endian machines when attenpting to use SDL_LoadWAV_RW function to load 8-bit WAV files.

* METAL: clip rect w/h must be <= render pass

* Fix name of macOS platform and link to README file

* Fixed bug libsdl-org#2199: make SDL_blit_slow handles SDL_PIXELFORMAT_ARGB2101010, storing as RGBA

* Fixed bug libsdl-org#2691 - re-enable surface_testCompleteSurfaceConversion for ARGB2101010

* INSTALL.txt: Say "macOS" instead of "Mac OS X" in modern times.

Reference Issue libsdl-org#5407.

* SDL_windowskeyboard.c: fix build with SDL_DISABLE_WINDOWS_IME defined.

Fixes libsdl-org#5408

* minor whitespace cleanup.

* SDL_audiocvt.c: minor cleanup.

* Adjust gradle dependencies to enable the build to position assets for the APK

* emscripten: obey enable-misc/SDL_MISC settings

* minor optimization (SDL_audiocvt.c)

* imported two libtool mainstream commits 28fbcb6a and b55b1cc8

* Remove 'reserved identifier' warning

* SDL_blit_slow: remove one nested 'if()' because of ARGB2101010 handling

* SDL_triangle_blit_slow: sync code with SDL_blit_slow to handle ARGB2101010

* SDL_GetBasePath() fixes for OS/2

* use _Static_assert for SDL_COMPILE_TIME_ASSERT(), when available

* testplatform.c: move static asserts out of TestTypes().

* simplify SetDSerror
- no need to keep the error in a static variable
- always print the error code
- reduce the required stack-size
- reduce the number of snprintf calls (and code size)

* Fixed build when events are disabled

Fixes libsdl-org#5413

* Removed problematic call to ISensor_SetEventSink()

Fixes libsdl-org#5288

* Fixed warnings when building with cygwin

Fixes libsdl-org#5025

* SDL_cocoawindow.m: update fullscreen toggle when SDL_SetWindowResizable called

* Ignore unknown WM_SIZE types.

According to MSDN, we can also get SIZE_MAXHIDE and SIZE_MAXSHOW,
based on state changes to other windows. It's not clear under
what circumstances this will happen (I saw some docs indicating
it may require multiple application windows), but it doesn't seem
right to treat them as RESTORED.

* Fix relative mouse input for Unvanquished (unvanquished.net)

Here's an IRC dump that hopefully explains the issue this fixes:

> I'm debugging something odd where, for a libre game,
  unvanquished.net (a FPS), relative mouse input in fullscreen is
  buggy
> it's like, working mostly ok, but it has a weird
  performance/cleanup bug
> after some time in relative mouse input mode, some time as low
  as 15s, usually more, the SDL sends A LOT of relative mouse
  input per frame
> almost all of which have xrel==0 && yrel==0
> by A LOT, I mean that after ~1min, it's usually in the
  thousands per frame
> each frame, a while ( SDL_PollEvent( &e)) loop reads the
  inputs, but it seems SDL is not clearing the list.
> one way to clear the list is to open the in-game console or
  menu, which switches the input mode to absolute, then close it
  which gets a working relative input mode (for some time at least)
> I've shown the issue to be present with SDL2.0.20 but not with
  2.0.14 on my system
> some other players on Arch Linux (SDL2.0.20) report a possibly
  related issue, where some keys seem to be pressed at random
> I've did some bisection on SDL master, and I've found that
  there are actually two commits involved, one breaking it
  totally (no input at all), and one fixing it partially (with
  the problem described above)

First related commit that breaks it totally:

	commit 82793ac
	Author: Sam Lantinga <slouken@libsdl.org>
	Date:   Thu Oct 14 14:26:21 2021 -0700

	    Fixed mouse warping while in relative mode

	    We should get a mouse event with an absolute position and no relative motion and shouldn't change the OS cursor position at all

Second related commit, that halfway fixes it:

	commit 31f8c3e
	Author: Sam Lantinga <slouken@libsdl.org>
	Date:   Thu Jan 6 11:27:44 2022 -0800

	    Fixed event pump starvation if the application frequently pushes its own events

Reverting the first commit did fix the issue for me, but would
probably reintroduce the bug it was fixing(?). This patch should
fix it for everyone hopefully.

DaemonEngine/Daemon#600 is the upstream
bug, and contains some early investigation.

* Don't warn if anyone peeps for events after quitting the event subsystem

Fixes libsdl-org#5013

* video: Add a hint to allow Vulkan surfaces on foreign windows

* Fixed compile warning and comment typo

* Added a hint to mark a foreign window as usable with OpenGL

Fixes libsdl-org#2942

* When updating grab state, only activate windows that are grabbed, fullscreen, and shown.

Fixes libsdl-org#5371

* Try not forcing activation when grabbing the mouse in fullscreen windows

* Workaround for bug in Microsoft WGI support

Fixes libsdl-org#5270

* Use SDL_Log instead of printf

* Added a hint to capture the mouse when mouse buttons are pressed, defaulting on

Fixes libsdl-org#5301

* Fixed memory leak in WIN_CreateBlankCursor()

* Fixed freeing the Windows blank cursor

* Start rumbling once a raw input controller has been correlated

Fixes libsdl-org#5351

* Modern CMake doesn't need "LANGUAGE C" for Objective-C

CMake 3.19 fails to compile Objective-C with that property set

Fixes libsdl-org#5418

* Added the hint SDL_HINT_MOUSE_RELATIVE_MODE_CENTER, controlling whether the mouse should be constrained to the center of the window or the whole window in relative mode.

For further info about the pros and cons, check out the discussion in libsdl-org#5271

* Added a note that SDL_RenderReadPixels() should be called before SDL_RenderPresent()

* Sync wiki -> header

* Fix "SDL_TRUE is not defined" runtime error for emscripten.

* SDL_UnionRect: If both rects are empty, zero out the result struct.

* SDL_Rect: minor code cleanups.

* SDL_Rect: Added floating point versions of all the rectangle APIs.

Fixes libsdl-org#5110.

* Fix "SDL_FALSE is not defined" runtime error for emscripten.

* Fixed Android crash when SDL_HIDAPI_DISABLED set to 1

The Java code needs the native functions to be implemented, even if they're not surfaced via the C API.

Fixes libsdl-org#5326

* Relative mouse mode is tied to the window with keyboard focus

This isn't obvious, but makes sense when thinking about how games actually use it. This is also in line with how Windows mouse relative mode is implemented.

Fixes libsdl-org#5340

* Fixed parameter operation ordering for ease of reading

* audio: Set error message on dsp init failure.

if SDL_EnumUnixAudioDevices() fails to find any devices,
set an error message on the exit path. Without this,
SDL_Init() could fail without any message available
in SDL_GetError().

* Sync wiki -> headers.

* Fixed bug libsdl-org#2426 - SDL_RenderReadPixels result is unspecified and fails testautomation
Call SDL_RenderPresent after calling SDL_RenderReadPixels.
From "include/SDL_render.h":
"If you're using this on the main rendering target, it should be called after rendering and before SDL_RenderPresent()."

* Fixed bug libsdl-org#2962 - when SDL_RenderReadPixels format = 0, used format of the target texture
include/SDL_render.h, format:
"0 to use the format of the rendering target "

* blit-auto optimizations

* regenerated SDL_blit_auto.c.

* Don't try to hide foreign windows when destroying the SDL window representation

Fixes libsdl-org#5432

* hints: Added SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE.

Fixes libsdl-org#2349.

* SDL_render.c: remove unsused case, since renderer target has been forced to NULL previously (see bug libsdl-org#4213)

* Add mapping for Logitech Precision Gamepad

* Also fix Android crash when SDL_HIDAPI_DISABLED set to 1

The Java code needs the native functions to be implemented, even if
they're not surfaced via the C API, therefore, a stub version of
functions were made only to the purpose of "fill the gaps" when
SDL_HIDAPI_DISABLED set to 1.

* use != '\0' comparison instead of SDL_strlen in the functions of SDL_getenv

* make SDL_strcasecmp standard compliant

* optimize the SDL_str(case)cmp functions

* Avoid trying to use texture framebuffers on emscripten

* stdlib: just cast iconv()'s 2nd arg to void *.

This makes the compiler happy (enough) regardless of whether the C runtime
headers think this argument should be const or not.

Fixes libsdl-org#4966.

* Fixed freeing a constant string (thanks @gnrlwart)

* Android: add SetWindowResizable() implementation
- which also enable/disable the orientation lock status.

This is only provided when the window is not SDL_WINDOW_FULLSCREEN (see SDL_video.c).
Final orientation also depends on SDL_HINT_ORIENTATIONS.

* Video: do not use hardcoded VIVANTE and VDK libraries

* Add SDL_RenderGetWindow() API to get the window associated with a renderer (libsdl-org#5440)

Add SDL_RenderGetWindow() API to get the window associated with a renderer

* Sync wiki -> header

* wayland: Bump minimum requirement to wayland-client 1.18 or newer

* wayland: The rest of the wayland-client 1.18 requirement... Git, please

* wayland: Basic support for zwp_tablet_*v2 protocol

* video: wayland: Use xdg-output for retrieving the desktop dimensions

Using wl-output to get the desktop display dimensions and dividing by the integer scale factor will not return the correct result when using a desktop with fractional scaling (e.g. a 3840x2160 display at 150% will incorrectly report the scaled desktop area as 1920x1080 instead of 2560x1440).  Use the xdg-output protocol, if available, to retrieve the correct desktop dimensions and offset.

Versions 1 through 3 of the protocol are supported.

* Vita: support audio format fallback

* Vita: add native YUV textures support.

* Fail if texture init fails.
* Refactor and cleanup.

* static analysis: Fixed several complaints from codechecker.

There are still some pending Objective-C specific issues.

Reference issue libsdl-org#4600.

* add some Thrustmaster wheels

* Fixed bug libsdl-org#1650: X11 doesn't set KMOD_NUM and KMOD_CAPS to system state

* x11: Minor cleanups and corrections in X11_ShowMessageBox.

Reference issue libsdl-org#3254.

* Avoid depending on libwayland 1.20 unnecessarily

When using shared linking (linking in the normal way with
-lwayland-client) rather than loading Wayland libraries dynamically at
runtime, listing symbols that don't exist in the current version results
in a build failure. We don't actually call wl_proxy_marshal_flags() or
wl_proxy_marshal_array_flags() directly; the reason we need them is
that they're called by the code generated by wayland-scanner >= 1.20.

If we're building against an older Wayland library, then we'll have its
corresponding version of wayland-scanner (mismatched versions are not
supported), so we won't need those two symbols, and can avoid generating
a dependency on them.

Conversely, if we're building against a newer Wayland library, the
generated code will call them unconditionally, so we cannot treat them as
optional and gracefully fall back: that would result in a crash. Instead,
treat them as a mandatory part of the Wayland library, so that if they
are not found at runtime, we can fall back to X11 without crashing.

libwayland 1.18 is in several LTS distributions (Ubuntu 20.04,
Debian 11, RHEL 8) so avoiding a hard dependency on 1.20 is quite
useful.

Signed-off-by: Simon McVittie <smcv@collabora.com>
Resolves: libsdl-org#5376

* wayland: Don't overwrite error message from SDL_EGL_CreateSurface

SDL_EGL_CreateSurface sets a more specific error message, so overwriting
it would lose information.

Signed-off-by: Simon McVittie <smcv@collabora.com>

* wayland: Minor fixes for old compilers

* wayland: Remove some now-redundant casts

* iOS >= 10.0 silence GLes deprecation warnings

* wayland: Add an xkb_keysym_t->SDL_Keycode mapping for backspace

* wayland: Enforce text capitalization manually, for remapped keymods

* wayland: Use xkb_keymap_mod to set mod state

* YUV: fix invalid read on last line when converting from SDL_PIXELFORMAT_YUY2 (see bug libsdl-org#4841)

* Vita: Fix NULL-pointer dereference

* wayland: Optimize keyboard_handle_modifiers.

1. Mod index values are (mostly) constant, so can be done with xkb_state_new
2. Mods can change without the group changing, avoid remap events if possible

Lastly, as a bonus, I added braces to the locale check, because I was nearby.

* Initialize compile status variable and check also program link status

* testshader: use SDL_malloc instead of SDL_stack_alloc.

* README-windows: Convert to actual Markdown text.

* README-windows: Wordwrap text file.

This makes for easier reading outside of a formal Markdown viewer.

* README-windows: Notes on building with Visual Studio/LLVM.

Fixes libsdl-org#5186.

* wayland: Work around a GNOME xdg_output scaling issue

* wayland: Avoid overwriting xdg_output position with wl_output position

* wayland: Relax the check for mismatching output scales

* configure: improvements to libdecor discovery :

use PKG_CHECK_MODULES, and use DECOR_LIB with find_lib.
Closes: libsdl-org#5460

Co-authored-by: Trigan2025 <trigan2025@hotmail.fr>

* direct3d: Implement missing blend operations.

This is only for Direct3D 9; Direct3D 11 already had this implemented.

Fixes libsdl-org#5375.

* Remove URLs from markdown headers in README-visualc.md

* Clean up formatting in README-directfb.md

* testgles2: Call correct function to get shader info log and add link status checking

* Sync wiki -> header

* Sync wiki -> header

* Vita: Use preallocated memory pool for textures

* Sync wiki -> header

* Correct default structure packing on Windows ARM64

See issue libsdl-org#5454 for details

* Fix potential memory leak in QueueCmdFillRects

* Vita: add hint to select which touchpad generates mouse events

* emscriptenaudio: proxy calls to main thread

* video: wayland: Use wp-viewporter for fullscreen with non-native resolutions

Wayland doesn't support mode switching, however Wayland compositors can support the wp_viewporter protocol, which allows for the mapping of arbitrarily sized buffer regions to output surfaces.  Use this functionality, when available, for fullscreen output when using non-native display modes and/or when dealing with scaled desktops, which can incur significant overdraw without this extension.

This also allows for the exposure of arbitrarily sized, emulated display modes, which can be useful for legacy compatability.

* wayland: Minor fix for old compilers

* video: wayland: Expose more resolutions for mode emulation

Expose as many emulated display modes as possible.  They will currently display stretched to the display's native desktop aspect, but if an application requires a hardcoded resolution, it will work at minimum.

Aside from the change in the emulated display mode list, the Wayland event handling code had to be updated to support separate scaling for the x and y axes, as square pixels are no longer guaranteed.

* video: wayland: Use viewports for non-fullscreen windows with fractional scaling

Use viewports for non-fullscreen windows when the desktop uses fractional scaling and the window is flagged as DPI-aware to provide a backbuffer mapped as close to 1:1 output as possible.  In the cases of odd window sizes the backbuffer may be a pixel off of scaling perfectly into the window size due to its scaled size being rounded off, but a minute amount of scaling during output is likely preferable to the large amounts of overdraw needed with integer scaled buffers.

* Vita: add audio capture support

* Vita: add SDL_GetPreferredLocales support

* stdinc: SDL_COMPILE_TIME_ASSERT defines shouldn't have a semicolon.

* x11: Catch X11 errors in X11_SetWindowPosition and X11_SetWindowSize.

The functions can go south if other operations are in progress, like
X11_SetWindowBordered, which might be doing something traumatic behind the
scenes of the window manager.

We can't make these tasks totally synchronous, which would fix the problem,
because not only can the window manager block however long it wants, it might
also decide to deny our requests without any notification, so we'd be waiting
forever for a window change that isn't coming.  :(

Fixes libsdl-org#5274.

* joystick: Fix rumble issues on PS5 HIDAPI controllers

We were returning the report size from HIDAPI_DriverPS5_RumbleJoystick() rather
than 0 upon success, causing SDL_JoystickRumble() (and callers) to think that
rumbling failed.

This didn't cause major problems until 1868c5b, when it started preventing
rumble state from being persisted in the joystick core, even though it was
successfully sent to the hardware.

This led to all sorts of strangeness, including broken rumble duration and
attempts to stop rumble being discarded.

* Desktop OpenGL 1.X/2.X PSVita Support

* Update README-vita.md

* Cleanup Spaces

* Vita: PVROGL: fix indentation and ifdef guards

* Vita: fix readme

* x11: Ignore BadValue for extremely small XRRSetScreenSize resolutions.

Reference Issue libsdl-org#4840.

* SDL2 thread proxying fixes

This PR uses new APIs added in [emscripten-core/emscripten#9336](emscripten-core/emscripten#9336)
to improve compatibility with USE_PTHREADS=1.

Original PR: emscripten-ports/SDL2#127
By: @jakogut
Reviewed by: Daft-Freak

* emscriptenmouse: remove old extra `_INT`

* fix formatting and cast warnings

Co-authored-by: Charlie Birks <charlie@daftgames.net>

* emscriptenmouse: remove useless return statement

* emscriptenframebuffer: fix formatting

* emscripten: Proxy SDL_GetUsableDisplayBounds to the main thread.

* Fixed loading 32-bit BMP files

* Move SDL_List functions to SDL_list.c to avoid more merge with eventual PR

* Add SDL_list.c/h

* Add SDL_list to macosx xcode

* Use RoInitialize/RoUninitialize for Windows.Gaming.Input

Thanks @walbourn!

Fixes libsdl-org#5270

* fix build against older SDKs after commit 8ebef12.

* check for HAVE_ROAPI_H in cmake and autotools, and

update SDL_config_windows.h and SDL_config_winrt.h

* attempt to fix uwp build

* render: Fix setting the scale mode for non-native textures

* Visualise scroll wheel events in testmouse

* Minor cleanup

* x11: Don't unload libGL.so to prevent a crash in XCloseDisplay()

libGL.so may register callbacks that can be invoked upon XCloseDisplay().
If XCloseDisplay() is called after libGL.so is unloaded, the callback pointer
will point at freed memory and invoking it will crash.

The texture framebuffer check optimized out in f37e4a9 was causing libGL.so to
never be unloaded as a side-effect. Skipping it exposed this bug by allowing
libGL.so to actually unload.

* x11: Wait a bit to see if window pos changes when changing fullscreen.

Helps prevent window from moving to 0,0 when leaving fullscreen.

Fixes libsdl-org#4749.

* testgles2: Fix buffer object sizes

* Added a define VERBOSE_MOTION_EVENTS to show mouse and finger motion events

* Handle interaction between auto capture and the SDL_CaptureMouse() API

Fixes libsdl-org#5457

* Minor cleanup

* IBus should use ev keycode instead of X keycode

See: https://github.com/ibus/ibus/blob/5a455b1ead5d72483952356ddfe25b9e3b637e6f/client/gtk2/ibusimcontext.c#L468

* Ignore focus change messages that contradict GetForegroundWindow.

On Wine, when a window is programmatically minimized in response
to losing focus, we receive a WM_ACTIVATE for the deactivation,
but GetForegroundWindow still indicates that our window is focused.
This causes an incorrect SDL_WINDOWEVENT_FOCUS_GAINED.

This is probably a Wine bug, but it may take a while to fix and
then for the fix to make its way to users.

* Don't resize fullscreen windows when hiding or minimizing them (thanks @madewokherd!)

This has the benefit of window previews (mousing over the icon) having the correct size and contents.

Fixes libsdl-org#5320

* x11: when waiting on fullscreen changes, not window position _and_ size.

This makes sure the window doesn't have outdated values if you try to access
them (or call something that does, like SDL_SetWindowMinimumSize).

Fixes libsdl-org#5233.

* Send key release event to input method. (libsdl-org#5281)

Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>

* Cache the fact that a device didn't look like a joystick

Fixes libsdl-org#5211

* x11: Try to keep SDL_WINDOW_FULLSCREEN* in sync with window manager.

So if Gnome/KDE/etc have a keyboard shortcut or titlebar decoration to
make any window go fullscreen (with the _NET_WM_FULLSCREEN flag on the
_NET_WM_STATE property), we update the SDL window flag.

Fixes libsdl-org#5390.

* Sort controllers by the js* index on Linux

Also fixed the initial scan to directly scan devices instead of using
udev so they can be sorted, as intended.

Fixes libsdl-org#4688

* wayland: Evaluate WINDOWPOS_CENTERED_DISPLAY for move events

Partially fixes the mouse cursor in UE5 editor. Imperfect because UE5 uses window position and global mouse state to get position, but of course we don't have global mouse and this is just to get the right display index so this still fails overall. We really need to make global mouse support a feature query...

* wayland: Try to detach at the beginning of ShowWindow, just in case.

It's possible that an external component (probably a GL/VK context) committed, so we need to cover our bases and detach in both HideWindow and ShowWindow.

Fixes a crash in UE5 editor's pop-ups.

* wayland: Add a bug link for the detach FIXME

* wayland: Pin the fake window position at (0, 0).

I kind of thought it'd be nice to have it in the center, but this is an issue
for applications that still assume global mouse and window positions are
accessible. For example, this fixes cursor offset issues in UE5.

* Makefile.in: added missing CXX variable.

* Compile with recursive mutexes for emscripten

Emscripten actually does support recursive mutexes, so no need to use SDL's fake recursive code.

Background: libsdl-org#5428, libsdl-org#5479

* x11: Treat WM setting the window "fullscreen" like FULLSCREEN_DESKTOP.

Fixes libsdl-org#5390.

* Only update modifier state for keys that are pressed in another application

Fixes libsdl-org#4432

* minor adjustment to os/2 watcom makefile

* Make sure the UIKit message box is being handled on the main thread

Potentially fixes libsdl-org#4865

* render: Update the size/scale/viewport on moves, in addition to resizes.

For OpenGL this means resetting the viewport state shadowing flag too.

Fixes libsdl-org#1504

* direct3d11: Set the swapchain target immediately after creating it.

Fixes libsdl-org#4782

* video: wayland: Set the surface damage region when using fullscreen viewports

When using emulated display modes, the output size is often larger than the drawable buffer.  As the surface damage region is automatically calculated from the smaller drawable buffer size, the damage region needs to be manually set to cover the entire viewport region or visual repaint artifacts can result.

* Fixed typo

* Updated the patch notes with API changes for 2.0.22

* Update version to 2.0.22 for release

* audio: SDL_ConvertStereoToMono_SSE3 missed an unaligned load.

* UWP: Require Windows 10 16299 or newer.

This is required to build with WGI support. Thanks for @FrozenChameleon for the fix!

Fixes libsdl-org#5504

* Vita: fix VIDEO_VITA_PVR flag

* fix os2 timer in fallback mode

* testevdev: Recognise touchpads as such

At the time I contributed this unit test, SDL didn't understand Linux
touchpads, but now it does.

Fixes: 373216a "Added support for touchpads in the Linux evdev code"
Signed-off-by: Simon McVittie <smcv@collabora.com>

* testevdev: Adapt to a broader definition of keyboards

At the time I contributed this unit test, SDL had a relatively narrow
definition of what is a keyboard, approximately matching udev
ID_INPUT_KEYBOARD. Now it uses the equivalent of udev ID_INPUT_KEY,
which matches anything with keyboard keys, and not just reasonably
complete alphanumeric keyboards.

Fixes: 040bd7a "Fix udev not detecting ID_INPUT_KEY devices when udev is not running"
Signed-off-by: Simon McVittie <smcv@collabora.com>

* test: Copy utf8.txt to build directory

testiconv wants this.

Signed-off-by: Simon McVittie <smcv@collabora.com>

* Initialise scandir argument

'scandir' does not initialise 'entries' on error

* Wayland: Add SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR

This hint allows libdecor to be used even when xdg-decoration is
available. It's mostly useful for debugging libdecor, but could in
theory be used by applications which want to (for example) bundle their
own libdecor plugins.

* WhatsNew.txt: Added SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR

* WhatsNew.txt: Document new dependency on libwayland-client 1.18.0

Signed-off-by: Simon McVittie <smcv@collabora.com>

* CI: update os2.yml to use open-watcom/setup-watcom

also remove os2-buildbot.sh -- not needed anymore.

* avoid NullPointer in SDL_GL_MakeCurrent

* avoid NullPointer in SDL_GetRenderTarget

* video: Wayland: Clamp fullscreen window dimensions to desktop

A scaled fullscreen window may exceed the bounds of the desktop.  Clamp the window size to the desktop dimensions in fullscreen mode.

* video: Wayland: Always round scaled pointer coordinates down

Rounding up can cause the pointer coordinates to exceed the window boundaries at the right and bottom edges.

* x11: Update the display when the WM changes a window's fullscreen state.

Fixes libsdl-org#5390.

* Added CMake option to disable the installer

* cmake: Fixed indenting and some oldschool `endif(TEXT)` things.

* hints: Make SDL_VIDEODRIVER and SDL_AUDIODRIVER formal hints.

They were just environment variables before.

Fixes libsdl-org#5528.

* Revert "video: Prefer Wayland over X11"

This reverts commit 8ceba27.

SDL Wayland support is stable, but there are a number of issues with third-party software (NVIDIA drivers, libwayland event overflow, libdecor not handling plugin load failures, Steam overlay not working with Wayland, etc.) that make it better to default to X11 at this time.

Games which would like to prefer wayland when available can use the following code before SDL_Init():
	SDL_SetHint(SDL_HINT_VIDEODRIVER, "wayland,x11");

Fixes libsdl-org#5527

* Certain audio drivers, like the RME "Pro" Audio driver, have resampling quality issues when using WASAPI.

We'll use SDL's resampling algorithm so we have consistent quality between platforms and drivers.

Fixes libsdl-org#5538

* wayland: Add support for TOOLTIP/POPUP_MENU

* video: Don't minimize fullscreen windows on focus loss by default when mode switching is disabled

When mode switching is disabled in a video backend, fullscreen windows are basically just fullscreen desktop windows with different internal scaling.  As no mode switching occurs, there's no need to minimize them on focus loss by default.  This can still be overridden by explicitly setting the internal hint for minimizing on focus loss.

This has the side effect of fixing a bug on GNOME, where, when a fullscreen Wayland window has it's focus lost and restored via alt+tab followed by switching back to windowed mode, the top portion of the window won't end up being obstructed by GNOME's top bar.

* Added controller mapping for the Thrustmaster Dual Analog 3.2 on Linux

* Enable evdev-based gamecontrollerdb on FreeBSD

* simplify SDL_GetBasePath on windows
- use GetModuleFileName directly (as recommended)

* use explicit GetModuleFileNameW

* Remove HWND_TOPMOST for fullscreen windows

Fixes libsdl-org#5509

* SDL_render.c: internally change viewport/cliprect type from SDL_FRect to SDL_DRect (double precision). (see bug libsdl-org#5547)

* Don't call scandir() inside of scandir()

This works around a crash in address sanitizer

* Fixed compile warnings

* x11: Revert "Fix keymap updating for X11 backend"

This reverts commit de6d290.

This patch had multiple issues, discussed in libsdl-org#5520.

* Fixed build

* Fix recent changes in VitaSDK

* SceKernelMemBlockType to unsigned int

* Fix a -Wshadow warning

* Remove an unused function prototype

* WhatsNew.txt: Add SDL_FRectEqualsEpsilon()

* Add SDL_FLT_EPSILON.

* SDL_Rect: Use a default epsilon in SDL_FRectEquals()

Add SDL_FRectEqualsEpsilon() for when more control over
equality test is required.

* test: Basic tests for SDL_FRectEquals

Based on the integer version. These tests mostly check that input
isn't mangled and that invalid input gives the expected negative
result.

* hidapi: Wrap CopyHIDDeviceInfo in define checks.

The purpose of this is to silence a 'defined but not used'
warning.

* os2: SDL_DestroyMutex should ignore NULL mutexes.

Every other backend does this, so this should match, now.
It's possible this was harmless, but we can avoid the system call
and the (likely?) debug message when it fails, though!

* windows: Fix calling convention for RoInitialize/RoUninitialize

Fixes libsdl-org#5563

* windows: Fix RoInitialize() failure after a CoInitializeEx() call using apartment threading

This mirrors the same codepath in WIN_CoInitialize() which handles STA and MTA.

* WGI: Keep a reference to the MTA to avoid crashing on COM teardown

Fixes libsdl-org#5552
Fixes libsdl-org#5270

* WGI: Only call RoUninitialize() if RoInitialize() succeeded

* Handle potential out of memory condition when working with hints

* SDL_Rect: Add \sa documentation block to SDL_FRect

* Return a correlation error when trigger rumble is attempted without correlation

* Fixed build

* SDL: sometimes the PS5 controller doesn't report having to power even when connected over USB. Possibly related to being completely charged? Either way we already know that it's USB or BT so let's use the driver's knowledge instead.

* Added support for the Backbone One controller on iOS

* Revert "Fix relative mouse input for Unvanquished (unvanquished.net)"

This reverts commit 3318590.

Fixes libsdl-org#5569

* hidapi, libusb: import mainstream commit 536bad201e

* Fixed logical size synchronization issue on macOS

https://discourse.libsdl.org/t/sdl-2-0-22-prerelease/35306/6

* x11: revert checks for _NET_WM_STATE_FULLSCREEN changes.

This reverts commit 8597735.
This reverts commit 0249df9.

Fixes libsdl-org#5572.
Reopens libsdl-org#5390.

Co-authored-by: Jo Bates <jo@valvesoftware.com>
Co-authored-by: Ozkan Sezer <sezeroz@gmail.com>
Co-authored-by: Cameron Gutman <aicommander@gmail.com>
Co-authored-by: Charlie Birks <charlie@daftgames.net>
Co-authored-by: Zach Reedy <86971250+zreedy@users.noreply.github.com>
Co-authored-by: SDL Wiki Bot <icculus-sdlwikibot@icculus.org>
Co-authored-by: Ryan C. Gordon <icculus@icculus.org>
Co-authored-by: Sylvain <sylvain.becker@gmail.com>
Co-authored-by: Guus Waals <_@guusw.nl>
Co-authored-by: Zach Reedy <zreedy@opera.com>
Co-authored-by: Wohlstand <admin@wohlnet.ru>
Co-authored-by: Sam Lantinga <slouken@libsdl.org>
Co-authored-by: staphen <staphen@gmail.com>
Co-authored-by: pionere <pionere@freemail.hu>
Co-authored-by: uyjulian <uyjulian@gmail.com>
Co-authored-by: Esme Povirk <esme@codeweavers.com>
Co-authored-by: Antoine Fontaine <antoine.fontaine@epfl.ch>
Co-authored-by: Ethan Lee <flibitijibibo@gmail.com>
Co-authored-by: Christian Kündig <kuendig@scandit.com>
Co-authored-by: Eddy Jansson <eddy@klopper.net>
Co-authored-by: Egor <egor@opensrc.club>
Co-authored-by: Jonatha Gabriel <jonathagabrielns@gmail.com>
Co-authored-by: Joao Paulo Magalhaes <dev@jpmag.me>
Co-authored-by: Florian "sp1rit"​ <sp1ritCS@protonmail.com>
Co-authored-by: Frank Praznik <frank.praznik@gmail.com>
Co-authored-by: Ivan Epifanov <isage.dna@gmail.com>
Co-authored-by: Kimplul <kimi.h.kuparinen@gmail.com>
Co-authored-by: Simon McVittie <smcv@collabora.com>
Co-authored-by: DominusExult <domiman+github@gmail.com>
Co-authored-by: capehill <juha.niemimaki@gmail.com>
Co-authored-by: Trigan2025 <trigan2025@hotmail.fr>
Co-authored-by: Cameron Cawley <ccawley2011@gmail.com>
Co-authored-by: Mathieu Eyraud <70028899+meyraud705@users.noreply.github.com>
Co-authored-by: Connor Clark <cjamcl@gmail.com>
Co-authored-by: Jaylon Gowie <jaylongowie46@gmail.com>
Co-authored-by: Reinhold Gschweicher <pyro4hell@gmail.com>
Co-authored-by: Christoph Reichenbach <creichen@gmail.com>
Co-authored-by: Weng Xuetian <wengxt@gmail.com>
Co-authored-by: David Gow <david@ingeniumdigital.com>
Co-authored-by: Semphris <semphris@protonmail.com>
Co-authored-by: Jan Beich <jbeich@FreeBSD.org>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants