src/video/uikit/SDL_uikitvideo.m
author Sam Lantinga
Tue, 01 Feb 2011 08:59:22 -0800
changeset 5131 7b7da52e8775
parent 5056 8b7988f42fcb
child 5154 fb424691cfc7
permissions -rw-r--r--
Fixed spacing
slouken@2765
     1
/*
slouken@2765
     2
    SDL - Simple DirectMedia Layer
slouken@2859
     3
    Copyright (C) 1997-2009 Sam Lantinga
slouken@2765
     4
slouken@2765
     5
    This library is free software; you can redistribute it and/or
slouken@2765
     6
    modify it under the terms of the GNU Lesser General Public
slouken@2765
     7
    License as published by the Free Software Foundation; either
slouken@2765
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@2765
     9
slouken@2765
    10
    This library is distributed in the hope that it will be useful,
slouken@2765
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@2765
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@2765
    13
    Lesser General Public License for more details.
slouken@2765
    14
slouken@2765
    15
    You should have received a copy of the GNU Lesser General Public
slouken@2765
    16
    License along with this library; if not, write to the Free Software
slouken@2765
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@2765
    18
slouken@2765
    19
    Sam Lantinga
slouken@2765
    20
    slouken@libsdl.org
slouken@2765
    21
*/
icculus@4443
    22
icculus@4443
    23
#import <UIKit/UIKit.h>
icculus@4443
    24
slouken@2765
    25
#include "SDL_config.h"
slouken@2765
    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
slouken@2765
    38
#include "SDL_renderer_sw.h"
slouken@2765
    39
#include "SDL_renderer_gles.h"
slouken@2765
    40
icculus@4443
    41
#include "SDL_assert.h"
icculus@4443
    42
slouken@2765
    43
#define UIKITVID_DRIVER_NAME "uikit"
slouken@2765
    44
slouken@2765
    45
/* Initialization/Query functions */
slouken@2765
    46
static int UIKit_VideoInit(_THIS);
icculus@4443
    47
static void UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * sdl_display);
slouken@3643
    48
static int UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display,
slouken@3643
    49
                                SDL_DisplayMode * mode);
slouken@2765
    50
static void UIKit_VideoQuit(_THIS);
slouken@2765
    51
icculus@4446
    52
BOOL SDL_UIKit_supports_multiple_displays = NO;
icculus@4443
    53
slouken@2765
    54
/* DUMMY driver bootstrap functions */
slouken@2765
    55
slouken@2765
    56
static int
slouken@2765
    57
UIKit_Available(void)
slouken@2765
    58
{
slouken@5131
    59
    return (1);
slouken@2765
    60
}
slouken@2765
    61
slouken@2765
    62
static void UIKit_DeleteDevice(SDL_VideoDevice * device)
slouken@2765
    63
{
slouken@2765
    64
    SDL_free(device);
slouken@2765
    65
}
slouken@2765
    66
slouken@2765
    67
static SDL_VideoDevice *
slouken@2765
    68
UIKit_CreateDevice(int devindex)
slouken@2765
    69
{
slouken@2765
    70
    SDL_VideoDevice *device;
slouken@2765
    71
slouken@2765
    72
    /* Initialize all variables that we clean on shutdown */
slouken@2765
    73
    device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
slouken@2765
    74
    if (!device) {
slouken@2765
    75
        SDL_OutOfMemory();
slouken@2765
    76
        if (device) {
slouken@2765
    77
            SDL_free(device);
slouken@2765
    78
        }
slouken@2765
    79
        return (0);
slouken@2765
    80
    }
slouken@2765
    81
slouken@2765
    82
    /* Set the function pointers */
slouken@2765
    83
    device->VideoInit = UIKit_VideoInit;
slouken@2765
    84
    device->VideoQuit = UIKit_VideoQuit;
icculus@4443
    85
    device->GetDisplayModes = UIKit_GetDisplayModes;
slouken@2765
    86
    device->SetDisplayMode = UIKit_SetDisplayMode;
slouken@2765
    87
    device->PumpEvents = UIKit_PumpEvents;
slouken@5131
    88
    device->CreateWindow = UIKit_CreateWindow;
slouken@5131
    89
    device->DestroyWindow = UIKit_DestroyWindow;
slouken@5056
    90
    device->GetWindowWMInfo = UIKit_GetWindowWMInfo;
slouken@5131
    91
    
slouken@5131
    92
    
slouken@5131
    93
    /* OpenGL (ES) functions */
slouken@5131
    94
    device->GL_MakeCurrent        = UIKit_GL_MakeCurrent;
slouken@5131
    95
    device->GL_SwapWindow        = UIKit_GL_SwapWindow;
slouken@5131
    96
    device->GL_CreateContext    = UIKit_GL_CreateContext;
slouken@5131
    97
    device->GL_DeleteContext    = UIKit_GL_DeleteContext;
slouken@5131
    98
    device->GL_GetProcAddress   = UIKit_GL_GetProcAddress;
slouken@5131
    99
    device->GL_LoadLibrary        = UIKit_GL_LoadLibrary;
slouken@5131
   100
    device->free = UIKit_DeleteDevice;
slouken@2765
   101
slouken@5131
   102
    device->gl_config.accelerated = 1;
slouken@5131
   103
slouken@2765
   104
    return device;
slouken@2765
   105
}
slouken@2765
   106
