src/video/uikit/SDL_uikitvideo.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 31 Oct 2011 05:56:58 -0400
changeset 6044 35448a5ea044
parent 6019 3d8b1ada8ad5
child 6062 2e4a1b92dc6f
permissions -rw-r--r--
Lots of fixes importing SDL source wholesale into a new iOS project
slouken@2765
     1
/*
slouken@5535
     2
  Simple DirectMedia Layer
slouken@5535
     3
  Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
slouken@2765
     4
slouken@5535
     5
  This software is provided 'as-is', without any express or implied
slouken@5535
     6
  warranty.  In no event will the authors be held liable for any damages
slouken@5535
     7
  arising from the use of this software.
slouken@2765
     8
slouken@5535
     9
  Permission is granted to anyone to use this software for any purpose,
slouken@5535
    10
  including commercial applications, and to alter it and redistribute it
slouken@5535
    11
  freely, subject to the following restrictions:
slouken@2765
    12
slouken@5535
    13
  1. The origin of this software must not be misrepresented; you must not
slouken@5535
    14
     claim that you wrote the original software. If you use this software
slouken@5535
    15
     in a product, an acknowledgment in the product documentation would be
slouken@5535
    16
     appreciated but is not required.
slouken@5535
    17
  2. Altered source versions must be plainly marked as such, and must not be
slouken@5535
    18
     misrepresented as being the original software.
slouken@5535
    19
  3. This notice may not be removed or altered from any source distribution.
slouken@2765
    20
*/
slouken@6044
    21
#include "SDL_config.h"
slouken@6044
    22
slouken@6044
    23
#if SDL_VIDEO_DRIVER_UIKIT
icculus@4443
    24
icculus@4443
    25
#import <UIKit/UIKit.h>
icculus@4443
    26
slouken@2765
    27
#include "SDL_video.h"
slouken@2765
    28
#include "SDL_mouse.h"
slouken@2765
    29
#include "../SDL_sysvideo.h"
slouken@2765
    30
#include "../SDL_pixels_c.h"
slouken@2765
    31
#include "../../events/SDL_events_c.h"
slouken@2765
    32
slouken@2765
    33
#include "SDL_uikitvideo.h"
slouken@2765
    34
#include "SDL_uikitevents.h"
slouken@2765
    35
#include "SDL_uikitwindow.h"
slouken@2765
    36
#include "SDL_uikitopengles.h"
slouken@2765
    37
icculus@4443
    38
#include "SDL_assert.h"
icculus@4443
    39
slouken@2765
    40
#define UIKITVID_DRIVER_NAME "uikit"
slouken@2765
    41
slouken@2765
    42
/* Initialization/Query functions */
slouken@2765
    43
static int UIKit_VideoInit(_THIS);
icculus@4443
    44
static void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display);
slouken@3643
    45
static int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display,
slouken@3643
    46
                                SDL_DisplayMode * mode);
slouken@2765
    47
static void UIKit_VideoQuit(_THIS);
slouken@2765
    48
icculus@4446
    49
BOOL SDL_UIKit_supports_multiple_displays = NO;
icculus@4443
    50
slouken@2765
    51
/* DUMMY driver bootstrap functions */
slouken@2765
    52
slouken@2765
    53
static int
slouken@2765
    54
UIKit_Available(void)
slouken@2765
    55
{
kees@6003
    56
    return 1;
slouken@2765
    57
}
slouken@2765
    58
slouken@2765
    59
static void UIKit_DeleteDevice(SDL_VideoDevice * device)
slouken@2765
    60
{
slouken@2765
    61
    SDL_free(device);
slouken@2765
    62
}
slouken@2765
    63
slouken@2765
    64
static SDL_VideoDevice *
slouken@2765
    65
