Skip to content

Loading…

Fullscreen on OS X never actually performs a mode switch. #300

Closed
ryanfields opened this Issue · 23 comments

5 participants

@ryanfields

I noticed that the fullscreen implementation on OS X does not do a mode switch, even when requesting a valid hardware mode. The current implementation always creates a window the size of the current desktop, and only creates the GL context at the requested mode size.

As usual, I've got some code to offer as a solution. It checks that the mode is valid, then performs a configure on the main display before setting the rect of the window. This should be more in line with the behavior developers would expect from a fullscreen feature.

I'll submit a pull request shortly.

EDIT

I noticed I left some code duplication unresolved in my changes. I'll submit a pull request after I deal with that tonight or tomorrow.

@mantognini mantognini was assigned
@mantognini
Simple and Fast Multimedia Library member

I noticed that the fullscreen implementation on OS X does not do a mode switch, even when requesting a valid hardware mode. The current implementation always creates a window the size of the current desktop, and only creates the GL context at the requested mode size.

Yes, that's intended. Do you have graphical issue with it ?

In the previous version, that is 1.6, Ceylo also use mode like in your PR. But we decided to change that for these reasons:

  • it's easier to handle : e.g. when you switch from your app to some other app you have to restore the desktop mode
  • it's better for the user : I hate when the icon on my desktop are moved around because the screen change its size
  • it can be supported without much pain on 10.5 (*) : you use a function that doesn't exist on Leopard (CGConfigureDisplayWithDisplayMode)

(*) yes : SFML 2.0 still supports this OS. This might change in the future for 2.1, maybe.

@mantognini
Simple and Fast Multimedia Library member

BTW, I know that some stuff could be implemented in a better way so I like issue and pull request like this one, even if some of PR don't lead to a merge, especially now that I don't have a lot of free time.

@ryanfields

I'm not sure it falls under the category of "graphical issue", but I get mediocre performance on my laptop and desktop Macs when running at their native display resolutions. I've got a 1920x1200 display, and a 1440x900 display, and in both cases I tend to run fullscreen games at one or two modes lower to get better performance.

There is a graphical issue present though, and that's one of aspect ratio. In the current implementation, SFML lies to the developer by saying, "Affirmative, I'll use the 1024x768 video mode!" when behind the scenes it has given the developer a 1024x768 context stretched to fit the desktop mode. By telling me 1024x768 is a valid mode, and then allowing me to create a fullscreen window with a 1024x768 mode requirement, SFML has insisted that it did the right thing and I am forced to trust it. In reality, it has stretched my 1024x768 content out of proportion and there's little I can do as a developer to resolve that (aside from digging into SFML's code, which is viable but not a practice SFML's users should ever need to resort to.)

In contrast, my proposed implementation puts aspect-ratio correctness in the hands of the developer, which is where that responsibility belongs. In my implementation, if I ask for 1024x768, I get true 1024x768 (letterboxed on my giant display, but at least the aspect ratio is right). My proposed implementation still gives the developer the option of doing "fake" mode switching, but offers the alternative of true mode switching. If I want to do a fake mode switch, I just ask for a fullscreen window at the desktop size and then account for the aspect in my drawing code. In either case, the context I get back for drawing on is exactly the size I asked for. No magic happens behind the scenes.

On that note, I'm actually thinking about removing the fake fullscreen fallback that I originally carried over into my implementation. If a window is opened with the fullscreen flag for a mode that isn't supported, the implementation really should just open a non-fullscreen window as the fallback, again to avoid any magic that creates a separation between real aspect-ratio and context aspect-ratio.

If SFML wants to provide the option of creating contexts that are locked to a size and stretched, that should be an entirely separate feature.

Now, I must also address the bullet point concerns raised.

It's easier to handle
The changes proposed in my pull request make it simple to handle command-tabbing out of the fullscreen app. I've gone ahead and added that handling as part of my pull request. Using my proposed changes, I can command-tab out of my test app and the desktop is returned to its original mode. Re-focusing my app puts my display back into the game resolution.

it's better for the user
It is not always better for the user. The important detail here is that it should up to the user, not to SFML. SFML should allow mode switching, but not require it. The game developer using SFML should offer the end user a choice of resolutions to run the game in, including desktop. The end user then has the choice. You can chose to run at desktop resolution so that your windows and icons aren't resized/moved. I can chose to run at a desired mode, because it improves my gaming experience. This is optimal. Right now, you get to be happy, while I have to deal with sub-par conditions. The blanket statement "it's better for the user" is not valid because different users have different requirements and priorities. You and I are a prime example of that.

