src/video/uikit/SDL_uikitvideo.m
author Kees Bakker
Tue, 27 Sep 2011 22:51:26 +0200
changeset 6003 fddf81967e2d
parent 6001 3ae3d1e58d59
child 6007 0e647f56751d
permissions -rw-r--r--
Use a consistent source code format in src/video/uikit

For example:
* Opening bracket of a method/function on a new line at column 0
* space after "if", "while", etc
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
*/
icculus@4443
    21
icculus@4443
    22
#import <UIKit/UIKit.h>
icculus@4443
    23
slouken@2765
    24
#include "SDL_config.h"
slouken@2765
    25
slouken@2765
    26
#include "SDL_video.h"
slouken@2765
    27
#include "SDL_mouse.h"
slouken@2765
    28
#include "../SDL_sysvideo.h"
slouken@2765
    29
#include "../SDL_pixels_c.h"
slouken@2765
    30
#include "../../events/SDL_events_c.h"
slouken@2765
    31
slouken@2765
    32
#include "SDL_uikitvideo.h"
slouken@2765
    33
#include "SDL_uikitevents.h"
slouken@2765
    34
#include "SDL_uikitwindow.h"
slouken@2765
    35
#include "SDL_uikitopengles.h"
slouken@2765
    36
icculus@4443
    37
#include "SDL_assert.h"
icculus@4443
    38
slouken@2765
    39
#define UIKITVID_DRIVER_NAME "uikit"
slouken@2765
    40
slouken@2765
    41
/* Initialization/Query functions */
slouken@2765
    42
static int UIKit_VideoInit(_THIS);
icculus@4443
    43
static void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display);
slouken@3643
    44
static int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display,
slouken@3643
    45
                                SDL_DisplayMode * mode);
slouken@2765
    46
static void UIKit_VideoQuit(_THIS);
slouken@2765
    47
icculus@4446
    48
BOOL SDL_UIKit_supports_multiple_displays = NO;
icculus@4443
    49
slouken@2765
    50
/* DUMMY driver bootstrap functions */
slouken@2765
    51
slouken@2765
    52
static int
slouken@2765
    53
UIKit_Available(void)
slouken@2765
    54
{
kees@6003
    55
    return 1;
slouken@2765
    56
}
slouken@2765
    57
slouken@2765
    58
static void UIKit_DeleteDevice(SDL_VideoDevice * device)
slouken@2765
    59
{
slouken@2765
    60
    SDL_free(device);
slouken@2765
    61
}
slouken@2765
    62
slouken@2765
    63
static SDL_VideoDevice *
slouken@2765
    64
UIKit_CreateDevice(int devindex)
slouken@2765
    65
{
slouken@2765
    66
    SDL_VideoDevice *device;
slouken@2765
    67
slouken@2765
    68
    /* Initialize all variables that we clean on shutdown */
slouken@2765
    69
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
slouken@2765
    70
    if (!device) {
slouken@2765
    71
        SDL_OutOfMemory();
slouken@2765
    72
        if (device) {
slouken@2765
    73
            SDL_free(device);
slouken@2765
    74
        }
slouken@2765
    75
        return (0);
slouken@2765
    76
    }
slouken@2765
    77
slouken@2765
    78
    /* Set the function pointers */
slouken@2765
    79
    device->VideoInit = UIKit_VideoInit;
slouken@2765
    80
    device->VideoQuit = UIKit_VideoQuit;
icculus@4443
    81
    device->GetDisplayModes = UIKit_GetDisplayModes;
slouken@2765
    82
    device->SetDisplayMode = UIKit_SetDisplayMode;
slouken@2765
    83
    device->PumpEvents = UIKit_PumpEvents;
slouken@5131
    84
    device->CreateWindow = UIKit_CreateWindow;
slouken@5131
    85
    device->DestroyWindow = UIKit_DestroyWindow;
slouken@5056
    86
    device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
kees@6001
    87
kees@6001
    88
slouken@5131
    89
    /* OpenGL (ES) functions */
slouken@5131
    90
    device->GL_MakeCurrent        = UIKit_GL_MakeCurrent;
slouken@5131
    91
    device->GL_SwapWindow        = UIKit_GL_SwapWindow;
slouken@5131
    92
    device->GL_CreateContext    = UIKit_GL_CreateContext;
slouken@5131
    93
    device->GL_DeleteContext    = UIKit_GL_DeleteContext;
slouken@5131
    94
    device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
slouken@5131
    95
    device->GL_LoadLibrary        = UIKit_GL_LoadLibrary;
slouken@5131
    96
    device->free = UIKit_DeleteDevice;
slouken@2765
    97
slouken@5131
    98
    device->gl_config.accelerated = 1;
slouken@5131
    99
slouken@2765
   100
    return device;
slouken@2765
   101
}
slouken@2765
   102
slouken@2765
   103
VideoBootStrap UIKIT_bootstrap = {
slouken@2765
   104
    UIKITVID_DRIVER_NAME, "SDL UIKit video driver",
slouken@2765
   105
    UIKit_Available, UIKit_CreateDevice
slouken@2765
   106
};
slouken@2765
   107
slouken@2765
   108
icculus@4443
   109
/*
icculus@4443
   110
!!! FIXME:
icculus@4443
   111
icculus@4443
   112
The main screen should list a AxB mode for portrait orientation, and then
icculus@4443
   113
 also list BxA for landscape mode. When setting a given resolution, we should
icculus@4443
   114
 rotate the view's transform appropriately (extra credit if you check the
icculus@4443
   115
 accelerometer and rotate the display so it's never upside down).
icculus@4443
   116
icculus@4443
   117
  http://iphonedevelopment.blogspot.com/2008/10/starting-in-landscape-mode-without.html
icculus@4443
   118
icculus@4443
   119
*/
icculus@4443
   120
icculus@5518
   121
static CGSize
icculus@5518
   122
UIKit_ForcePortrait(const CGSize size)
icculus@5518
   123
{
icculus@5518
   124
    CGSize retval;
icculus@5518
   125
    if (size.width < size.height) { // portrait
icculus@5518
   126
        retval = size;
icculus@5518
   127
    } else {  // landscape
icculus@5518
   128
        retval.width = size.height;
icculus@5518
   129
        retval.height = size.width;
icculus@5518
   130
    }
icculus@5518
   131
    return retval;
icculus@5518
   132
}
icculus@5518
   133
icculus@5518
   134
static CGSize
icculus@5518
   135
UIKit_ForceLandscape(const CGSize size)
icculus@5518
   136
{
icculus@5518
   137
    CGSize retval;
icculus@5518
   138
    if (size.width > size.height) { // landscape
icculus@5518
   139
        retval = size;
icculus@5518
   140
    } else {  // portrait
icculus@5518
   141
        retval.width = size.height;
icculus@5518
   142
        retval.height = size.width;
icculus@5518
   143
    }
icculus@5518
   144
    return retval;
icculus@5518
   145
}
icculus@5518
   146
icculus@4443
   147
static void
icculus@4443
   148
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
icculus@4443
   149
{
icculus@4446
   150
    UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4443
   151
    SDL_DisplayMode mode;
icculus@4443
   152
    SDL_zero(mode);
icculus@4443
   153
icculus@4443
   154
    // availableModes showed up in 3.2 (the iPad and later). We should only
icculus@4443
   155
    //  land here for at least that version of the OS.
icculus@4446
   156
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4446
   157
        const CGRect rect = [uiscreen bounds];
icculus@4443
   158
        mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@4443
   159
        mode.w = (int) rect.size.width;
icculus@4443
   160
        mode.h = (int) rect.size.height;
icculus@4443
   161
        mode.refresh_rate = 0;
icculus@4443
   162
        mode.driverdata = NULL;
icculus@4443
   163
        SDL_AddDisplayMode(display, &mode);
icculus@5518
   164
        mode.w = (int) rect.size.height;  // swap the orientation, add again.
icculus@5518
   165
        mode.h = (int) rect.size.width;
icculus@5518
   166
        SDL_AddDisplayMode(display, &mode);
icculus@4443
   167
        return;
icculus@4443
   168
    }
icculus@4443
   169
icculus@5518
   170
    const int ismain = (uiscreen == [UIScreen mainScreen]);
icculus@4446
   171
    const NSArray *modes = [uiscreen availableModes];
icculus@4443
   172
    const NSUInteger mode_count = [modes count];
icculus@4443
   173
    NSUInteger i;
icculus@4443
   174
    for (i = 0; i < mode_count; i++) {
icculus@4443
   175
        UIScreenMode *uimode = (UIScreenMode *) [modes objectAtIndex:i];
icculus@5518
   176
        CGSize size = [uimode size];
icculus@4443
   177
        mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@5518
   178
        mode.refresh_rate = 0;
icculus@5518
   179
        mode.driverdata = uimode;
icculus@4443
   180
        mode.w = (int) size.width;
icculus@4443
   181
        mode.h = (int) size.height;
icculus@5518
   182
        if (SDL_AddDisplayMode(display, &mode))
icculus@5518
   183
            [uimode retain];
icculus@5518
   184
icculus@5518
   185
        if (ismain) {
icculus@5518
   186
            // Add the mode twice, flipped to portrait and landscape.
icculus@5518
   187
            //  SDL_AddDisplayMode() will ignore duplicates.
icculus@5518
   188
            size = UIKit_ForcePortrait([uimode size]);
icculus@5518
   189
            mode.w = (int) size.width;
icculus@5518
   190
            mode.h = (int) size.height;
icculus@5518
   191
            if (SDL_AddDisplayMode(display, &mode))
icculus@5518
   192
                [uimode retain];
icculus@5518
   193
icculus@5518
   194
            size = UIKit_ForceLandscape(size);
icculus@5518
   195
            mode.w = (int) size.width;
icculus@5518
   196
            mode.h = (int) size.height;
icculus@5518
   197
            if (SDL_AddDisplayMode(display, &mode))
icculus@5518
   198
                [uimode retain];
icculus@5518
   199
        }
icculus@4443
   200
    }
icculus@4443
   201
}
icculus@4443
   202
icculus@4443
   203
icculus@4443
   204
static void
icculus@5558
   205
UIKit_AddDisplay(UIScreen *uiscreen, UIScreenMode *uimode, int w, int h)
icculus@4443
   206
{
icculus@4443
   207
    SDL_VideoDisplay display;
icculus@4443
   208
    SDL_DisplayMode mode;
icculus@4443
   209
    SDL_zero(mode);
icculus@4443
   210
    mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@4443
   211
    mode.w = w;
icculus@4443
   212
    mode.h = h;
icculus@4443
   213
    mode.refresh_rate = 0;
kees@6001
   214
icculus@5558
   215
    [uimode retain];
icculus@5558
   216
    mode.driverdata = uimode;
icculus@4443
   217
icculus@4443
   218
    SDL_zero(display);
icculus@4443
   219
    display.desktop_mode = mode;
icculus@4443
   220
    display.current_mode = mode;
icculus@4446
   221
icculus@4446
   222
    [uiscreen retain];
icculus@4446
   223
    display.driverdata = uiscreen;
icculus@4443
   224
    SDL_AddVideoDisplay(&display);
icculus@4443
   225
}
icculus@4443
   226
icculus@4443
   227
slouken@2765
   228
int
slouken@2765
   229