UIKit_CreateDevice(int devindex)
slouken@2765
    66
{
slouken@2765
    67
    SDL_VideoDevice *device;
slouken@2765
    68
slouken@2765
    69
    /* Initialize all variables that we clean on shutdown */
slouken@2765
    70
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
slouken@2765
    71
    if (!device) {
slouken@2765
    72
        SDL_OutOfMemory();
slouken@2765
    73
        if (device) {
slouken@2765
    74
            SDL_free(device);
slouken@2765
    75
        }
slouken@2765
    76
        return (0);
slouken@2765
    77
    }
slouken@2765
    78
slouken@2765
    79
    /* Set the function pointers */
slouken@2765
    80
    device->VideoInit = UIKit_VideoInit;
slouken@2765
    81
    device->VideoQuit = UIKit_VideoQuit;
icculus@4443
    82
    device->GetDisplayModes = UIKit_GetDisplayModes;
slouken@2765
    83
    device->SetDisplayMode = UIKit_SetDisplayMode;
slouken@2765
    84
    device->PumpEvents = UIKit_PumpEvents;
slouken@5131
    85
    device->CreateWindow = UIKit_CreateWindow;
slouken@5131
    86
    device->DestroyWindow = UIKit_DestroyWindow;
slouken@5056
    87
    device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
kees@6001
    88
kees@6001
    89
slouken@5131
    90
    /* OpenGL (ES) functions */
slouken@5131
    91
    device->GL_MakeCurrent        = UIKit_GL_MakeCurrent;
slouken@5131
    92
    device->GL_SwapWindow        = UIKit_GL_SwapWindow;
slouken@5131
    93
    device->GL_CreateContext    = UIKit_GL_CreateContext;
slouken@5131
    94
    device->GL_DeleteContext    = UIKit_GL_DeleteContext;
slouken@5131
    95
    device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
slouken@5131
    96
    device->GL_LoadLibrary        = UIKit_GL_LoadLibrary;
slouken@5131
    97
    device->free = UIKit_DeleteDevice;
slouken@2765
    98
slouken@5131
    99
    device->gl_config.accelerated = 1;
slouken@5131
   100
slouken@2765
   101
    return device;
slouken@2765
   102
}
slouken@2765
   103
slouken@2765
   104
VideoBootStrap UIKIT_bootstrap = {
slouken@2765
   105
    UIKITVID_DRIVER_NAME, "SDL UIKit video driver",
slouken@2765
   106
    UIKit_Available, UIKit_CreateDevice
slouken@2765
   107
};
slouken@2765
   108
slouken@2765
   109
icculus@4443
   110
/*
icculus@4443
   111
!!! FIXME:
icculus@4443
   112
icculus@4443
   113
The main screen should list a AxB mode for portrait orientation, and then
icculus@4443
   114
 also list BxA for landscape mode. When setting a given resolution, we should
icculus@4443
   115
 rotate the view's transform appropriately (extra credit if you check the
icculus@4443
   116
 accelerometer and rotate the display so it's never upside down).
icculus@4443
   117
icculus@4443
   118
  http://iphonedevelopment.blogspot.com/2008/10/starting-in-landscape-mode-without.html
icculus@4443
   119
icculus@4443
   120
*/
icculus@4443
   121
icculus@4443
   122
static void
icculus@4443
   123
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
icculus@4443
   124
{
icculus@4446
   125
    UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4443
   126
    SDL_DisplayMode mode;
icculus@4443
   127
    SDL_zero(mode);
icculus@4443
   128
icculus@4443
   129
    // availableModes showed up in 3.2 (the iPad and later). We should only
icculus@4443
   130
    //  land here for at least that version of the OS.
icculus@4446
   131
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4446
   132
        const CGRect rect = [uiscreen bounds];
icculus@4443
   133
        mode.format = SDL_PIXELFORMAT_ABGR8888;
kees@6009
   134
        mode.refresh_rate = 0;
kees@6009
   135
        mode.driverdata = NULL;
kees@6009
   136
icculus@4443
   137
        mode.w = (int) rect.size.width;
icculus@4443
   138
        mode.h = (int) rect.size.height;
icculus@4443
   139
        SDL_AddDisplayMode(display, &mode);
kees@6009
   140
icculus@5518
   141
        mode.w = (int) rect.size.height;  // swap the orientation, add again.
icculus@5518
   142
        mode.h = (int) rect.size.width;
icculus@5518
   143
        SDL_AddDisplayMode(display, &mode);
icculus@4443
   144
        return;
icculus@4443
   145
    }