it can be supported without much pain on 10.5
I meant to write this for both 10.6 and earlier versions and unintentionally left out the 10.5 code path. I will address that in my pull request. Prior to 10.6, there was CGDisplaySwitchToMode, which achieves the same hardware switch. In 10.5 and older, you use that to just perform a blanket mode switch across all the displays. With 10.6 and up, we get this nice "per-display" option that allows us to switch the mode of only the display we care about, and leave the other displays untouched (which is what my proposed changes do). I will happily add in the < 10.6 support to my proposed changes.

I hope I've made an effective case for true hardware switching, because that feature is important to me. The key detail to note here is that the current SFML implementation only allows fake fullscreen, while this proposed implementation allows either fake or true fullscreen. The "cost" of my implementation is that we temporarily lose the ability to lock the GL context to a specific set of dimensions, but I'm not sure that was ever a feature in the first place. It appears that it was just a side-effect or workaround on the OS X side of the current implementation and may actually be inconsistent with the Windows implementation.

@mantognini
Simple and Fast Multimedia Library member

Let me rephrase what you wrote and tell me if that's what you meant.

You want SFML to prevent the developer to create stretched content by choosing a video mode that is not of the same ratio as the screen (e.g. 4:3 mode on a 16:10 display) by using letterboxing.

Wouldn't be easier, or at least more correct, for the developer to provide only fullscreen mode that have the same ratio as the desktop ?

I can command-tab out of my test app and the desktop is returned to its original mode. Re-focusing my app puts my display back into the game resolution.

Great! But you still have this blue screen transition, right ? It's really slow, isn't it ? If that's the case, is it really better to have that feature ?

You can chose to run at desktop resolution so that your windows and icons aren't resized/moved.

This only rely on the kindness, or professionalism, of the developer. If the user can't change the video mode before the first run to something that match it's desktop size then it's not a viable solution. SFML should not, in any case, interfere with the user's workspace settings.

@retep998

Pretty much every single game I play, when I go fullscreen, it changes the video mode completely to that resolution. While providing a stretched context does give a nearly identical effect, especially on LCD monitors where smaller resolutions are merely scaled anyway, it's very different for a CRT monitor which is actually capable of displaying such resolutions natively and can degrade visual quality if you merely stretch the context. Also, using a different aspect ratio does not result in letterboxing. My 1080p monitor can handle 1280x1024 just fine, although it does cause some games to appear stretched. However many games, such as all the games by Codemasters, allow you to manually specify the ratio so they adjust the scale of the UI and the ratio of the perspective.
Anyway, what I think the proper solution should be, is make sf::Style::Fullscreen necessitate a full mode switch, and error if the resolution isn't supported. There's already an API for iterating through all the display modes, so why make it irrelevant by just stretching the context? Now, I do understand that some people would prefer to merely stretch the context, so perhaps we should add some sort of sf::Style which merely stretches the context to the current desktop resolution. Likewise, if someone wants letterboxing, we could add that as well. Remember, the norm in pretty much the entire video game industry is to perform a mode switch, so when I specify a lower resolution in fullscreen, I expect a full mode switch to a lower resolution, unless of course I specify to simply stretch the context using the new sf::Style's which I hope you add.
On another note, on windows when I create a window without any borders, if I specify my resolution, it suddenly switches to fullscreen. 1920x1079, still a window, 1920x1080, bam its fullscreen. While this isn't much of an issue, if I make my window semi-transparent using the windows aero api, it doesn't work in fullscreen. So if I want to have a snowy overlay over my live desktop I have to lower one of the dimensions by a pixel.

@ryanfields

That rephrasing is not accurate, mainly because it ignored the first point I made. I get better performance at lower resolutions. As a hardware abstraction layer, SFML should give me access to those modes if it reports support for those modes.

As to the aspect-ratio issue, the problem is that SFML misrepresents the resolution. If I ask for 1024x768, that's exactly what I should get, a visual space that is 1024 pixels wide and 768 pixels tall. Instead, what I get is a visual space that is 1920 pixels wide and 1200 pixels tall, but SFML tells me I have a space that is 1024 by 768. So then I do all of my drawing as if the screen I'm drawing to is 1024x768, because that's what SFML has told me I am drawing to. In reality, I am drawing to 1920 by 1200, and my output is being distorted. The only time my output should ever be distorted is when I explicitly ask the HAL to distort it, and in this case I haven't.

I don't understand why the current implementation would be considered "easier". In order to achieve aspect-ratio correction in the current implementation (which it can't currently do), the following steps must be taken:

  1. Determine the desktop size.
  2. Create the window at the desktop size.
  3. Create the context at the requested size.
  4. Scale the context until one of its dimensions meets the corresponding window dimension.
  5. Translate the context along the opposite axis until it is centered.

