src/video/uikit/SDL_uikitmetalview.m
author Ryan C. Gordon <icculus@icculus.org>
Sun, 27 May 2018 20:30:03 -0400
changeset 12002 9116d02d3feb
parent 11918 c087b18ba812
child 12320 758d4e1222a7
permissions -rw-r--r--
metal: contrary to documentation, we need to set the drawableSize explicitly.

Fixes Bugzilla #4149.
icculus@11365
     1
/*
icculus@11365
     2
 Simple DirectMedia Layer
slouken@11811
     3
 Copyright (C) 1997-2018 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
#include "../../SDL_internal.h"
icculus@11365
    30
slouken@11733
    31
#if SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN)
icculus@11365
    32
icculus@11365
    33
#import "../SDL_sysvideo.h"
icculus@11365
    34
#import "SDL_uikitwindow.h"
icculus@11365
    35
#import "SDL_uikitmetalview.h"
icculus@11365
    36
icculus@11365
    37
#include "SDL_assert.h"
icculus@11365
    38
icculus@11365
    39
@implementation SDL_uikitmetalview
icculus@11365
    40
icculus@11365
    41
/* Returns a Metal-compatible layer. */
icculus@11365
    42
+ (Class)layerClass
icculus@11365
    43
{
icculus@11365
    44
    return [CAMetalLayer class];
icculus@11365
    45
}
icculus@11365
    46
icculus@11365
    47
- (instancetype)initWithFrame:(CGRect)frame
icculus@11365
    48
                        scale:(CGFloat)scale
icculus@11365
    49
{
icculus@11365
    50
    if ((self = [super initWithFrame:frame])) {
libsdl@11886
    51
        self.tag = METALVIEW_TAG;
icculus@12002
    52
        /* Set the desired scale. */
icculus@12002
    53
        ((CAMetalLayer *) self.layer).drawableSize = self.bounds.size;
libsdl@11886
    54
        self.layer.contentsScale = scale;
icculus@11365
    55
    }
icculus@11365
    56
icculus@11365
    57
    return self;
icculus@11365
    58
}
icculus@11365
    59
icculus@11365
    60
/* Set the size of the metal drawables when the view is resized. */
icculus@11365
    61
- (void)layoutSubviews
icculus@11365
    62
{
slouken@11918
    63
    CGSize bounds;
slouken@11918
    64
icculus@11365
    65
    [super layoutSubviews];
slouken@11918
    66
slouken@11918
    67
    bounds = [self bounds].size;
slouken@11918
    68
    bounds.width *= self.layer.contentsScale;
slouken@11918
    69
    bounds.height *= self.layer.contentsScale;
slouken@11918
    70
    ((CAMetalLayer *) self.layer).drawableSize = bounds;
icculus@11365
    71
}
icculus@11365
    72
icculus@11365
    73
@end
icculus@11365
    74
icculus@11365
    75
SDL_uikitmetalview*
icculus@11365
    76
UIKit_Mtl_AddMetalView(SDL_Window* window)
icculus@11365
    77
{
icculus@11365
    78
    SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
icculus@11365
    79
    SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view;
icculus@11365
    80
    CGFloat scale = 1.0;
slime73@11515
    81
slouken@11918
    82
    if ([view isKindOfClass:[SDL_uikitmetalview class]]) {
slouken@11918
    83
        return (SDL_uikitmetalview *)view;
slouken@11918
    84
    }
slouken@11732
    85
icculus@11365
    86
    if (window->flags & SDL_WINDOW_ALLOW_HIGHDPI) {
libsdl@11886
    87
        /* Set the scale to the natural scale factor of the screen - then
libsdl@11886
    88
         * the backing dimensions of the Metal view will match the pixel
libsdl@11886
    89
         * dimensions of the screen rather than the dimensions in points
libsdl@11886
    90
         * yielding high resolution on retine displays.
icculus@11365
    91
         */
slouken@11506
    92
#ifdef __IPHONE_8_0
icculus@11365
    93
        if ([data.uiwindow.screen respondsToSelector:@selector(nativeScale)]) {
icculus@11365
    94
            scale = data.uiwindow.screen.nativeScale;
slouken@11506
    95
        } else
slouken@11506
    96
#endif
slouken@11506
    97
        {
icculus@11365
    98
            scale = data.uiwindow.screen.scale;
icculus@11365
    99
        }
icculus@11365
   100
    }
icculus@11365
   101
    SDL_uikitmetalview *metalview
icculus@11365
   102
         = [[SDL_uikitmetalview alloc] initWithFrame:view.frame
libsdl@11886
   103
                                               scale:scale];
icculus@11365
   104
    [metalview setSDLWindow:window];
icculus@11365
   105
icculus@11365
   106
    return metalview;
icculus@11365
   107
}
icculus@11365
   108
icculus@11365
   109
void
icculus@11365
   110
UIKit_Mtl_GetDrawableSize(SDL_Window * window, int * w, int * h)
icculus@11365
   111
{
slime73@11435
   112
    @autoreleasepool {
slime73@11435
   113
        SDL_WindowData *data = (__bridge SDL_WindowData *)window->driverdata;
slime73@11435
   114
        SDL_uikitview *view = (SDL_uikitview*)data.uiwindow.rootViewController.view;
slime73@11435
   115
        SDL_uikitmetalview* metalview = [view viewWithTag:METALVIEW_TAG];
slime73@11435
   116
        if (metalview) {
slime73@11435
   117
            CAMetalLayer *layer = (CAMetalLayer*)metalview.layer;
slime73@11435
   118
            assert(layer != NULL);
slime73@11435
   119
            if (w) {
slime73@11435
   120
                *w = layer.drawableSize.width;
slime73@11435
   121
            }
slime73@11435
   122
            if (h) {
slime73@11435
   123
                *h = layer.drawableSize.height;
slime73@11435
   124
            }
slime73@11435
   125
        } else {
slime73@11435
   126
            SDL_GetWindowSize(window, w, h);
slime73@11435
   127
        }
slime73@11435
   128
    }
icculus@11365
   129
}
icculus@11365
   130
slouken@11733
   131
#endif /* SDL_VIDEO_DRIVER_UIKIT && (SDL_VIDEO_RENDER_METAL || SDL_VIDEO_VULKAN) */