slouken@2765
   107
VideoBootStrap UIKIT_bootstrap = {
slouken@2765
   108
    UIKITVID_DRIVER_NAME, "SDL UIKit video driver",
slouken@2765
   109
    UIKit_Available, UIKit_CreateDevice
slouken@2765
   110
};
slouken@2765
   111
slouken@2765
   112
icculus@4443
   113
/*
icculus@4443
   114
!!! FIXME:
icculus@4443
   115
icculus@4443
   116
The main screen should list a AxB mode for portrait orientation, and then
icculus@4443
   117
 also list BxA for landscape mode. When setting a given resolution, we should
icculus@4443
   118
 rotate the view's transform appropriately (extra credit if you check the
icculus@4443
   119
 accelerometer and rotate the display so it's never upside down).
icculus@4443
   120
icculus@4443
   121
  http://iphonedevelopment.blogspot.com/2008/10/starting-in-landscape-mode-without.html
icculus@4443
   122
icculus@4443
   123
*/
icculus@4443
   124
icculus@4443
   125
static void
icculus@4443
   126
UIKit_GetDisplayModes(_THIS, SDL_VideoDisplay * display)
icculus@4443
   127
{
icculus@4446
   128
    UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4443
   129
    SDL_DisplayMode mode;
icculus@4443
   130
    SDL_zero(mode);
icculus@4443
   131
icculus@4443
   132
    // availableModes showed up in 3.2 (the iPad and later). We should only
icculus@4443
   133
    //  land here for at least that version of the OS.
icculus@4446
   134
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4446
   135
        const CGRect rect = [uiscreen bounds];
icculus@4443
   136
        mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@4443
   137
        mode.w = (int) rect.size.width;
icculus@4443
   138
        mode.h = (int) rect.size.height;
icculus@4443
   139
        mode.refresh_rate = 0;
icculus@4443
   140
        mode.driverdata = NULL;
icculus@4443
   141
        SDL_AddDisplayMode(display, &mode);
icculus@4443
   142
        return;
icculus@4443
   143
    }
icculus@4443
   144
icculus@4446
   145
    const NSArray *modes = [uiscreen availableModes];
icculus@4443
   146
    const NSUInteger mode_count = [modes count];
icculus@4443
   147
    NSUInteger i;
icculus@4443
   148
    for (i = 0; i < mode_count; i++) {
icculus@4443
   149
        UIScreenMode *uimode = (UIScreenMode *) [modes objectAtIndex:i];
icculus@4443
   150
        const CGSize size = [uimode size];
icculus@4443
   151
        mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@4443
   152
        mode.w = (int) size.width;
icculus@4443
   153
        mode.h = (int) size.height;
icculus@4443
   154
        mode.refresh_rate = 0;
icculus@4443
   155
        mode.driverdata = uimode;
icculus@4443
   156
        [uimode retain];
icculus@4443
   157
        SDL_AddDisplayMode(display, &mode);
icculus@4443
   158
    }
icculus@4443
   159
}
icculus@4443
   160
icculus@4443
   161
icculus@4443
   162
static void
icculus@4446
   163
UIKit_AddDisplay(UIScreen *uiscreen, int w, int h)
icculus@4443
   164
{
icculus@4443
   165
    SDL_VideoDisplay display;
icculus@4443
   166
    SDL_DisplayMode mode;
icculus@4443
   167
    SDL_zero(mode);
icculus@4443
   168
    mode.format = SDL_PIXELFORMAT_ABGR8888;
icculus@4443
   169
    mode.w = w;
icculus@4443
   170
    mode.h = h;
icculus@4443
   171
    mode.refresh_rate = 0;
icculus@4443
   172
icculus@4443
   173
    SDL_zero(display);
icculus@4443
   174
    display.desktop_mode = mode;
icculus@4443
   175
    display.current_mode = mode;
icculus@4446
   176
icculus@4446
   177
    [uiscreen retain];
icculus@4446
   178
    display.driverdata = uiscreen;
icculus@4443
   179
    SDL_AddVideoDisplay(&display);
icculus@4443
   180
}
icculus@4443
   181
