SDL_uikitmodes.m
Go to the documentation of this file.
/*
Simple DirectMedia Layer
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_UIKIT
#include "SDL_assert.h"
#include "SDL_uikitmodes.h"
@implementation SDL_DisplayData
@synthesize uiscreen;
@end
@implementation SDL_DisplayModeData
@synthesize uiscreenmode;
@end
static int
UIKit_AllocateDisplayModeData(SDL_DisplayMode * mode,
UIScreenMode * uiscreenmode)
{
SDL_DisplayModeData *data = nil;
if (uiscreenmode != nil) {
/* Allocate the display mode data */
data = [[SDL_DisplayModeData alloc] init];
if (!data) {
return SDL_OutOfMemory();
}
data.uiscreenmode = uiscreenmode;
}
mode->driverdata = (void *) CFBridgingRetain(data);
return 0;
}
static void
UIKit_FreeDisplayModeData(SDL_DisplayMode * mode)
{
if (mode->driverdata != NULL) {
CFRelease(mode->driverdata);
mode->driverdata = NULL;
}
}
static NSUInteger
UIKit_GetDisplayModeRefreshRate(UIScreen *uiscreen)
{
#ifdef __IPHONE_10_3
if ([uiscreen respondsToSelector:@selector(maximumFramesPerSecond)]) {
return uiscreen.maximumFramesPerSecond;
}
#endif
return 0;
}
static int
UIKit_AddSingleDisplayMode(SDL_VideoDisplay * display, int w, int h,
UIScreen * uiscreen, UIScreenMode * uiscreenmode)
{
SDL_DisplayMode mode;
SDL_zero(mode);
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
return -1;
}
mode.format = SDL_PIXELFORMAT_ABGR8888;
mode.refresh_rate = (int) UIKit_GetDisplayModeRefreshRate(uiscreen);
mode.w = w;
mode.h = h;
if (SDL_AddDisplayMode(display, &mode)) {
return 0;
} else {
UIKit_FreeDisplayModeData(&mode);
return -1;
}
}
static int
UIKit_AddDisplayMode(SDL_VideoDisplay * display, int w, int h, UIScreen * uiscreen,
UIScreenMode * uiscreenmode, SDL_bool addRotation)
{
if (UIKit_AddSingleDisplayMode(display, w, h, uiscreen, uiscreenmode) < 0) {
return -1;
}
if (addRotation) {
/* Add the rotated version */
if (UIKit_AddSingleDisplayMode(display, h, w, uiscreen, uiscreenmode) < 0) {
return -1;
}
}
return 0;
}
static int
UIKit_AddDisplay(UIScreen *uiscreen)
{
UIScreenMode *uiscreenmode = uiscreen.currentMode;
CGSize size = uiscreen.bounds.size;
SDL_VideoDisplay display;
SDL_DisplayMode mode;
SDL_zero(mode);
/* Make sure the width/height are oriented correctly */
if (UIKit_IsDisplayLandscape(uiscreen) != (size.width > size.height)) {
CGFloat height = size.width;
size.width = size.height;
size.height = height;
}
mode.format = SDL_PIXELFORMAT_ABGR8888;
mode.refresh_rate = (int) UIKit_GetDisplayModeRefreshRate(uiscreen);
mode.w = (int) size.width;
mode.h = (int) size.height;
if (UIKit_AllocateDisplayModeData(&mode, uiscreenmode) < 0) {
return -1;
}
SDL_zero(display);
display.desktop_mode = mode;
display.current_mode = mode;
/* Allocate the display data */
SDL_DisplayData *data = [[SDL_DisplayData alloc] init];
if (!data) {
UIKit_FreeDisplayModeData(&display.desktop_mode);
return SDL_OutOfMemory();
}
data.uiscreen = uiscreen;
display.driverdata = (void *) CFBridgingRetain(data);
SDL_AddVideoDisplay(&display);
return 0;
}
SDL_bool
UIKit_IsDisplayLandscape(UIScreen *uiscreen)
{
#if !TARGET_OS_TV
if (uiscreen == [UIScreen mainScreen]) {
return UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation);
} else
#endif /* !TARGET_OS_TV */
{
CGSize size = uiscreen.bounds.size;
return (size.width > size.height);
}
}
int
UIKit_InitModes(_THIS)
{
@autoreleasepool {
for (UIScreen *uiscreen in [UIScreen screens]) {
if (UIKit_AddDisplay(uiscreen) < 0) {
return -1;
}
}
}
return 0;
}
void
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
{
@autoreleasepool {
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
SDL_bool isLandscape = UIKit_IsDisplayLandscape(data.uiscreen);
SDL_bool addRotation = (data.uiscreen == [UIScreen mainScreen]);
CGFloat scale = data.uiscreen.scale;
NSArray *availableModes = nil;
#if TARGET_OS_TV
addRotation = SDL_FALSE;
availableModes = @[data.uiscreen.currentMode];
#else
availableModes = data.uiscreen.availableModes;
#endif
#ifdef __IPHONE_8_0
/* The UIScreenMode of an iPhone 6 Plus should be 1080x1920 rather than
* 1242x2208 (414x736@3x), so we should use the native scale. */
if ([data.uiscreen respondsToSelector:@selector(nativeScale)]) {
scale = data.uiscreen.nativeScale;
}
#endif
for (UIScreenMode *uimode in availableModes) {
/* The size of a UIScreenMode is in pixels, but we deal exclusively
* in points (except in SDL_GL_GetDrawableSize.) */
int w = (int)(uimode.size.width / scale);
int h = (int)(uimode.size.height / scale);
/* Make sure the width/height are oriented correctly */
if (isLandscape != (w > h)) {
int tmp = w;
w = h;
h = tmp;
}
UIKit_AddDisplayMode(display, w, h, data.uiscreen, uimode, addRotation);
}
}
}
int
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
@autoreleasepool {
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
#if !TARGET_OS_TV
SDL_DisplayModeData *modedata = (__bridge SDL_DisplayModeData *)mode->driverdata;
[data.uiscreen setCurrentMode:modedata.uiscreenmode];
#endif
if (data.uiscreen == [UIScreen mainScreen]) {
/* [UIApplication setStatusBarOrientation:] no longer works reliably
* in recent iOS versions, so we can't rotate the screen when setting
* the display mode. */
if (mode->w > mode->h) {
if (!UIKit_IsDisplayLandscape(data.uiscreen)) {
return SDL_SetError("Screen orientation does not match display mode size");
}
} else if (mode->w < mode->h) {
if (UIKit_IsDisplayLandscape(data.uiscreen)) {
return SDL_SetError("Screen orientation does not match display mode size");
}
}
}
}
return 0;
}
int
UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay * display, SDL_Rect * rect)
{
@autoreleasepool {
int displayIndex = (int) (display - _this->displays);
SDL_DisplayData *data = (__bridge SDL_DisplayData *) display->driverdata;
CGRect frame = data.uiscreen.bounds;
/* the default function iterates displays to make a fake offset,
as if all the displays were side-by-side, which is fine for iOS. */
if (SDL_GetDisplayBounds(displayIndex, rect) < 0) {
return -1;
}
#if !TARGET_OS_TV && __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_7_0
if (!UIKit_IsSystemVersionAtLeast(7.0)) {
frame = [data.uiscreen applicationFrame];
}
#endif
rect->x += frame.origin.x;
rect->y += frame.origin.y;
rect->w = frame.size.width;
rect->h = frame.size.height;
}
return 0;
}
void
UIKit_QuitModes(_THIS)
{
/* Release Objective-C objects, so higher level doesn't free() them. */
int i, j;
@autoreleasepool {
for (i = 0; i < _this->num_displays; i++) {
SDL_VideoDisplay *display = &_this->displays[i];
UIKit_FreeDisplayModeData(&display->desktop_mode);
for (j = 0; j < display->num_display_modes; j++) {
SDL_DisplayMode *mode = &display->display_modes[j];
UIKit_FreeDisplayModeData(mode);
}
if (display->driverdata != NULL) {
CFRelease(display->driverdata);
display->driverdata = NULL;
}
}
}
}
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */
UIKit_InitModes
int UIKit_InitModes(_THIS)
scale
GLenum GLenum GLenum GLenum GLenum scale
Definition: SDL_opengl_glext.h:9375
UIKit_IsSystemVersionAtLeast
SDL_bool UIKit_IsSystemVersionAtLeast(double version)
UIKit_QuitModes
void UIKit_QuitModes(_THIS)
x
GLint GLint GLint GLint GLint x
Definition: SDL_opengl.h:1574
SDL_DisplayMode::w
int w
Definition: SDL_video.h:56
UIKit_IsDisplayLandscape
SDL_bool UIKit_IsDisplayLandscape(UIScreen *uiscreen)
rect
SDL_Rect rect
Definition: testrelative.c:27
SDL_FALSE
Definition: SDL_stdinc.h:141
h
GLfloat GLfloat GLfloat GLfloat h
Definition: SDL_opengl_glext.h:1946
SDL_DisplayMode
The structure that defines a display mode.
Definition: SDL_video.h:53
SDL_DisplayMode::refresh_rate
int refresh_rate
Definition: SDL_video.h:58
data
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: SDL_opengl.h:1974
UIKit_GetDisplayModes
void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
SDL_AddVideoDisplay
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display)
Definition: SDL_video.c:606
SDL_DisplayData
Definition: SDL_cocoamodes.h:26
_this
static SDL_VideoDevice * _this
Definition: SDL_video.c:121
SDL_DisplayData::uiscreen
UIScreen * uiscreen
Definition: SDL_uikitmodes.h:30
SDL_VideoDisplay::num_display_modes
int num_display_modes
Definition: SDL_sysvideo.h:129
SDL_DisplayModeData
Definition: SDL_cocoamodes.h:31
SDL_PIXELFORMAT_ABGR8888
Definition: SDL_pixels.h:254
_THIS
#define _THIS
Definition: SDL_alsa_audio.h:31
frame
int frame
Definition: teststreaming.c:60
SDL_DisplayMode::driverdata
void * driverdata
Definition: SDL_video.h:59
SDL_VideoDevice::num_displays
int num_displays
Definition: SDL_sysvideo.h:311
j
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
Definition: SDL_x11sym.h:50
SDL_VideoDisplay::display_modes
SDL_DisplayMode * display_modes
Definition: SDL_sysvideo.h:130
SDL_VideoDisplay::current_mode
SDL_DisplayMode current_mode
Definition: SDL_sysvideo.h:132
mode
GLenum mode
Definition: SDL_opengl_glext.h:1122
w
GLubyte GLubyte GLubyte GLubyte w
Definition: SDL_opengl_glext.h:731
SDL_VideoDevice::displays
SDL_VideoDisplay * displays
Definition: SDL_sysvideo.h:312
SDL_GetDisplayBounds
#define SDL_GetDisplayBounds
Definition: SDL_dynapi_overrides.h:503
SDL_zero
#define SDL_zero(x)
Definition: SDL_stdinc.h:416
SDL_DisplayMode::h
int h
Definition: SDL_video.h:57
y
GLint GLint GLint GLint GLint GLint y
Definition: SDL_opengl.h:1574
SDL_Rect::x
int x
Definition: SDL_rect.h:66
SDL_Rect::w
int w
Definition: SDL_rect.h:67
size
GLsizeiptr size
Definition: SDL_opengl_glext.h:537
SDL_VideoDisplay
Definition: SDL_sysvideo.h:125
i
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
Definition: SDL_x11sym.h:50
UIKit_GetDisplayUsableBounds
int UIKit_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
NULL
#define NULL
Definition: begin_code.h:164
SDL_OutOfMemory
#define SDL_OutOfMemory()
Definition: SDL_error.h:52
SDL_bool
SDL_bool
Definition: SDL_stdinc.h:139
SDL_VideoDisplay::desktop_mode
SDL_DisplayMode desktop_mode
Definition: SDL_sysvideo.h:131
SDL_SetError
#define SDL_SetError
Definition: SDL_dynapi_overrides.h:30
height
GLint GLint GLsizei GLsizei height
Definition: SDL_opengl.h:1572
SDL_DisplayModeData::uiscreenmode
UIScreenMode * uiscreenmode
Definition: SDL_uikitmodes.h:36
SDL_Rect::h
int h
Definition: SDL_rect.h:67
SDL_AddDisplayMode
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
Definition: SDL_video.c:743
SDL_DisplayMode::format
Uint32 format
Definition: SDL_video.h:55
SDL_uikitmodes.h
in
GLuint in
Definition: SDL_opengl_glext.h:7940
SDL_Rect::y
int y
Definition: SDL_rect.h:66
SDL_Rect
A rectangle, with the origin at the upper left.
Definition: SDL_rect.h:64
SDL_VideoDisplay::driverdata
void * driverdata
Definition: SDL_sysvideo.h:138
SDL_assert.h
UIKit_SetDisplayMode
int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)