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

FNA.Core: Fix display change out of bounds exception #470

Merged
merged 1 commit into from
Jan 2, 2024

Conversation

jfmu
Copy link
Contributor

@jfmu jfmu commented Jan 1, 2024

i have this tested. This fixes an out of bounds exception when a display adapter suddenly disappears (i tested with unplugging miniDP cable). For some people this seems to happen during powersave (they afk in a game for a while and crash)

@jfmu jfmu force-pushed the fix_windowmove_adapterchange branch from 0290c8a to ab60501 Compare January 1, 2024 23:41
@flibitijibibo
Copy link
Member

When this gets fired, do we get any events for displays getting added/removed? I think there's an event SDL fires when the display array changes without GetNumDisplays getting called first.

@jfmu
Copy link
Contributor Author

jfmu commented Jan 2, 2024

Hi, im back from work and i investigated a bit. So scenario first.

I dont have the exact setup of the player that reported the bug , i just tried until i got the same error. What i did:

I have a notebook and a mini-DP plug to an external monitor. I have the external monitor marked as the primary monitor.
When the game is on the laptop-monitor (the seconary), i unplug the external (primary) monitor. You are right, there is an event:

image
and this event is not in the SDL_DisplayEventID enum. But in SDL2 sourcecode i found:

image

And after that, displayIndex 1 gets a disconnect Displayevent:

image

So im not really sure about it but if you move it here:
image

then the crash bug is gone and i believe this is because after the current invocation of AdaptersChanged() there is an access to .Adapters (yellow), and SDL didnt delete the adapter yet.

image

Should i just edit the pull request and just add AdaptersChanged() at the end?

@flibitijibibo
Copy link
Member

The part that makes the timing weird is that the event in that last screenshot is queued, so by the time we read it in SDL_PollEvent it should have already done the changes to the display list within SDL, and AdaptersChanged is what allows us to reinit the list of adapters. It almost seems like the bug is that the display index of the window is wrong; if there's only 1 adapter at that moment and the display index of the window is still 1 (as in, the second display) then we've got a timing bug in SDL.

So, to confirm: At the moment we assign currentAdapter, we want to know the values of Adapters.Count as well as displayIndex. If we can confirm that displayIndex is too high then we've got an SDL bug to fix!

Alternatively, we can modify AdaptersChanged to do the query right then and there, to ensure that SDL_GetNumDisplays is called before calling SDL_GetWindowDisplayIndex, meaning this line...

https:/FNA-XNA/FNA/blob/master/src/Graphics/GraphicsAdapter.cs#L258

... will look more like this block:

https:/FNA-XNA/FNA/blob/master/src/Graphics/GraphicsAdapter.cs#L147-L149

@jfmu
Copy link
Contributor Author

jfmu commented Jan 2, 2024

Yeah. You are right. I believe the timing issue is that the SDL_WINDOWEVENT_MOVED comes before DISCONNECT or CONNECT displayevents. I can see it in console log output with printf debugging if i just call AdaptersChanged() every time.

First, sorry, my laptop is kind of half-closed so i peeked in there and saw it crashed only when the primary monitor comes back online.
and this is because the events come like this:

SDL_WINDOWEVENT_MOVED (where no AdaptersChanged() is)
crash <->
SDL_DISPLAYEVENT (connect).

@flibitijibibo
Copy link
Member

Huh, I wonder if it should be filtered to put the display events first... might be worth asking Sam about this. For now, let's do a bounds check in window moved, and call AdaptersChanged if it's out of bounds. We can file an SDL report for the timing issue afterward.

@jfmu
Copy link
Contributor Author

jfmu commented Jan 2, 2024

it is because they use WM_DISPLAYCHANGE on windows for reenumerating display devices internally (thats resolution change). Im currently looking for a satifactory solution for display hotplugging.

@jfmu
Copy link
Contributor Author

jfmu commented Jan 2, 2024

Okay so i think the only, sadly, solution to this getting the messages in order is either rearranging them in sdl, which may prove difficult or doing it like this: https://learn.microsoft.com/en-us/windows/win32/devio/registering-for-device-notification

with this GUID.
image

Sorry for all the text, and thanks for fixing it in FNA for now =)

…ex of display might have changed (not sure here but this should fix out of bounds exception crash)
@jfmu jfmu force-pushed the fix_windowmove_adapterchange branch from ab60501 to e668422 Compare January 2, 2024 19:58
@flibitijibibo flibitijibibo merged commit 4b4b822 into FNA-XNA:master Jan 2, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants