Fixed bug 4788 - macOS 10.14 (Mojave) opengl issues (SDL-1.2) SDL-1.2
authorSam Lantinga
Sun, 05 Apr 2020 08:54:07 -0700
branchSDL-1.2
changeset 13688ab7529cb9558
parent 13665 9c0fc6e28c5e
child 13802 2f82852644d1
Fixed bug 4788 - macOS 10.14 (Mojave) opengl issues (SDL-1.2)

Murphy

I don't build SDL apps on macOS myself, but two recent pieces of code I've written have run into this (or a related Mojave/SDL1.2 blank screen bug) for other users. I thought I'd share what I'd gleaned in case it's helpful.

First, I notice the issue specifies OpenGL. Maybe that's a backend thing I'm not aware of or maybe there are multiple blank screen bugs related to Mojave, but this also occurs with applications that aren't (explicitly, anyway) doing anything with OpenGL.

Second, the solution of building with an old SDK (e.g., the macOS 10.13 SDK from Xcode 10.1) resolves it (though it's a pain).

Third, it looks like this came up in DOSBox-X and Jon Campbell patched the vendored SDL1.2 to fix it (I haven't tested this on my own applications). I'm not sure if there was an attempt to upstream this, but here's the commit and a related issue tracker entry where it's discussed:
https://github.com/joncampbell123/dosbox-x/commit/fdf6061c05dcb35a1ea111ad5b75ade350059df3
https://github.com/joncampbell123/dosbox-x/issues/896

Fourth, lending credence to the idea that there may be multiple bugs at play here, some of the Mojave bug reports refer to a *black* screen, but others are less specific about "no video" or "blank screen" or the like. In the case of my applications, the result isn't black. It's light gray or something (possibly a default window background color?).

[Fixed with patch by Alex Sirota]
src/video/quartz/SDL_QuartzVideo.m
src/video/quartz/SDL_QuartzWindow.h
src/video/quartz/SDL_QuartzWindow.m
     1.1 --- a/src/video/quartz/SDL_QuartzVideo.m	Sun Mar 22 22:03:38 2020 -0400
     1.2 +++ b/src/video/quartz/SDL_QuartzVideo.m	Sun Apr 05 08:54:07 2020 -0700
     1.3 @@ -940,6 +940,10 @@
     1.4      /* Set app state, hide cursor if necessary, ... */
     1.5      QZ_DoActivate(this);
     1.6  
     1.7 +    [ window_view setNeedsDisplay:YES ];
     1.8 +  	[ [ qz_window contentView ] setNeedsDisplay:YES ];
     1.9 +  	[ qz_window displayIfNeeded ];
    1.10 +    
    1.11      return current;
    1.12  
    1.13      /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
    1.14 @@ -1115,7 +1119,11 @@
    1.15  
    1.16      /* Save flags to ensure correct teardown */
    1.17      mode_flags = current->flags;
    1.18 -
    1.19 +    
    1.20 +    [ window_view setNeedsDisplay:YES ];
    1.21 +   	[ [ qz_window contentView ] setNeedsDisplay:YES ];
    1.22 +   	[ qz_window displayIfNeeded ];
    1.23 +    
    1.24      /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */
    1.25      if (fade_token != kCGDisplayFadeReservationInvalidToken) {
    1.26          CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
    1.27 @@ -1155,7 +1163,13 @@
    1.28  
    1.29      if (qz_window != nil) {
    1.30          nsgfx_context = [NSGraphicsContext graphicsContextWithWindow:qz_window];
    1.31 -        [NSGraphicsContext setCurrentContext:nsgfx_context];
    1.32 +        if (nsgfx_context != NULL) {
    1.33 +        	[NSGraphicsContext setCurrentContext:nsgfx_context];
    1.34 +      	}
    1.35 +      	else {
    1.36 +      		/* Whoops, looks like Mojave doesn't support this anymore */
    1.37 +      		fprintf(stderr,"Unable to obtain graphics context for NSWindow (Mojave behavior)\n");
    1.38 +      	}
    1.39      }
    1.40  
    1.41      /* Setup the new pixel format */
    1.42 @@ -1500,10 +1514,17 @@
    1.43      }
    1.44  }
    1.45  
    1.46 -static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects)
    1.47 -{
    1.48 +static SDL_VideoDevice *last_this = NULL;
    1.49 +
    1.50 +void QZ_UpdateRectsOnDrawRect(/*TODO: NSRect from drawRect*/) {
    1.51 +	// HACK
    1.52 +	SDL_VideoDevice *this = last_this;
    1.53 +
    1.54 +	if (this == NULL) return;
    1.55 +  if (SDL_VideoSurface == NULL) return;
    1.56 +
    1.57      if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
    1.58 -        QZ_GL_SwapBuffers (this);
    1.59 +// TODO
    1.60      }
    1.61      else if ( [ qz_window isMiniaturized ] ) {
    1.62      
    1.63 @@ -1512,8 +1533,9 @@
    1.64      
    1.65      else {
    1.66          NSGraphicsContext *ctx = [NSGraphicsContext currentContext];
    1.67 -        if (ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */
    1.68 -            [NSGraphicsContext setCurrentContext:nsgfx_context];
    1.69 +        /* NTS: nsgfx_context == NULL will occur on Mojave, may be non-NULL on older versions of OS X */
    1.70 +          if (nsgfx_context != NULL && ctx != nsgfx_context) { /* uhoh, you might be rendering from another thread... */
    1.71 +                  [NSGraphicsContext setCurrentContext:nsgfx_context];
    1.72              ctx = nsgfx_context;
    1.73          }
    1.74          CGContextRef cgc = (CGContextRef) [ctx graphicsPort];
    1.75 @@ -1528,6 +1550,25 @@
    1.76      }
    1.77  }
    1.78  
    1.79 +static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects)
    1.80 +{
    1.81 +	// HACK
    1.82 +	last_this = this;
    1.83 +
    1.84 +    if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) {
    1.85 +        QZ_GL_SwapBuffers (this);
    1.86 +	// TODO?
    1.87 +    }
    1.88 +    else if ( [ qz_window isMiniaturized ] ) {
    1.89 +        /* Do nothing if miniaturized */
    1.90 +    }
    1.91 +    else {
    1.92 +	[ window_view setNeedsDisplay:YES ];
    1.93 +	[ [ qz_window contentView ] setNeedsDisplay:YES ];
    1.94 +	[ qz_window displayIfNeeded ];
    1.95 +    }
    1.96 +}
    1.97 +
    1.98  static void QZ_VideoQuit (_THIS)
    1.99  {
   1.100      CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
     2.1 --- a/src/video/quartz/SDL_QuartzWindow.h	Sun Mar 22 22:03:38 2020 -0400
     2.2 +++ b/src/video/quartz/SDL_QuartzWindow.h	Sun Apr 05 08:54:07 2020 -0700
     2.3 @@ -47,5 +47,6 @@
     2.4  
     2.5  /* Subclass of NSView to set cursor rectangle */
     2.6  @interface SDL_QuartzView : NSView
     2.7 +- (void)drawRect:(NSRect)dirtyRect;
     2.8  - (void)resetCursorRects;
     2.9  @end
     3.1 --- a/src/video/quartz/SDL_QuartzWindow.m	Sun Mar 22 22:03:38 2020 -0400
     3.2 +++ b/src/video/quartz/SDL_QuartzWindow.m	Sun Apr 05 08:54:07 2020 -0700
     3.3 @@ -220,6 +220,13 @@
     3.4  
     3.5  @implementation SDL_QuartzView
     3.6  
     3.7 +void QZ_UpdateRectsOnDrawRect(/*TODO: NSRect from drawRect*/);
     3.8 +
     3.9 +- (void)drawRect:(NSRect)dirtyRect
    3.10 +{
    3.11 +	QZ_UpdateRectsOnDrawRect();
    3.12 +}
    3.13 +
    3.14  - (void)resetCursorRects
    3.15  {
    3.16      SDL_Cursor *sdlc = SDL_GetCursor();