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