Git Product home page Git Product logo

Comments (35)

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Assuming you're using MonoGame.Framework.SDL2.csproj?

If you can provide me with a complete history of what SDL2_GameWindow::EndScreenDeviceChange is going through throughout your program (print the full set of variables and their values each time the device change occurs), that'll tell me what's wrong with the application. Otherwise, best I can say is "I dunno, lol", since I recently added code to ensure that GraphicsDeviceManager preferences were usable by the time you hit Game::Initialize. Though, I also haven't seen ToggleFullscreen in a while, so maybe there's something to be investigated there.

A test case will also help, if you've got one.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Hm, here's something: keep an eye on _wantFullScreen in GraphicsDeviceManager.cs as well. Wondering if messing with ToggleFullscreen and GraphicsDeviceManager preferences too much causes some inconsistencies.

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

Bummer that it wasn't just "oh, I hardcoded that to be on" ;)

Thanks for the pointers, I'll debug at the points you mentioned.

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

This is a little strange... when the app starts, every time SDL2_GameWindow::EndScreenDeviceChange() is called, when we get to the SDL_SetWindowFullscreen call, both of these tests always returns 0:

(INTERNAL_sdlWindowFlags_Next & SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN)
// as well as
(INTERNAL_sdlWindowFlags_Next & SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP)

and _wantFullScreen is set to false.

That gets called 3 times during startup and then the window appears fullscreen. If I let my loading-screen and splash-screens run, then my game is sitting idle. If I then hit F11, the ToggleFullscreen code gets called but the state in SDL_Window seems to not match the actual stae of the window... so _wantFullScreen gets switched from false to true. Resultingly, a test of:

(INTERNAL_sdlWindowFlags_Next & SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN)
// as well as
(INTERNAL_sdlWindowFlags_Next & SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP)

Shows that SDL_WINDOW_FULLSCREEN flag and SDL_WINDOW_FULLSCREEN_DESKTOP are now set. Although my game ran past this point, when I'm debugging it always dies right afterwards by running out of memory at the next Draw() call in the game loop.

What code might be capable of setting the window fullscreen against _wantFullScreen's wishes?

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

It miiight be possible that ToggleFullscreen() is changing IsFullscreen without consulting _wantFullscreen first? I don't know what behavior could change here, but maybe before the IsFullscreen = !IsFullscreen; bit we need _wantFullscreen = !IsFullscreen as well? _wantFullscreen is a weird, weird variable...

Of course, this probably means that BeginScreenDeviceChange is getting false each time, so SDL2_GamePlatform::BeginScreenDeviceChange is always being told to stay windowed. That'd be another place to look for issues.

You might be able to set a breakpoint at SDL_SetWindowFullscreen or spam SDL_GetWindowFlags to check its info, but the part where it runs out of memory is really interesting. The Mono profiler might be able to shed some light on that (I think)?

Is there any use of System.Windows.Forms going on? That's the only other thing I can think of that might try to change the window state (it really, really shouldn't); SDL2 does the rest... and I don't think 2.0.0 has had any reports regarding fullscreen for any particular OS.

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

IsFullscreen is just wrapping _wantFullscreen basically, and it does appear to be getting set correctly inToggleFullScreen.

I set a breakpoint at all the calls to SDL_SetWindowFullscreen inside of BeginScreenDeviceChange and it doesn't gets either of those FULLSCREEN flags being set during the initial startup. Also, since the app gets focus gained/lost because of my debugging, I put a breakpoint where SDL_SetWindowFullscreen is called in INTERNAL_RunLoop and the flags aren't set there either. The flags only get set when I hit F11.

No use of System.Windows.Forms in our project.