In the mode-switch implementation, these steps suffice:

  1. Create the window at the requested size.
  2. Create the context at the requested size.
  3. Switch the mode.

Regarding the slowness or ugliness of the mode switch... I don't see how that takes priority over higher game performance or aspect ratio correctness. I'd much rather have a fast running game. If dropping the resolution doubles my frame-rate, then I really don't care at all if the mode switch that got me there looked ugly or took a couple seconds. If my game is running at 30 FPS instead of 15 FPS, I'm a happy user.

The industry standard in desktop gaming is to let the user choose the video mode in which to run the game, not to lock the game to the desktop resolution. SFML should strive to meet the industry standard.

EDIT
And no... it wouldn't be more correct for the developer to only offer modes that match the desktop aspect ratio. It's entirely plausible to have video hardware that supports a 16:9 high resolution mode that's slow, and a bunch of 4:3 modes that are blazing fast. There's no way to know what kind of hardware SFML will be running on. The correct thing to do is let the end user chose the mode that gives them the best performance, and provide access to that mode instead of faking it.

@LaurentGomila
Simple and Fast Multimedia Library member

I don't know much about what happens with fullscreen on OS X, but:

  • on Windows and Linux, sf::Style::Fullscreen is implemented with a true switch to fullscreen mode
  • users who really want to avoid the fullscreen switch can still use the current strategy, by creating a window which has the same size as the desktop and with sf::Style::None

So, with the addition of the other arguments explained above (better performances, etc.), I'd say that switching to fullscreen mode seems to be a better solution.

@mantognini
Simple and Fast Multimedia Library member

Here is the discussion I had with Ceylo a long time ago. It explains why the current implementation was chosen.

That rephrasing is not accurate, mainly because it ignored the first point I made. I get better performance at lower resolutions.

If the rephrasing was only wrong on the performance-part then you will be amazed by how computers work today. I've made a quick benchmark to compare the performance of your implementation VS the master branch. You can find it here.

Conclusion :
  • performance are the same
  • 'master' version stretches the content is the mode has not the same ratio as the display
  • 'fullscreen' version resizes all open windows

I understand your points. It would be cool to get those mode with letterboxing, yes! However, until we find a solution to workaround the resizing of the windows (for example Finder, Mail, ... ; all those apps that are running before launching the SFML app are completely resized and moved to match the new mode but their size are not restore when the SFML app exits so you have to resize them all manually), I don't think it's a good idea to use that mode switch. (And we can work on this for SFML 2.1 ;-) )

@ryanfields

I finally had a chance to run that benchmark:

[MODE-SW] REPORT : 500 sprites rotating; 1984 frames in 20 seconds; ~99.2 FPS
[DESKTOP] REPORT : 500 sprites rotating; 1693 frames in 20 seconds; ~84.65 FPS

[MODE-SW] REPORT : 1000 sprites rotating; 982 frames in 20 seconds; ~49.1 FPS
[DESKTOP] REPORT : 1000 sprites rotating; 861 frames in 20 seconds; ~43.05 FPS

[MODE-SW] REPORT : 2000 sprites rotating; 498 frames in 20 seconds; ~24.9 FPS
[DESKTOP] REPORT : 2000 sprites rotating; 432 frames in 20 seconds; ~21.6 FPS

On the surface, the numbers don't look that far off, but in practice, the experience at desktop resolution is awful. Amazed is not how I'd describe myself. The rotation stutters severely, no matter what the FPS, when operating at desktop resolution. At true 800x600, the 500 and 1000 sprite benchmarks flow extremely smooth. The 2000 sprite benchmark isn't "smooth" at 25 FPS, but the granularity is what I would expect at 25 FPS. It's visually rough, but does not exhibit the random, uneven stutter that I get at desktop resolution.

I still believe that using the requested hardware mode is a superior solution to faking it with a desktop overlay.

@retep998

The performance difference you're getting is identical to the difference I get between fullscreen at 800x600 and windowed at 800x600 over my 1920x1080 desktop here on windows. As well, I encounter slight stutters in windowed mode which do not occur in fullscreen. For people who aren't running a high end gpu, being able to run your game at an actually smaller resolution, rather than merely upscaling, lowers the pressure on the gpu by not having to pipe a full 1080p display. I don't know a single person who would be willing to trade off slower framerates just to boost their alt+tab speeds.

@mantognini
Simple and Fast Multimedia Library member

I'll try to test it again but don't expect it to be soon. I'm completely under water with my other jobs.. probably around february..

