src/video/cocoa/SDL_cocoametalview.m
author Ryan C. Gordon <icculus@icculus.org>
Sun, 27 May 2018 20:30:03 -0400
changeset 12002 9116d02d3feb
parent 11886 27d81cb6e6af
child 12201 8bdc4d340419
permissions -rw-r--r--
metal: contrary to documentation, we need to set the drawableSize explicitly.

Fixes Bugzilla #4149.
icculus@11365
     1
/*
slouken@11816
     2
  Simple DirectMedia Layer
slouken@11816
     3
  Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
icculus@11365
     4
slouken@11816
     5
  This software is provided 'as-is', without any express or implied
slouken@11816
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@11816
     7
  arising from the use of this software.
slouken@11816
     8
slouken@11816
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@11816
    10
  including commercial applications, and to alter it and redistribute it
slouken@11816
    11
  freely, subject to the following restrictions:
slouken@11816
    12
slouken@11816
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@11816
    14
     claim that you wrote the original software. If you use this software
slouken@11816
    15
     in a product, an acknowledgment in the product documentation would be
slouken@11816
    16
     appreciated but is not required.
slouken@11816
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@11816
    18
     misrepresented as being the original software.
slouken@11816
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@11816
    20
*/
icculus@11365
    21
/*
icculus@11365
    22
 * @author Mark Callow, www.edgewise-consulting.com.
icculus@11365
    23
 *
icculus@11365
    24
 * Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
icculus@11365
    25
 * how to add a CAMetalLayer backed view.
icculus@11365
    26
 */
icculus@11365
    27
icculus@11365
    28
#import "SDL_cocoametalview.h"
icculus@11365
    29
slime73@11797
    30
#if SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL)
slouken@11407
    31
icculus@11365
    32
#include "SDL_assert.h"
icculus@11365
    33
icculus@11365
    34
@implementation SDL_cocoametalview
icculus@11365
    35
icculus@11365
    36
/* The synthesized getter should be called by super's viewWithTag. */
icculus@11365
    37
@synthesize tag = _tag;
icculus@11365
    38
icculus@11365
    39
/* Return a Metal-compatible layer. */
icculus@11365
    40
+ (Class)layerClass
icculus@11365
    41
{
slime73@11435
    42
	return NSClassFromString(@"CAMetalLayer");
icculus@11365
    43
}
icculus@11365
    44
icculus@11365
    45
/* Indicate the view wants to draw using a backing layer instead of drawRect. */
slime73@11797
    46
- (BOOL)wantsUpdateLayer
slime73@11435
    47
{
slime73@11435
    48
    return YES;
slime73@11435
    49
}
icculus@11365
    50
icculus@11365
    51
/* When the wantsLayer property is set to YES, this method will be invoked to
icculus@11365
    52
 * return a layer instance.
icculus@11365
    53
 */
slime73@11797
    54
- (CALayer*)makeBackingLayer
slime73@11435
    55
{
slime73@11435
    56
    return [self.class.layerClass layer];
slime73@11435
    57
}
icculus@11365
    58
icculus@11365
    59
- (instancetype)initWithFrame:(NSRect)frame
libsdl@11886
    60
                        scale:(CGFloat)scale
icculus@11365
    61
{
slime73@11435
    62
	if ((self = [super initWithFrame:frame])) {
libsdl@11886
    63
        _tag = METALVIEW_TAG;
slime73@11809
    64
        self.wantsLayer = YES;
slime73@11809
    65
slime73@11435
    66
        /* Allow resize. */
slime73@11435
    67
        self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
slime73@11809
    68
icculus@12002
    69
        /* Set the desired scale. */
icculus@12002
    70
        ((CAMetalLayer *) self.layer).drawableSize = NSSizeToCGSize([self bounds].size);
libsdl@11886
    71
        self.layer.contentsScale = scale;
icculus@12002
    72
    }
icculus@11365
    73
  
slime73@11435
    74
	return self;
icculus@11365
    75
}
icculus@11365
    76
icculus@11365
    77
/* Set the size of the metal drawables when the view is resized. */
slime73@11797
    78
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize
slime73@11797
    79
{
slime73@11797
    80
    [super resizeWithOldSuperviewSize:oldSize];
icculus@11365
    81
}
icculus@11365
    82
icculus@11365
    83
@end
icculus@11365
    84
icculus@11365
    85
SDL_cocoametalview*
icculus@11365
    86
Cocoa_Mtl_AddMetalView(SDL_Window* window)
icculus@11365
    87
{
libsdl@11886
    88
    SDL_WindowData* data = (__bridge SDL_WindowData *)window->driverdata;
icculus@11365
    89
    NSView *view = data->nswindow.contentView;
libsdl@11886
    90
    CGFloat scale = 1.0;
icculus@11365
    91
libsdl@11886
    92
    if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
libsdl@11886
    93
        /* Set the scale to the natural scale factor of the screen - then
libsdl@11886
    94
         * the backing dimensions of the Metal view will match the pixel
libsdl@11886
    95
         * dimensions of the screen rather than the dimensions in points
libsdl@11886
    96
         * yielding high resolution on retine displays.
libsdl@11886
    97
         *
libsdl@11886
    98
         * N.B. In order for backingScaleFactor to be > 1,
libsdl@11886
    99
         * NSHighResolutionCapable must be set to true in the app's Info.plist.
libsdl@11886
   100
         */
libsdl@11886
   101
        NSWindow* nswindow = data->nswindow;
libsdl@11886
   102
        if ([nswindow.screen respondsToSelector:@selector(backingScaleFactor)])
libsdl@11886
   103
            scale = data->nswindow.screen.backingScaleFactor;
libsdl@11886
   104
    }
libsdl@11886
   105
        
icculus@11365
   106
    SDL_cocoametalview *metalview
libsdl@11886
   107
        = [[SDL_cocoametalview alloc] initWithFrame:view.frame scale:scale];
icculus@11365
   108
    [view addSubview:metalview];
icculus@11365
   109
    return metalview;
icculus@11365
   110
}
icculus@11365
   111
icculus@11365
   112
void
icculus@11365
   113
Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
icculus@11365
   114
{
icculus@11365
   115
    SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
icculus@11365
   116
    NSView *view = data->nswindow.contentView;
icculus@11365
   117
    SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
icculus@11365
   118
    if (metalview) {
icculus@11365
   119
        CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
icculus@11365
   120
        assert(layer != NULL);
slime73@11435
   121
        if (w) {
icculus@11365
   122
            *w = layer.drawableSize.width;
slime73@11435
   123
        }
slime73@11435
   124
        if (h) {
icculus@11365
   125
            *h = layer.drawableSize.height;
slime73@11435
   126
        }
libsdl@11886
   127
    } else {
libsdl@11886
   128
        SDL_GetWindowSize(window, w, h);
icculus@11365
   129
    }
icculus@11365
   130
}
icculus@11365
   131
slime73@11797
   132
#endif /* SDL_VIDEO_DRIVER_COCOA && (SDL_VIDEO_VULKAN || SDL_VIDEO_RENDER_METAL) */
slouken@11407
   133
icculus@11365
   134
/* vi: set ts=4 sw=4 expandtab: */