src/video/cocoa/SDL_cocoametalview.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 28 Aug 2017 02:30:41 -0700
changeset 11388 16b174adc603
parent 11367 e8fc755a89e8
child 11402 d459d8934897
permissions -rw-r--r--
Instantiate the CAMetalLayer so SDL_Vulkan_CreateSurface() doesn't fail
Error message was:
[mvk-info] MoltenVK version 0.18.2. Vulkan version 1.0.51.
[***MoltenVK ERROR***] VK_ERROR_INITIALIZATION_FAILED: On-screen rendering requires a view that is backed by a layer of type CAMetalLayer.
2017-08-28 02:17:29.579 testvulkan[95627:1716939] ERROR: SDL_Vulkan_CreateSurface(): vkCreateMacOSSurfaceMVK failed: VK_ERROR_INITIALIZATION_FAILED
icculus@11365
     1
/*
icculus@11365
     2
 Simple DirectMedia Layer
icculus@11365
     3
 Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
icculus@11365
     4
 
icculus@11365
     5
 This software is provided 'as-is', without any express or implied
icculus@11365
     6
 warranty.  In no event will the authors be held liable for any damages
icculus@11365
     7
 arising from the use of this software.
icculus@11365
     8
 
icculus@11365
     9
 Permission is granted to anyone to use this software for any purpose,
icculus@11365
    10
 including commercial applications, and to alter it and redistribute it
icculus@11365
    11
 freely, subject to the following restrictions:
icculus@11365
    12
 
icculus@11365
    13
 1. The origin of this software must not be misrepresented; you must not
icculus@11365
    14
 claim that you wrote the original software. If you use this software
icculus@11365
    15
 in a product, an acknowledgment in the product documentation would be
icculus@11365
    16
 appreciated but is not required.
icculus@11365
    17
 2. Altered source versions must be plainly marked as such, and must not be
icculus@11365
    18
 misrepresented as being the original software.
icculus@11365
    19
 3. This notice may not be removed or altered from any source distribution.
icculus@11365
    20
 */
icculus@11365
    21
icculus@11365
    22
/*
icculus@11365
    23
 * @author Mark Callow, www.edgewise-consulting.com.
icculus@11365
    24
 *
icculus@11365
    25
 * Thanks to Alex Szpakowski, @slime73 on GitHub, for his gist showing
icculus@11365
    26
 * how to add a CAMetalLayer backed view.
icculus@11365
    27
 */
icculus@11365
    28
icculus@11365
    29
#import "SDL_cocoametalview.h"
icculus@11365
    30
icculus@11365
    31
#include "SDL_assert.h"
icculus@11365
    32
#include "SDL_loadso.h"
icculus@11365
    33
#include <dlfcn.h>
icculus@11365
    34
icculus@11365
    35
@implementation SDL_cocoametalview
icculus@11365
    36
icculus@11365
    37
/* The synthesized getter should be called by super's viewWithTag. */
icculus@11365
    38
@synthesize tag = _tag;
icculus@11365
    39
icculus@11365
    40
/* Return a Metal-compatible layer. */
icculus@11365
    41
+ (Class)layerClass
icculus@11365
    42
{
icculus@11365
    43
  return [CAMetalLayer class];
icculus@11365
    44
}
icculus@11365
    45
icculus@11365
    46
/* Indicate the view wants to draw using a backing layer instead of drawRect. */
icculus@11365
    47
-(BOOL) wantsUpdateLayer { return YES; }
icculus@11365
    48
icculus@11365
    49
/* When the wantsLayer property is set to YES, this method will be invoked to
icculus@11365
    50
 * return a layer instance.
icculus@11365
    51
 */
icculus@11365
    52
-(CALayer*) makeBackingLayer { return [self.class.layerClass layer]; }
icculus@11365
    53
icculus@11365
    54
- (instancetype)initWithFrame:(NSRect)frame
icculus@11365
    55
                   useHighDPI:(bool)useHighDPI
icculus@11365
    56
{
icculus@11365
    57
  if ((self = [super initWithFrame:frame])) {
icculus@11365
    58
    
icculus@11365
    59
    /* Allow resize. */
icculus@11365
    60
    self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
icculus@11365
    61
    _tag = METALVIEW_TAG;
icculus@11365
    62
      
icculus@11365
    63
    _useHighDPI = useHighDPI;
icculus@11365
    64
    [self updateDrawableSize];
icculus@11365
    65
  }
icculus@11365
    66
  
icculus@11365
    67
  return self;
icculus@11365
    68
}
icculus@11365
    69
icculus@11365
    70
/* Set the size of the metal drawables when the view is resized. */
icculus@11365
    71
- (void)resizeSubviewsWithOldSize:(NSSize)oldSize {
icculus@11365
    72
    [super resizeSubviewsWithOldSize:oldSize];
icculus@11365
    73
    [self updateDrawableSize];
icculus@11365
    74
}
icculus@11365
    75
icculus@11365
    76
- (void)updateDrawableSize
icculus@11365
    77
{
icculus@11365
    78
    if (_useHighDPI) {
icculus@11365
    79
        NSSize size = [self convertRectToBacking:[self bounds]].size;
icculus@11365
    80
         /* Isn't there a better way to convert from NSSize to CGSize? */
icculus@11365
    81
        CGSize cgsize = *(CGSize*)&size;
icculus@11365
    82
        ((CAMetalLayer *) self.layer).drawableSize = cgsize;
icculus@11365
    83
    }
icculus@11365
    84
}
icculus@11365
    85
icculus@11365
    86
@end
icculus@11365
    87
icculus@11365
    88
SDL_cocoametalview*
icculus@11365
    89
Cocoa_Mtl_AddMetalView(SDL_Window* window)
icculus@11365
    90
{
icculus@11365
    91
    SDL_WindowData *data = (SDL_WindowData *)window->driverdata;
icculus@11365
    92
    NSView *view = data->nswindow.contentView;
icculus@11365
    93
icculus@11365
    94
    SDL_cocoametalview *metalview
icculus@11365
    95
        = [[SDL_cocoametalview alloc] initWithFrame:view.frame
icculus@11365
    96
                       useHighDPI:(window->flags & SDL_WINDOW_ALLOW_HIGHDPI)];
slouken@11388
    97
    // Instantiate the CAMetalLayer
slouken@11388
    98
    metalview.wantsLayer = YES;
icculus@11365
    99
    [view addSubview:metalview];
icculus@11365
   100
    return metalview;
icculus@11365
   101
}
icculus@11365
   102
icculus@11365
   103
void
icculus@11365
   104
Cocoa_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
icculus@11365
   105
{
icculus@11365
   106
    SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
icculus@11365
   107
    NSView *view = data->nswindow.contentView;
icculus@11365
   108
    SDL_cocoametalview* metalview = [view viewWithTag:METALVIEW_TAG];
icculus@11365
   109
    if (metalview) {
icculus@11365
   110
        CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
icculus@11365
   111
        assert(layer != NULL);
icculus@11365
   112
        if (w)
icculus@11365
   113
            *w = layer.drawableSize.width;
icculus@11365
   114
        if (h)
icculus@11365
   115
            *h = layer.drawableSize.height;
icculus@11365
   116
    }
icculus@11365
   117
}
icculus@11365
   118
icculus@11365
   119
/* vi: set ts=4 sw=4 expandtab: */
icculus@11365
   120