Anyway, as I said, I'm willing to use those modes to prevent the screen from stretching (and, if, as you said, those modes also make the animation more smooth, it would be cool). The only thing I want to make sure before using them is that the user's desktop and windows are not rearranged because of the mode switch.

I currently don't know how to do it and as I don't have that much free time, any input would be appreciated. :-)

@JayArby

The window/icon move/resize issue exists in windows as well, but I'm pretty sure it's just considered normal. Every fullscreen game I've ever played has this issue when run at lower resolutions. The systems should provide automatic handling for this issue, but they just don't. Not on windows, not on mac. As Laurent pointed out, there is a workaround if you do not wish to do a display-mode switch.

@retep998

I've never had the issue of icons moving around or windows resizing when I play fullscreen games and I'm using Windows. Maybe it's just your system that has that issue. Kinda weird considering it's my system which has the problem in issue #306. Man, fullscreen support feels like such a mess.

@mantognini
Simple and Fast Multimedia Library member

Every fullscreen game I've ever played has this issue when run at lower resolutions. The systems should provide automatic handling for this issue, but they just don't.

It's not a valid argument to be lazy; let's – at least – try to find a workaround. ;-)

As Laurent pointed out, there is a workaround if you do not wish to do a display-mode switch.

This solution doesn't work on Mac, sadly.

@LaurentGomila
Simple and Fast Multimedia Library member

This solution doesn't work on Mac, sadly.

Hum? Why?

If it doesn't work it's a bug.

@mantognini
Simple and Fast Multimedia Library member

Maybe I've misunderstood what was the workaround but when you create a borderless window of the size of the desktop, you still have the menu bar (and maybe also the dock) so it's not equivalent to a fullscreen mode.

@LaurentGomila
Simple and Fast Multimedia Library member

True, I didn't think about that, sorry.

@ryanfields

My code branch does the exact same thing that the original did when requesting a desktop-sized mode. There is no menu bar or dock...

@mantognini
Simple and Fast Multimedia Library member

Yes, but the window's style is not sf::Style::None as in Laurent's workaround for Windows.

BTW: the current impl does that too (of course)

@ryanfields

My code branch doesn't require a workaround... It just does the right thing depending on the mode you ask for...

If you want to run fullscreen at desktop resolution, choose sf::Style::Fullscreen and the desktop resolution.
If you want to run a smoother fullscreen mode, use sf::Style::Fullscreen and a lower resolution.

If you hate your windows being moved around, stick with method 1.
If the moving issue doesn't bother you (as several here have commented), use method 2.

The way the OS handles mode switching is a limitation of the OS and is not our problem to solve. We should be providing gamers the ability to have smooth, fast video. We should not be so concerned with providing a smooth mode change experience that we prevent gamers from having smooth, fast video.

@mantognini
Simple and Fast Multimedia Library member

Apparently there were some misunderstanding.. There's no point in discussion about this workaround IMO. What I said earlier still holds.

Anyway, as I said, I'm willing to use those modes to prevent the screen from stretching (and, if, as you said, those modes also make the animation more smooth, it would be cool). The only thing I want to make sure before using them is that the user's desktop and windows are not rearranged because of the mode switch.

@ryanfields

OS X will always attempt to make all windows and their content remain visible within the frame of the screen when performing a video mode switch. It is not possible to prevent this. The only way to deal with it at all is to deeply hack at some private API calls which are undocumented. Doing so will prevent any app built on SFML from being included in the Mac App store. It will also make SFML susceptible to internal API changes that could lead to crashes anytime a user installs updates to OS X.

We should not be trying to fight the OS, even when we feel that one of its behaviors is inconvenient. Fighting with the OS is not appropriate behavior for Mac applications and is a poor practice for OS X developers to adopt.

It is not possible to exert the kind of control over other applications' windows that is needed to prevent them from being moved by a mode switch.

@mantognini
Simple and Fast Multimedia Library member

Ok, so I give PR #301 another shot and measured the performance on all available resolutions. On my computer, with high resolution I lose a little bit less than 10% and only gain ~2% with very low resolution. It is also not compatible with 10.5 without a lot of modification (in DisplayImpl.hpp CGDisplayModeRef is used).

I also tested very quickly a game : they use switch mode but somehow managed to prevent all windows to be resized. (I just need to know if their code will work on 10.5...) So there should be a solution to that issue !

I don't know if I'll use switch mode or a modified backbuffer yet. I need to implement both versions and test their respective performance. So I close this issue now and open a new one to reflect exactly the task.

@mantognini mantognini closed this
@mantognini mantognini removed this from the 2.0 milestone
@mantognini mantognini was unassigned by ryanfields
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.