icculus@4443
   146
kees@6007
   147
    for (UIScreenMode *uimode in [uiscreen availableModes]) {
icculus@5518
   148
        CGSize size = [uimode size];
icculus@4443
   149
        mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@5518
   150
        mode.refresh_rate = 0;
icculus@5518
   151
        mode.driverdata = uimode;
icculus@4443
   152
        mode.w = (int) size.width;
icculus@4443
   153
        mode.h = (int) size.height;
icculus@5518
   154
        if (SDL_AddDisplayMode(display, &mode))
kees@6009
   155
            [uimode retain];        // retain is needed because of mode.driverdata
icculus@5518
   156
kees@6009
   157
        if (uiscreen == [UIScreen mainScreen]) {
kees@6009
   158
            // Add the mode with swapped width/height
kees@6009
   159
            mode.w = (int) size.height;
kees@6009
   160
            mode.h = (int) size.width;
icculus@5518
   161
            if (SDL_AddDisplayMode(display, &mode))
icculus@5518
   162
                [uimode retain];
icculus@5518
   163
        }
icculus@4443
   164
    }
icculus@4443
   165
}
icculus@4443
   166
icculus@4443
   167
icculus@4443
   168
static void
kees@6018
   169
UIKit_AddDisplay(UIScreen *uiscreen, int w, int h)
icculus@4443
   170
{
icculus@4443
   171
    SDL_VideoDisplay display;
icculus@4443
   172
    SDL_DisplayMode mode;
icculus@4443
   173
    SDL_zero(mode);
icculus@4443
   174
    mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@4443
   175
    mode.w = w;
icculus@4443
   176
    mode.h = h;
icculus@4443
   177
    mode.refresh_rate = 0;
kees@6001
   178
kees@6018
   179
    // UIScreenMode showed up in 3.2 (the iPad and later). We're
kees@6018
   180
    //  misusing this supports_multiple_displays flag here for that.
kees@6018
   181
    if (!SDL_UIKit_supports_multiple_displays) {
kees@6018
   182
        UIScreenMode *uimode = [uiscreen currentMode];
kees@6018
   183
        [uimode retain];  // once for the desktop_mode
kees@6018
   184
        [uimode retain];  // once for the current_mode
kees@6018
   185
        mode.driverdata = uimode;
kees@6018
   186
    }
icculus@4443
   187
icculus@4443
   188
    SDL_zero(display);
icculus@4443
   189
    display.desktop_mode = mode;
icculus@4443
   190
    display.current_mode = mode;
icculus@4446
   191
icculus@4446
   192
    [uiscreen retain];
icculus@4446
   193
    display.driverdata = uiscreen;
icculus@4443
   194
    SDL_AddVideoDisplay(&display);
icculus@4443
   195
}
icculus@4443
   196
icculus@4443
   197
slouken@2765
   198
int
slouken@2765
   199