icculus@4443
   182
slouken@2765
   183
int
slouken@2765
   184
UIKit_VideoInit(_THIS)
slouken@2765
   185
{
icculus@4443
   186
    _this->gl_config.driver_loaded = 1;
slouken@2765
   187
icculus@4445
   188
    NSString *reqSysVer = @"3.2";
icculus@4445
   189
    NSString *currSysVer = [[UIDevice currentDevice] systemVersion];
icculus@4445
   190
    if ([currSysVer compare:reqSysVer options:NSNumericSearch] != NSOrderedAscending)
icculus@4446
   191
        SDL_UIKit_supports_multiple_displays = YES;
slouken@2765
   192
icculus@4443
   193
    // If this is iPhoneOS < 3.2, all devices are one screen, 320x480 pixels.
icculus@4443
   194
    //  The iPad added both a larger main screen and the ability to use
icculus@4443
   195
    //  external displays.
icculus@4446
   196
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4443
   197
        // Just give 'em the whole main screen.
icculus@4446
   198
        UIScreen *uiscreen = [UIScreen mainScreen];
icculus@4446
   199
        const CGRect rect = [uiscreen bounds];
icculus@4446
   200
        UIKit_AddDisplay(uiscreen, (int)rect.size.width, (int)rect.size.height);
icculus@4443
   201
    } else {
icculus@4443
   202
        const NSArray *screens = [UIScreen screens];
icculus@4443
   203
        const NSUInteger screen_count = [screens count];
icculus@4443
   204
        NSUInteger i;
icculus@4443
   205
        for (i = 0; i < screen_count; i++) {
icculus@4443
   206
            // the main screen is the first element in the array.
icculus@4446
   207
            UIScreen *uiscreen = (UIScreen *) [screens objectAtIndex:i];
icculus@4446
   208
            const CGSize size = [[uiscreen currentMode] size];
icculus@4446
   209
            UIKit_AddDisplay(uiscreen, (int) size.width, (int) size.height);
icculus@4443
   210
        }
icculus@4443
   211
    }
slouken@2765
   212
slouken@2765
   213
    /* We're done! */
slouken@2765
   214
    return 0;
slouken@2765
   215
}
slouken@2765
   216
slouken@2765
   217
static int
slouken@3643
   218
UIKit_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
slouken@2765
   219
{
icculus@4446
   220
    UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4446
   221
    if (!SDL_UIKit_supports_multiple_displays) {
icculus@4443
   222
        // Not on at least iPhoneOS 3.2 (versions prior to iPad).
icculus@4443
   223
        SDL_assert(mode->driverdata == NULL);
icculus@4443
   224
    } else {
icculus@4443
   225
        UIScreenMode *uimode = (UIScreenMode *) mode->driverdata;
icculus@4446
   226
        [uiscreen setCurrentMode:uimode];
icculus@4443
   227
    }
icculus@4443
   228
slouken@2765
   229
    return 0;
slouken@2765
   230
}
slouken@2765
   231
slouken@2765
   232
void
slouken@2765
   233
UIKit_VideoQuit(_THIS)
slouken@2765
   234
{
icculus@4443
   235
    // Release Objective-C objects, so higher level doesn't free() them.
icculus@4443
   236
    int i, j;
icculus@4443
   237
    for (i = 0; i < _this->num_displays; i++) {
icculus@4443
   238
        SDL_VideoDisplay *display = &_this->displays[i];
icculus@4446
   239
        UIScreen *uiscreen = (UIScreen *) display->driverdata;
icculus@4446
   240
        [uiscreen release];
icculus@4443
   241
        display->driverdata = NULL;
icculus@4443
   242
        for (j = 0; j < display->num_display_modes; j++) {
icculus@4443
   243
            SDL_DisplayMode *mode = &display->display_modes[j];
icculus@4443
   244
            UIScreenMode *uimode = (UIScreenMode *) mode->driverdata;
icculus@4443
   245
            if (uimode) {
icculus@4443
   246
                [uimode release];
icculus@4443
   247
                mode->driverdata = NULL;
icculus@4443
   248
            }
icculus@4443
   249
        }
icculus@4443
   250
    }
slouken@2765
   251
}
slouken@2765
   252
slouken@2765
   253
/* vi: set ts=4 sw=4 expandtab: */