UIKit_VideoInit(_THIS)
slouken@2765
   230
{
icculus@4443
   231
    _this->gl_config.driver_loaded = 1;
slouken@2765
   232
icculus@4445
   233
    NSString *reqSysVer = @"3.2";
icculus@4445
   234
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
icculus@4445
   235
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
icculus@4446
   236
        SDL_UIKit_supports_multiple_displays = YES;
slouken@2765
   237
icculus@4443
   238
    // If this is iPhoneOS < 3.2, all devices are one screen, 320x480 pixels.
icculus@4443
   239
    //  The iPad added both a larger main screen and the ability to use
icculus@4443
   240
    //  external displays.
icculus@4446
   241
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4443
   242
        // Just give 'em the whole main screen.
icculus@4446
   243
        UIScreen *uiscreen = [UIScreen mainScreen];
icculus@5558
   244
        UIScreenMode *uiscreenmode = [uiscreen currentMode];
icculus@4446
   245
        const CGRect rect = [uiscreen bounds];
icculus@5558
   246
        UIKit_AddDisplay(uiscreen, uiscreenmode, (int)rect.size.width, (int)rect.size.height);
icculus@4443
   247
    } else {
icculus@4443
   248
        const NSArray *screens = [UIScreen screens];
icculus@4443
   249
        const NSUInteger screen_count = [screens count];
icculus@4443
   250
        NSUInteger i;
icculus@4443
   251
        for (i = 0; i < screen_count; i++) {
icculus@4443
   252
            // the main screen is the first element in the array.
icculus@4446
   253
            UIScreen *uiscreen = (UIScreen *) [screens objectAtIndex:i];
icculus@5558
   254
            UIScreenMode *uiscreenmode = [uiscreen currentMode];
icculus@4446
   255
            const CGSize size = [[uiscreen currentMode] size];
icculus@5558
   256
            UIKit_AddDisplay(uiscreen, uiscreenmode, (int)size.width, (int)size.height);
icculus@4443
   257
        }
icculus@4443
   258
    }
slouken@2765
   259
slouken@2765
   260
    /* We're done! */
slouken@2765
   261
    return 0;
slouken@2765
   262
}
slouken@2765
   263
slouken@2765
   264
static int
slouken@3643
   265
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
slouken@2765
   266
{
icculus@4446
   267
    UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4446
   268
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4443
   269
        // Not on at least iPhoneOS 3.2 (versions prior to iPad).
icculus@4443
   270
        SDL_assert(mode->driverdata == NULL);
icculus@4443
   271
    } else {
icculus@4443
   272
        UIScreenMode *uimode = (UIScreenMode *) mode->driverdata;
icculus@4446
   273
        [uiscreen setCurrentMode:uimode];
icculus@4443
   274
    }
icculus@4443
   275
slouken@2765
   276
    return 0;
slouken@2765
   277
}
slouken@2765
   278
slouken@2765
   279
void
slouken@2765
   280
UIKit_VideoQuit(_THIS)
slouken@2765
   281
{
icculus@4443
   282
    // Release Objective-C objects, so higher level doesn't free() them.
icculus@4443
   283
    int i, j;
icculus@4443
   284
    for (i = 0; i < _this->num_displays; i++) {
icculus@4443
   285
        SDL_VideoDisplay *display = &_this->displays[i];
icculus@4446
   286
        UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4446
   287
        [uiscreen release];
icculus@4443
   288
        display->driverdata = NULL;
icculus@4443
   289
        for (j = 0; j < display->num_display_modes; j++) {
icculus@4443
   290
            SDL_DisplayMode *mode = &display->display_modes[j];
icculus@4443
   291
            UIScreenMode *uimode = (UIScreenMode *) mode->driverdata;
icculus@4443
   292
            if (uimode) {
icculus@4443
   293
                [uimode release];
icculus@4443
   294
                mode->driverdata = NULL;
icculus@4443
   295
            }
icculus@4443
   296
        }
icculus@4443
   297
    }
slouken@2765
   298
}
slouken@2765
   299
slouken@2765
   300
/* vi: set ts=4 sw=4 expandtab: */