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