...hmm... I realized that I could restore-down my Visual Studio window and actually watch when it goes fullscreen (because it's a smaller window during initialization, before it goes fullscreen).

It's on this specific line:

SDL.SDL_SetWindowPosition(
                    INTERNAL_sdlWindow,
                    x + ((INTERNAL_glFramebufferWidth - clientWidth) / 2),
                    y + ((INTERNAL_glFramebufferHeight - clientHeight) / 2)
                );

This is... strange.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Ah, now that might be something:

https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/SDL2/SDL2_GameWindow.cs#L354
https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/SDL2/SDL2_GameWindow.cs#L363

These two lines, take 'em out. Wondering if we screwed something up early on for when handling window events. Even though the focus isn't getting touched (er, well, it shouldn't), it may still mess with the flags.

This may also be why window state is getting wonky on seemingly unrelated SDL window calls, but I don't know if that's our fault or SDL2 doing something internally.

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

Took those two lines out & it didn't appear to have any effect.

Why is it that .SDL_SetWindowPosition() is making it go fullscreen? Does that just mean that something else set the flags to make it fullscreen prior to that call, and that call happens to be Applying Changes?

(Not sure if it's relevant but the position it's setting the window to is (0, 0)).

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Does removing that block of code to center the window fix it?

Here's the SetWindowPosition in SDL... not sure if tracing this will lead to anything interesting:

http://hg.libsdl.org/SDL/file/cf99258f905c/src/video/SDL_video.c#l1524

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

Removing the SetWindowPosition call, DOES prevent it from going fullscreen on startup. Pretty cool :)

Then, if I hit F11, it goes fullscreen. However, subsequent F11s only make it flicker, and it stays fullscreen. That's gotta be another hint... so I'll debug more of that (might hop over and do the Ludum Dare now, though - if it's an interesting theme).

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Another wrinkle is that despite having "Window.AllowUserResizing = true;" Window resizing is not being allowed.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

I actually don't think I ever bothered to implement that. Look into the resizable window flag and resize events, then submit the patch. None of my games use that, so I have nothing to test with.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Ok sounds good. We'll take a peek. Thanks!

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Ah, now I remember why I didn't bother implementing it: this little gem:

https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/SDL2/SDL2_GameWindow.cs#L167

For some reason, SDL2 never had a SetWindowResizable, so it can only be set before SDL_CreateWindow. So, if you need this variable, just change this line manually:

https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/SDL2/SDL2_GameWindow.cs#L576

I'll need to add this as a remark in the SDL2_GameWindow's documentation. The window should at least be resizable after that, but I don't think the viewport is modified, just the mouse scaling:

https://github.com/flibitijibibo/MonoGame/blob/monogame-sdl2/MonoGame.Framework/SDL2/SDL2_GameWindow.cs#L370

It might be worth asking the SDL mailing list why a SetWindowResizable was never made... I can't really think of a reason, unless it affects the GL context.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Those changes seemed to have worked. Just needed to add this into the SDL event handling as well for it to behave the same way XNA does.

if(evt.window.windowEvent == SDL.SDL_WindowEventID.SDL_WINDOWEVENT_RESIZED)
OnClientSizeChanged();

The only issue I see now is when we switch to fullscreen the graphics get stretched (since we force our viewport to 16:9. I think thats due to the SDL window forcing the render to cover the whole window, but I'll explore it a bit more. Let me know if you might have any insight. Thanks a ton for your help!

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Compare it to XNA4 and let me know what you get. As far as I know it should work if you set the backbuffer preferences to the actual display mode, then adjust the Viewport accordingly (this is what we do for FEZ).

Also, I've added in the resizable window changes:

766cb17

The resizability for the SDL2_GameWindow is now configurable via #define. This should be particularly nice when merging branches that change things in this file.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Thanks! You actually need to put another check in there to check to make sure it is specifically a resize event, otherwise you'll get an infinite loop in my experience.

Good work on the define. Good idea!

I have it on the same codebase with MonoSDL2 and XNA4. Everything works the same except the fullscreen on Mono is stretched vertically. In XNA4 it automatically letterboxes the rendering. I'm setting the Viewport to be 16:9 as well as the preferredbackbufferwidth/height. You are saying the preferredbackbuffer stuff should be to the actual display resolution rather than the viewport size?

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Hmmm. Actually on my fullscreen code, I'm not doing the 16:9 fixing properly. Let me explore. XNA must be doing something extra under the covers that is fixing my mistake.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

If you're using Window.ClientBounds to check the display size, change it to the GraphicsDevice/GraphicsAdapter information instead. For fullscreen on SDL2, the ClientBounds will always be the native screen resolution, so if the intended resolution ends up being lower than the native res, the info will be wrong. I'm hoping to fix this internally, but the MonoGame core implementation uses the ClientBounds in too many places, so I have to stick with it until we get the core library using the INTERNAL_backbufferWidth/Height.

I'll split up the resize events, now that I look at it it would probably cause an infinite loop inside ApplyChanges... my bad.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Ended up just splitting those two window events:

cc7f2e6
17d08e2

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Those changes look good.

I am using the GraphicsDevice width and height already. And I changed my code to force a 16:9 PreferredWidth/Height and I get the same results. So it seems like XNA is doing something on its own to center the viewport rather than stretching it. I'll dig around some more tomorrow.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Hmmm. So the more I look at this, the more it looks "correct" (in that I'm rendering properly to a 1280x720 canvas). I'm pushing our game to fullscreen at 1280x720. Both XNA and Monogame agree that that is a valid DisplayMode for my monitor. As best I can tell, XNA actually changes my monitors resolution to that, causing a letterboxing effect (presumably done via the driver). SDL appears to be doing a "fake" fullscreen though, where it isn't actually changing my resolution. So instead of letting my graphics driver do the letterboxing for it, Mono is just stretching everything to fit as if the resolution was actually 1280x720. FYI, my screen is 1680x1050. I've tried changing SDL2 to use "actual" fullscreen where it changes my display mode, but that is just resulting in a black screen.

It seems like this is just what SDL does: http://forums.libsdl.org/viewtopic.php?t=4373&sid=d8fd7fcc8a2e16e71a1df6edf1949080

If you switch to a resolution that your driver supports but isn't the same aspect ratio as your monitor you'll get the stretching in SDL in fake fullscreen mode. Although I guess theoretically if your driving doesn't do letterboxing automatically this could be a problem in real fullscreen mode as well. Looks like rendering to a texture and scaling that up and letterboxing on my own is the way to go. Fortunately I just switched things to render the whole scene to texture yesterday for another reason.

Thanks for you help on this one. Let me know if you have another idea, I think this is the correct route though.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

I had to make this change in GraphicsAdapter.CurrentDisplayMode within the SDL2 define:

SDL2.SDL.SDL_DisplayMode dm;
SDL2.SDL.SDL_GetCurrentDisplayMode(0, out dm);

            return new DisplayMode(
                dm.w,
                dm.h,
                dm.refresh_rate,
                SurfaceFormat.Color
            );

I think that is probably the correct way to do it. Short of maybe caching the value. Although, that probably isn't necessary. It allowed me to actually get the display resolution and do the letterboxing myself. Worked like a charm. Only problem I have now is when I come out of fullscreen the Mono version of the code doesn't restore the old resolution. Probably something easy I'd guess.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Indeed, that is what we do in the SDL2_GameWindow, as I mentioned earlier in the thread.

Odds are it's the monitor that's able to letterbox when the aspect ratio is off. Not yet aware of any driver that'll handle that.

If you need the "intended" resolution, grab the CurrentDisplayMode. If you want the actual resolution, grab Window.ClientBounds. That should give you the info needed to letterbox on the right aspect ratios.

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

Committed some changes from Darthdurden's window tweaks:
SeanColombo@e5f5c07

Due to my github n00bery, I'm not sure how to do a pull request for that because we have another pull request from the same branch that's waiting to get merged (so it's trying to pick up all of those changes too).

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

You'll need to create a new git branch and then push that branch to your origin.

However, I don't know if I want those changes. This breaks the ability to get the fullscreen FBO resolution when you can get the "real" resolution from Window.ClientBounds.

from fna-mghistory.

SeanColombo avatar SeanColombo commented on June 21, 2024

The change darthdurden made, makes it analogous to how XNA does it.

Can't you just get the values you're looking for from GraphicsDevice.PresentationParameters?

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

I'm largely doing this for the sake of XNA4 accuracy. The original XNA API behavior needs to be 100% accurate to the original, and the SDL display mode will not be the same in every case. The platform extensions, however, I am willing to let by, since calls like Game.Window.ClientBounds can have different behavior on varying platforms.

I don't think I ever got a test case, anyone have one?

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

Yea I actually made this change to make it accurate to XNA4. The DisplayMode property returns the current DisplayMode of display you are using, regardless of your backbuffer size when you are in XNA. When I want the backbuffer size, I just query GraphicsDevice.PresentationParameters. The test cause is just making a non-fullscreen window and checking all of those parameters.

I guess the way you have it implemented will work if you are in fullscreen since the backbuffer and screen resolution are the same, but basically this fixes things for windowed mode as well. Any reason you wouldn't want to just query PresenationParameters if you want backbuffer info?

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

It's less about what I'd do, but rather what the client did when writing their XNA4 game. This is how they ended up writing their code, and it bugs out on MG-SDL2.

That said, I just looked at the original code I had in there before using the FBO dims:

fee6195

So maybe that code will work? Let me run it through AVNT real quick, as that's the game that queries this value.

I'll just push this myself if it does work, as there are some other things I need to change in the GameWindow as a result.

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

http://www.flibitijibibo.com/avntMode.zip

The AVNT code works in XNA4, but with that DisplayMode change it causes ^ in MG-SDL2.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

So I think this is the problem:

Lets say you have a 1920x1080 display for this example and want to run your game at 1280x720.

In SDL2 "Fullscreen Mode" isn't really fullscreen in the current code. If you run in fullscreen it is making the window the same size as the screens resolution (so 1080p). So you have a 1920x1080 window taking up the whole screen but with a backbuffer of only 720p size, but scaled up so that it looks like your actual resolution has switched to 720p. So my guess is that is why you want the DisplayMode to return the backbuffer size, since in XNA, those would be the same since it goes into real fullscreen mode and actually changes the screen display resolution.

So really that DisplayMode code should return what you are proposing if we're in fullscreen mode, but when in windowed mode, it should be return what I'm proposing. I think.

But long story short, I think my code is technically correct, except that fullscreen isn't done the same way it is done in XNA. So either we fix that somehow (which probably isn't worth it), or just change the way DisplayMode works depending on if we are in Fullscreen or not.

Does that make sense to you?

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

In windowed mode, the FBO dimensions will be the same as the window dimensions, so in windowed mode it would not matter which is queried. Only in fullscreen mode will the two values vary, and only when the intended resolution is different.

Basically, make it correct in XNA first, then fix the MonoGame bugs (and for platform code such as direct use of GameWindow, be prepared to def things for XNA4 and MonoGame). That is rule #1 of the MG-SDL2 project.

If that's the idea you have in mind, go for it. It really does sound like you just want to render your game solely in 720p regardless of the resolution, with black borders around the viewport. AVNT actually does the same thing, and the way that is done is by allowing any resolution, but making the viewport 1280x720 inside that resolution. You cannot assume that a 720p fullscreen window will magically have borders around the viewport; this is only ever done by the monitor rather than the OS display manager. I would even suggest changing your OS display mode just to be sure that the monitor is doing the work rather than the OS.

In fact, here's my desktop at 1152x864, with my monitor set to letterbox, as an example of this:

http://www.flibitijibibo.com/monitorboxing.jpg

It's also worth noting that forcing your viewport to a resolution when you have the option to avoid it (read: you're not doing a port from the 360) is pretty much asking for PC gamers to hate you.

from fna-mghistory.

darthdurden avatar darthdurden commented on June 21, 2024

I agree that the window and FBO dimensions would be the same in windowed mode. I'm interested in getting the current display mode though (ie. the actual resolution that the OS is outputting to determine what we want to display to the user when they go to fullscreen mode).

I suppose I could possible switch the code around to put it into fullscreen first and then query the DisplayMode to get the resolution. The only problem with that is that in XNA the DisplayMode actually changes (to match the viewport as best I can tell) so you'll get essentially the backbuffer size. SO XNA and Mono will disagree on what to do at that point.

As for forcing 720, that isn't what we're planning on doing. Right now we are rendering to a 720 backbuffer on a RenderTarget in fullscreen mode, but we scale it up to fill the screen. It probably won't stay that way and we'll most likely render to as big of a 16:9 area as we can based on the width/height of your monitor with letterboxing (done on our end) where appropriate.

Anyway, I get what you're saying about the defines, I can probably figure something out. I'll look at the spots where we are getting DisplayMode and see if they can do it some other way when in Mono. Or we'll just fork that file if all else fails. ;)

from fna-mghistory.

flibitijibibo avatar flibitijibibo commented on June 21, 2024

Someone else figured this one out for you:

5bb1a57

The faulty behavior was also in GraphicsDevice, not just GraphicsAdapter.

This should now be resolved.

from fna-mghistory.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.