src/video/cocoa/SDL_cocoavideo.m
author Sam Lantinga <slouken@libsdl.org>
Mon, 11 Feb 2013 17:39:52 -0800
changeset 6848 478ecc8a58b3
parent 6836 b0ca1571caf3
child 6885 700f1b25f77f
permissions -rw-r--r--
Backed out use of @autorelease keyword for now, since it's not supported by older Xcode versions.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 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_COCOA
    24 
    25 #if defined(__APPLE__) && defined(__POWERPC__)
    26 #include <altivec.h>
    27 #undef bool
    28 #undef vector
    29 #undef pixel
    30 #endif
    31 
    32 #include "SDL.h"
    33 #include "SDL_endian.h"
    34 #include "SDL_cocoavideo.h"
    35 #include "SDL_cocoashape.h"
    36 #include "SDL_assert.h"
    37 
    38 /* Initialization/Query functions */
    39 static int Cocoa_VideoInit(_THIS);
    40 static void Cocoa_VideoQuit(_THIS);
    41 
    42 /* Cocoa driver bootstrap functions */
    43 
    44 static int
    45 Cocoa_Available(void)
    46 {
    47     return (1);
    48 }
    49 
    50 static void
    51 Cocoa_DeleteDevice(SDL_VideoDevice * device)
    52 {
    53     SDL_free(device->driverdata);
    54     SDL_free(device);
    55 }
    56 
    57 static SDL_VideoDevice *
    58 Cocoa_CreateDevice(int devindex)
    59 {
    60     SDL_VideoDevice *device;
    61     SDL_VideoData *data;
    62 
    63     Cocoa_RegisterApp();
    64 
    65     /* Initialize all variables that we clean on shutdown */
    66     device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
    67     if (device) {
    68         data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData));
    69     } else {
    70         data = NULL;
    71     }
    72     if (!data) {
    73         SDL_OutOfMemory();
    74         if (device) {
    75             SDL_free(device);
    76         }
    77         return NULL;
    78     }
    79     device->driverdata = data;
    80 
    81     /* Find out what version of Mac OS X we're running */
    82     Gestalt(gestaltSystemVersion, &data->osversion);
    83 
    84     /* Set the function pointers */
    85     device->VideoInit = Cocoa_VideoInit;
    86     device->VideoQuit = Cocoa_VideoQuit;
    87     device->GetDisplayBounds = Cocoa_GetDisplayBounds;
    88     device->GetDisplayModes = Cocoa_GetDisplayModes;
    89     device->SetDisplayMode = Cocoa_SetDisplayMode;
    90     device->PumpEvents = Cocoa_PumpEvents;
    91 
    92     device->CreateWindow = Cocoa_CreateWindow;
    93     device->CreateWindowFrom = Cocoa_CreateWindowFrom;
    94     device->SetWindowTitle = Cocoa_SetWindowTitle;
    95     device->SetWindowIcon = Cocoa_SetWindowIcon;
    96     device->SetWindowPosition = Cocoa_SetWindowPosition;
    97     device->SetWindowSize = Cocoa_SetWindowSize;
    98     device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize;
    99     device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize;
   100     device->ShowWindow = Cocoa_ShowWindow;
   101     device->HideWindow = Cocoa_HideWindow;
   102     device->RaiseWindow = Cocoa_RaiseWindow;
   103     device->MaximizeWindow = Cocoa_MaximizeWindow;
   104     device->MinimizeWindow = Cocoa_MinimizeWindow;
   105     device->RestoreWindow = Cocoa_RestoreWindow;
   106     device->SetWindowBordered = Cocoa_SetWindowBordered;
   107     device->SetWindowFullscreen = Cocoa_SetWindowFullscreen;
   108     device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp;
   109     device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp;
   110     device->SetWindowGrab = Cocoa_SetWindowGrab;
   111     device->DestroyWindow = Cocoa_DestroyWindow;
   112     device->GetWindowWMInfo = Cocoa_GetWindowWMInfo;
   113     
   114     device->shape_driver.CreateShaper = Cocoa_CreateShaper;
   115     device->shape_driver.SetWindowShape = Cocoa_SetWindowShape;
   116     device->shape_driver.ResizeWindowShape = Cocoa_ResizeWindowShape;
   117     
   118 #if SDL_VIDEO_OPENGL_CGL
   119     device->GL_LoadLibrary = Cocoa_GL_LoadLibrary;
   120     device->GL_GetProcAddress = Cocoa_GL_GetProcAddress;
   121     device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary;
   122     device->GL_CreateContext = Cocoa_GL_CreateContext;
   123     device->GL_MakeCurrent = Cocoa_GL_MakeCurrent;
   124     device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval;
   125     device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval;
   126     device->GL_SwapWindow = Cocoa_GL_SwapWindow;
   127     device->GL_DeleteContext = Cocoa_GL_DeleteContext;
   128 #endif
   129 
   130     device->StartTextInput = Cocoa_StartTextInput;
   131     device->StopTextInput = Cocoa_StopTextInput;
   132     device->SetTextInputRect = Cocoa_SetTextInputRect;
   133 
   134     device->SetClipboardText = Cocoa_SetClipboardText;
   135     device->GetClipboardText = Cocoa_GetClipboardText;
   136     device->HasClipboardText = Cocoa_HasClipboardText;
   137 
   138     device->free = Cocoa_DeleteDevice;
   139 
   140     return device;
   141 }
   142 
   143 VideoBootStrap COCOA_bootstrap = {
   144     "cocoa", "SDL Cocoa video driver",
   145     Cocoa_Available, Cocoa_CreateDevice
   146 };
   147 
   148 
   149 int
   150 Cocoa_VideoInit(_THIS)
   151 {
   152     Cocoa_InitModes(_this);
   153     Cocoa_InitKeyboard(_this);
   154     Cocoa_InitMouse(_this);
   155     return 0;
   156 }
   157 
   158 void
   159 Cocoa_VideoQuit(_THIS)
   160 {
   161     Cocoa_QuitModes(_this);
   162     Cocoa_QuitKeyboard(_this);
   163     Cocoa_QuitMouse(_this);
   164 }
   165 
   166 /* This function assumes that it's called from within an autorelease pool */
   167 NSImage *
   168 Cocoa_CreateImage(SDL_Surface * surface)
   169 {
   170     SDL_Surface *converted;
   171     NSBitmapImageRep *imgrep;
   172     Uint8 *pixels;
   173     int i;
   174     NSImage *img;
   175 
   176     converted = SDL_ConvertSurfaceFormat(surface, 
   177 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
   178                                          SDL_PIXELFORMAT_RGBA8888,
   179 #else
   180                                          SDL_PIXELFORMAT_ABGR8888,
   181 #endif
   182                                          0);
   183     if (!converted) {
   184         return nil;
   185     }
   186 
   187     imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
   188                     pixelsWide: converted->w
   189                     pixelsHigh: converted->h
   190                     bitsPerSample: 8
   191                     samplesPerPixel: 4
   192                     hasAlpha: YES
   193                     isPlanar: NO
   194                     colorSpaceName: NSDeviceRGBColorSpace
   195                     bytesPerRow: converted->pitch
   196                     bitsPerPixel: converted->format->BitsPerPixel] autorelease];
   197     if (imgrep == nil) {
   198         SDL_FreeSurface(converted);
   199         return nil;
   200     }
   201 
   202     /* Copy the pixels */
   203     pixels = [imgrep bitmapData];
   204     SDL_memcpy(pixels, converted->pixels, converted->h * converted->pitch);
   205     SDL_FreeSurface(converted);
   206 
   207     /* Premultiply the alpha channel */
   208     for (i = (surface->h * surface->w); i--; ) {
   209         Uint8 alpha = pixels[3];
   210         pixels[0] = (Uint8)(((Uint16)pixels[0] * alpha) / 255);
   211         pixels[1] = (Uint8)(((Uint16)pixels[1] * alpha) / 255);
   212         pixels[2] = (Uint8)(((Uint16)pixels[2] * alpha) / 255);
   213         pixels += 4;
   214     }
   215 
   216     img = [[[NSImage alloc] initWithSize: NSMakeSize(surface->w, surface->h)] autorelease];
   217     if (img != nil) {
   218         [img addRepresentation: imgrep];
   219     }
   220     return img;
   221 }
   222 
   223 /*
   224  * Mac OS X log support.
   225  *
   226  * This doesn't really have aything to do with the interfaces of the SDL video
   227  *  subsystem, but we need to stuff this into an Objective-C source code file.
   228  */
   229 
   230 void SDL_NSLog(const char *text)
   231 {
   232     NSLog(@"%s", text);
   233 }
   234 
   235 /*
   236  * Mac OS X assertion support.
   237  *
   238  * This doesn't really have aything to do with the interfaces of the SDL video
   239  *  subsystem, but we need to stuff this into an Objective-C source code file.
   240  */
   241 
   242 SDL_assert_state
   243 SDL_PromptAssertion_cocoa(const SDL_assert_data *data)
   244 {
   245     const int initialized = (SDL_WasInit(SDL_INIT_VIDEO) != 0);
   246     if (!initialized) {
   247         if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1) {
   248             fprintf(stderr, "Assertion failed AND couldn't init video mode!\n");
   249             return SDL_ASSERTION_BREAK;  /* oh well, crash hard. */
   250         }
   251     }
   252 
   253     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
   254 
   255     NSString *msg = [NSString stringWithFormat:
   256             @"Assertion failure at %s (%s:%d), triggered %u time%s:\n  '%s'",
   257                 data->function, data->filename, data->linenum,
   258                 data->trigger_count, (data->trigger_count == 1) ? "" : "s",
   259                 data->condition];
   260 
   261     NSLog(@"%@", msg);
   262 
   263     /*
   264      * !!! FIXME: this code needs to deal with fullscreen modes:
   265      * !!! FIXME:  reset to default desktop, runModal, reset to current?
   266      */
   267 
   268     NSAlert* alert = [[NSAlert alloc] init];
   269     [alert setAlertStyle:NSCriticalAlertStyle];
   270     [alert setMessageText:msg];
   271     [alert addButtonWithTitle:@"Retry"];
   272     [alert addButtonWithTitle:@"Break"];
   273     [alert addButtonWithTitle:@"Abort"];
   274     [alert addButtonWithTitle:@"Ignore"];
   275     [alert addButtonWithTitle:@"Always Ignore"];
   276     const NSInteger clicked = [alert runModal];
   277     [alert release];
   278 
   279     [pool release];
   280 
   281     if (!initialized) {
   282         SDL_QuitSubSystem(SDL_INIT_VIDEO);
   283     }
   284 
   285     return (SDL_assert_state) (clicked - NSAlertFirstButtonReturn);
   286 }
   287 
   288 #endif /* SDL_VIDEO_DRIVER_COCOA */
   289 
   290 /* vim: set ts=4 sw=4 expandtab: */