We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 2998

Summary: Vsync fails to work while SDL window is covered by another opaque window in Mac OS X
Product: SDL Reporter: Joshua Bodine <josh>
Component: videoAssignee: Alex Szpakowski <amaranth72>
Status: RESOLVED ABANDONED QA Contact: Sam Lantinga <slouken>
Severity: normal    
Priority: P2 CC: amaranth72
Version: HG 2.0   
Hardware: x86_64   
OS: Mac OS X (All)   
Attachments: code that demonstrates issue

Description Joshua Bodine 2015-06-02 10:16:59 UTC
Created attachment 2169 [details]
code that demonstrates issue

When a non-fullscreen window with an OpenGL context (and SDL_GL_SetSwapInterval(1) enabled) is completely covered by another application's opaque window, the framerate is no longer restricted to vsync and the framerate increases dramatically, consuming a lot of CPU. Once any portion of the SDL window is visible again, vsync works properly again. Obstructing the SDL window only partially, or obstructing it entirely with a translucent window, does not cause the framerate to increase.

The attached source file demonstrates this issue.

My operating system is Mac OS X 10.10.3. This behavior was observed in SDL 2.0 development code in mercurial as of today's date.
Comment 1 Alex Szpakowski 2015-06-02 17:27:18 UTC
I believe this is completely out of SDL's control – it's just how the modern OS X window manager works, even when the app requests vsync.

It's also worth mentioning that (on any operating system) vsync requests are just requests. The OS gets the final say in when to actually use it, and users often have the option to completely disable it system-wide (even in OS X.)

It is possible to get notified when such an occlusion event happens, however SDL doesn't currently make use of that to post its own event (SDL_WINDOWEVENT_HIDDEN or similar.) It would probably be useful to add that: https://bugzilla.libsdl.org/show_bug.cgi?id=2656
Comment 2 Alex Szpakowski 2015-10-03 01:59:31 UTC
Mac OS 10.11 seems to have fixed this behavior (on my system at least), for what it's worth.
Comment 3 Joshua Bodine 2017-07-08 17:16:47 UTC
I just checked back in here on this bug status since I am still experiencing it in our program on macOS 10.12.5 and SDL 2.0.5. We have a workaround in place to stop the program from eating 100% CPU when the window is obscured, but without the workaround the problem still exists.

As for the claim that this is standard macOS behavior, I haven't tried this recently, but when I wrote an experimental pure Cocoa application to test this same behavior, the framerate remained consistent when the window was obscured. I therefore believe that it is indeed possible, although I don't know what it would take to replicate it in SDL.
Comment 4 Alex Szpakowski 2017-07-14 02:58:05 UTC
How did your Cocoa app's render loop execute? From my understanding, a lot of Cocoa apps use a CVDisplayLink (or a higher level API which wraps that) in order to get a callback that executes before every display refresh event, and then use that callback to render. That would allow for steady framerates no matter the vsync setting requested in the OpenGL context.

That sort of thing is not feasible to implement in SDL's mac backend code because SDL exposes a polling and push-frame API, rather than a callback-based one.
Comment 5 Joshua Bodine 2017-09-01 05:42:58 UTC
It was a very basic Cocoa app. I created a window with an OpenGL View in the interface editor (or whatever it's called now), put something in the main loop (I think) to set the view to always need redrawing, and then I put some framerate tracking/print out code in the method that was called when the app tried to re-draw the view. It was some time ago, so some of the details escape me, but I do remember that the framerate remained constant when the window was obscured.

The more I think about it, the more I think that using vsync to throttle your entire application is probably not a great idea on our end. Nonetheless, it seems to me that having your rendering function lose vsync when your application's window is obscured would be unexpected behavior.
Comment 6 Sam Lantinga 2017-09-01 17:30:03 UTC
For what it's worth, I tried reproducing this on Mac OS X 10.12.6 and wasn't able to. It seems this may have been fixed in later OS versions.
Comment 7 Alex Szpakowski 2017-09-01 21:20:46 UTC
(In reply to Joshua Bodine from comment #5)
> It was a very basic Cocoa app. I created a window with an OpenGL View in the
> interface editor (or whatever it's called now), put something in the main
> loop (I think) to set the view to always need redrawing, and then I put some
> framerate tracking/print out code in the method that was called when the app
> tried to re-draw the view. It was some time ago, so some of the details
> escape me, but I do remember that the framerate remained constant when the
> window was obscured.

I believe that's a similar situation to what I described above - the Cocoa run loop fires off draw events at a rate slower than a busy loop (possibly tied to the monitor's native refresh rate), even when the OpenGL context doesn't have vsync enabled.

SDL's APIs cannot hook into and expose this behaviour because SDL's external APIs are polling, rather than callback-based.
Comment 8 Ryan C. Gordon 2018-08-06 21:20:23 UTC
Hello, and sorry if you're getting dozens of copies of this message by email.

We are closing out bugs that appear to be abandoned in some form. This can happen for lots of reasons: we couldn't reproduce it, conversation faded out, the bug was noted as fixed in a comment but we forgot to mark it resolved, the report is good but the fix is impractical, we fixed it a long time ago without realizing there was an associated report, etc.

Individually, any of these bugs might have a better resolution (such as WONTFIX or WORKSFORME or INVALID) but we've added a new resolution of ABANDONED to make this easily searchable and make it clear that it's not necessarily unreasonable to revive a given bug report.

So if this bug is still a going concern and you feel it should still be open: please feel free to reopen it! But unless you respond, we'd like to consider these bugs closed, as many of them are several years old and overwhelming our ability to prioritize recent issues.

(please note that hundred of bug reports were sorted through here, so we apologize for any human error. Just reopen the bug in that case!)

Thanks,
--ryan.