UIKit_VideoInit(_THIS)
slouken@2765
   200
{
icculus@4443
   201
    _this->gl_config.driver_loaded = 1;
slouken@2765
   202
icculus@4445
   203
    NSString *reqSysVer = @"3.2";
icculus@4445
   204
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
icculus@4445
   205
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
icculus@4446
   206
        SDL_UIKit_supports_multiple_displays = YES;
slouken@2765
   207
kees@6013
   208
    // Add the main screen.
kees@6013
   209
    UIScreen *uiscreen = [UIScreen mainScreen];
kees@6013
   210
    const CGSize size = [uiscreen bounds].size;
kees@6018
   211
    UIKit_AddDisplay(uiscreen, (int)size.width, (int)size.height);
kees@6013
   212
icculus@4443
   213
    // If this is iPhoneOS < 3.2, all devices are one screen, 320x480 pixels.
icculus@4443
   214
    //  The iPad added both a larger main screen and the ability to use
kees@6013
   215
    //  external displays. So, add the other displays (screens in UI speak).
kees@6013
   216
    if (SDL_UIKit_supports_multiple_displays) {
kees@6007
   217
        for (UIScreen *uiscreen in [UIScreen screens]) {
kees@6013
   218
            // Only add the other screens
kees@6013
   219
            if (uiscreen != [UIScreen mainScreen]) {
kees@6013
   220
                const CGSize size = [uiscreen bounds].size;
kees@6018
   221
                UIKit_AddDisplay(uiscreen, (int)size.width, (int)size.height);
kees@6013
   222
            }
icculus@4443
   223
        }
icculus@4443
   224
    }
slouken@2765
   225
slouken@2765
   226
    /* We're done! */
slouken@2765
   227
    return 0;
slouken@2765
   228
}
slouken@2765
   229
slouken@2765
   230
static int
slouken@3643
   231
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
slouken@2765
   232
{
icculus@4446
   233
    UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4446
   234
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4443
   235
        // Not on at least iPhoneOS 3.2 (versions prior to iPad).
icculus@4443
   236
        SDL_assert(mode->driverdata == NULL);
icculus@4443
   237
    } else {
icculus@4443
   238
        UIScreenMode *uimode = (UIScreenMode *) mode->driverdata;
icculus@4446
   239
        [uiscreen setCurrentMode:uimode];
icculus@4443
   240
    }
icculus@4443
   241
slouken@2765
   242
    return 0;
slouken@2765
   243
}
slouken@2765
   244
kees@6019
   245
static void
kees@6019
   246
UIKit_ReleaseUIScreenMode(SDL_DisplayMode * mode)
kees@6019
   247
{
kees@6019
   248
    if (!SDL_UIKit_supports_multiple_displays) {
kees@6019
   249
        // Not on at least iPhoneOS 3.2 (versions prior to iPad).
kees@6019
   250
        SDL_assert(mode->driverdata == NULL);
kees@6019
   251
    } else {
kees@6019
   252
        UIScreenMode *uimode = (UIScreenMode *) mode->driverdata;
kees@6019
   253
        [uimode release];
kees@6019
   254
        mode->driverdata = NULL;
kees@6019
   255
    }
kees@6019
   256
}
kees@6019
   257
slouken@2765
   258
void
slouken@2765
   259
UIKit_VideoQuit(_THIS)
slouken@2765
   260
{
icculus@4443
   261
    // Release Objective-C objects, so higher level doesn't free() them.
icculus@4443
   262
    int i, j;
icculus@4443
   263
    for (i = 0; i < _this->num_displays; i++) {
icculus@4443
   264
        SDL_VideoDisplay *display = &_this->displays[i];
icculus@4446
   265
        UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4446
   266
        [uiscreen release];
icculus@4443
   267
        display->driverdata = NULL;
kees@6019
   268
        UIKit_ReleaseUIScreenMode(&display->desktop_mode);
kees@6019
   269
        UIKit_ReleaseUIScreenMode(&display->current_mode);
icculus@4443
   270
        for (j = 0; j < display->num_display_modes; j++) {
icculus@4443
   271
            SDL_DisplayMode *mode = &display->display_modes[j];
kees@6019
   272
            UIKit_ReleaseUIScreenMode(mode);
icculus@4443
   273
        }
icculus@4443
   274
    }
slouken@2765
   275
}
slouken@2765
   276
slouken@6044
   277
#endif /* SDL_VIDEO_DRIVER_UIKIT */
slouken@6044
   278
slouken@2765
   279
/* vi: set ts=4 sw=4 expandtab: */