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