macOS: Fix asserts in SDL_Render's metal scissor code when the window is resized.
authorAlex Szpakowski <slime73@gmail.com>
Sun, 13 Oct 2019 15:18:28 -0300
changeset 13113eab802de5fbb
parent 13112 8c5d9e937ea8
child 13114 3276502021a5
macOS: Fix asserts in SDL_Render's metal scissor code when the window is resized.
src/video/cocoa/SDL_cocoametalview.h
src/video/cocoa/SDL_cocoametalview.m
     1.1 --- a/src/video/cocoa/SDL_cocoametalview.h	Sun Oct 13 12:16:40 2019 -0300
     1.2 +++ b/src/video/cocoa/SDL_cocoametalview.h	Sun Oct 13 15:18:28 2019 -0300
     1.3 @@ -42,12 +42,16 @@
     1.4  @interface SDL_cocoametalview : NSView
     1.5  
     1.6  - (instancetype)initWithFrame:(NSRect)frame
     1.7 -                      highDPI:(BOOL)highDPI;
     1.8 +                      highDPI:(BOOL)highDPI
     1.9 +                     windowID:(Uint32)windowID;
    1.10 +
    1.11 +- (void)updateDrawableSize;
    1.12  
    1.13  /* Override superclass tag so this class can set it. */
    1.14  @property (assign, readonly) NSInteger tag;
    1.15  
    1.16  @property (nonatomic) BOOL highDPI;
    1.17 +@property (nonatomic) Uint32 sdlWindowID;
    1.18  
    1.19  @end
    1.20  
     2.1 --- a/src/video/cocoa/SDL_cocoametalview.m	Sun Oct 13 12:16:40 2019 -0300
     2.2 +++ b/src/video/cocoa/SDL_cocoametalview.m	Sun Oct 13 15:18:28 2019 -0300
     2.3 @@ -30,6 +30,28 @@
     2.4  #if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_METAL)
     2.5  
     2.6  #include "SDL_assert.h"
     2.7 +#include "SDL_events.h"
     2.8 +
     2.9 +static int SDLCALL
    2.10 +SDL_MetalViewEventWatch(void *userdata, SDL_Event *event)
    2.11 +{
    2.12 +    /* Update the drawable size when SDL receives a size changed event for
    2.13 +     * the window that contains the metal view. It would be nice to use
    2.14 +     * - (void)resizeWithOldSuperviewSize:(NSSize)oldSize and
    2.15 +     * - (void)viewDidChangeBackingProperties instead, but SDL's size change
    2.16 +     * events don't always happen in the same frame (for example when a
    2.17 +     * resizable window exits a fullscreen Space via the user pressing the OS
    2.18 +     * exit-space button). */
    2.19 +    if (event->type == SDL_WINDOWEVENT && event->window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
    2.20 +        @autoreleasepool {
    2.21 +            SDL_cocoametalview *view = (__bridge SDL_cocoametalview *)userdata;
    2.22 +            if (view.sdlWindowID == event->window.windowID) {
    2.23 +                [view updateDrawableSize];
    2.24 +            }
    2.25 +        }
    2.26 +    }
    2.27 +    return 0;
    2.28 +}
    2.29  
    2.30  @implementation SDL_cocoametalview
    2.31  
    2.32 @@ -55,20 +77,30 @@
    2.33  
    2.34  - (instancetype)initWithFrame:(NSRect)frame
    2.35                        highDPI:(BOOL)highDPI
    2.36 +                     windowID:(Uint32)windowID;
    2.37  {
    2.38      if ((self = [super initWithFrame:frame])) {
    2.39          self.highDPI = highDPI;
    2.40 +        self.sdlWindowID = windowID;
    2.41          self.wantsLayer = YES;
    2.42  
    2.43          /* Allow resize. */
    2.44          self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
    2.45  
    2.46 +        SDL_AddEventWatch(SDL_MetalViewEventWatch, self);
    2.47 +
    2.48          [self updateDrawableSize];
    2.49      }
    2.50    
    2.51      return self;
    2.52  }
    2.53  
    2.54 +- (void)dealloc
    2.55 +{
    2.56 +    SDL_DelEventWatch(SDL_MetalViewEventWatch, self);
    2.57 +    [super dealloc];
    2.58 +}
    2.59 +
    2.60  - (NSInteger)tag
    2.61  {
    2.62      return METALVIEW_TAG;
    2.63 @@ -91,13 +123,6 @@
    2.64      metalLayer.drawableSize = NSSizeToCGSize(backingSize);
    2.65  }
    2.66  
    2.67 -/* Set the size of the metal drawables when the view is resized. */
    2.68 -- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
    2.69 -{
    2.70 -    [super resizeWithOldSuperviewSize:oldSize];
    2.71 -    [self updateDrawableSize];
    2.72 -}
    2.73 -
    2.74  @end
    2.75  
    2.76  SDL_MetalView
    2.77 @@ -106,10 +131,13 @@
    2.78      SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
    2.79      NSView *view = data->nswindow.contentView;
    2.80      BOOL highDPI = (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) != 0;
    2.81 +    Uint32 windowID = SDL_GetWindowID(window);
    2.82      SDL_cocoametalview *newview;
    2.83      SDL_MetalView metalview;
    2.84  
    2.85 -    newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame highDPI:highDPI];
    2.86 +    newview = [[SDL_cocoametalview alloc] initWithFrame:view.frame
    2.87 +                                                highDPI:highDPI
    2.88 +                                                windowID:windowID];
    2.89      if (newview == nil) {
    2.90          return NULL;
    2.91      }