1/* 2 Simple DirectMedia Layer 3 Copyright (C) 1997-2020 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_internal.h" 22 23#if SDL_VIDEO_DRIVER_COCOA 24 25#include "SDL.h" 26#include "SDL_endian.h" 27#include "SDL_cocoavideo.h" 28#include "SDL_cocoashape.h" 29#include "SDL_cocoavulkan.h" 30#include "SDL_cocoametalview.h" 31#include "SDL_assert.h" 32 33/* Initialization/Query functions */ 34static int Cocoa_VideoInit(_THIS); 35static void Cocoa_VideoQuit(_THIS); 36 37/* Cocoa driver bootstrap functions */ 38 39static int 40Cocoa_Available(void) 41{ 42 return (1); 43} 44 45static void 46Cocoa_DeleteDevice(SDL_VideoDevice * device) 47{ 48 SDL_free(device->driverdata); 49 SDL_free(device); 50} 51 52static SDL_VideoDevice * 53Cocoa_CreateDevice(int devindex) 54{ 55 SDL_VideoDevice *device; 56 SDL_VideoData *data; 57 58 Cocoa_RegisterApp(); 59 60 /* Initialize all variables that we clean on shutdown */ 61 device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice)); 62 if (device) { 63 data = (struct SDL_VideoData *) SDL_calloc(1, sizeof(SDL_VideoData)); 64 } else { 65 data = NULL; 66 } 67 if (!data) { 68 SDL_OutOfMemory(); 69 SDL_free(device); 70 return NULL; 71 } 72 device->driverdata = data; 73 74 /* Set the function pointers */ 75 device->VideoInit = Cocoa_VideoInit; 76 device->VideoQuit = Cocoa_VideoQuit; 77 device->GetDisplayBounds = Cocoa_GetDisplayBounds; 78 device->GetDisplayUsableBounds = Cocoa_GetDisplayUsableBounds; 79 device->GetDisplayDPI = Cocoa_GetDisplayDPI; 80 device->GetDisplayModes = Cocoa_GetDisplayModes; 81 device->SetDisplayMode = Cocoa_SetDisplayMode; 82 device->PumpEvents = Cocoa_PumpEvents; 83 device->SuspendScreenSaver = Cocoa_SuspendScreenSaver; 84 85 device->CreateSDLWindow = Cocoa_CreateWindow; 86 device->CreateSDLWindowFrom = Cocoa_CreateWindowFrom; 87 device->SetWindowTitle = Cocoa_SetWindowTitle; 88 device->SetWindowIcon = Cocoa_SetWindowIcon; 89 device->SetWindowPosition = Cocoa_SetWindowPosition; 90 device->SetWindowSize = Cocoa_SetWindowSize; 91 device->SetWindowMinimumSize = Cocoa_SetWindowMinimumSize; 92 device->SetWindowMaximumSize = Cocoa_SetWindowMaximumSize; 93 device->SetWindowOpacity = Cocoa_SetWindowOpacity; 94 device->ShowWindow = Cocoa_ShowWindow; 95 device->HideWindow = Cocoa_HideWindow; 96 device->RaiseWindow = Cocoa_RaiseWindow; 97 device->MaximizeWindow = Cocoa_MaximizeWindow; 98 device->MinimizeWindow = Cocoa_MinimizeWindow; 99 device->RestoreWindow = Cocoa_RestoreWindow; 100 device->SetWindowBordered = Cocoa_SetWindowBordered; 101 device->SetWindowResizable = Cocoa_SetWindowResizable; 102 device->SetWindowFullscreen = Cocoa_SetWindowFullscreen; 103 device->SetWindowGammaRamp = Cocoa_SetWindowGammaRamp; 104 device->GetWindowGammaRamp = Cocoa_GetWindowGammaRamp; 105 device->SetWindowGrab = Cocoa_SetWindowGrab; 106 device->DestroyWindow = Cocoa_DestroyWindow; 107 device->GetWindowWMInfo = Cocoa_GetWindowWMInfo; 108 device->SetWindowHitTest = Cocoa_SetWindowHitTest; 109 device->AcceptDragAndDrop = Cocoa_AcceptDragAndDrop; 110 111 device->shape_driver.CreateShaper = Cocoa_CreateShaper; 112 device->shape_driver.SetWindowShape = Cocoa_SetWindowShape; 113 device->shape_driver.ResizeWindowShape = Cocoa_ResizeWindowShape; 114 115#if SDL_VIDEO_OPENGL_CGL 116 device->GL_LoadLibrary = Cocoa_GL_LoadLibrary; 117 device->GL_GetProcAddress = Cocoa_GL_GetProcAddress; 118 device->GL_UnloadLibrary = Cocoa_GL_UnloadLibrary; 119 device->GL_CreateContext = Cocoa_GL_CreateContext; 120 device->GL_MakeCurrent = Cocoa_GL_MakeCurrent; 121 device->GL_GetDrawableSize = Cocoa_GL_GetDrawableSize; 122 device->GL_SetSwapInterval = Cocoa_GL_SetSwapInterval; 123 device->GL_GetSwapInterval = Cocoa_GL_GetSwapInterval; 124 device->GL_SwapWindow = Cocoa_GL_SwapWindow; 125 device->GL_DeleteContext = Cocoa_GL_DeleteContext; 126#elif SDL_VIDEO_OPENGL_EGL 127 device->GL_LoadLibrary = Cocoa_GLES_LoadLibrary; 128 device->GL_GetProcAddress = Cocoa_GLES_GetProcAddress; 129 device->GL_UnloadLibrary = Cocoa_GLES_UnloadLibrary; 130 device->GL_CreateContext = Cocoa_GLES_CreateContext; 131 device->GL_MakeCurrent = Cocoa_GLES_MakeCurrent; 132 device->GL_SetSwapInterval = Cocoa_GLES_SetSwapInterval; 133 device->GL_GetSwapInterval = Cocoa_GLES_GetSwapInterval; 134 device->GL_SwapWindow = Cocoa_GLES_SwapWindow; 135 device->GL_DeleteContext = Cocoa_GLES_DeleteContext; 136#endif 137 138#if SDL_VIDEO_VULKAN 139 device->Vulkan_LoadLibrary = Cocoa_Vulkan_LoadLibrary; 140 device->Vulkan_UnloadLibrary = Cocoa_Vulkan_UnloadLibrary; 141 device->Vulkan_GetInstanceExtensions = Cocoa_Vulkan_GetInstanceExtensions; 142 device->Vulkan_CreateSurface = Cocoa_Vulkan_CreateSurface; 143 device->Vulkan_GetDrawableSize = Cocoa_Vulkan_GetDrawableSize; 144#endif 145 146#if SDL_VIDEO_METAL 147 device->Metal_CreateView = Cocoa_Metal_CreateView; 148 device->Metal_DestroyView = Cocoa_Metal_DestroyView; 149 device->Metal_GetLayer = Cocoa_Metal_GetLayer; 150 device->Metal_GetDrawableSize = Cocoa_Metal_GetDrawableSize; 151#endif 152 153 device->StartTextInput = Cocoa_StartTextInput; 154 device->StopTextInput = Cocoa_StopTextInput; 155 device->SetTextInputRect = Cocoa_SetTextInputRect; 156 157 device->SetClipboardText = Cocoa_SetClipboardText; 158 device->GetClipboardText = Cocoa_GetClipboardText; 159 device->HasClipboardText = Cocoa_HasClipboardText; 160 161 device->free = Cocoa_DeleteDevice; 162 163 return device; 164} 165 166VideoBootStrap COCOA_bootstrap = { 167 "cocoa", "SDL Cocoa video driver", 168 Cocoa_Available, Cocoa_CreateDevice 169}; 170 171 172int 173Cocoa_VideoInit(_THIS) 174{ 175 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 176 177 Cocoa_InitModes(_this); 178 Cocoa_InitKeyboard(_this); 179 if (Cocoa_InitMouse(_this) < 0) { 180 return -1; 181 } 182 183 data->allow_spaces = ((floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6) && SDL_GetHintBoolean(SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES, SDL_TRUE)); 184 185 /* The IOPM assertion API can disable the screensaver as of 10.7. */ 186 data->screensaver_use_iopm = floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_6; 187 188 data->swaplock = SDL_CreateMutex(); 189 if (!data->swaplock) { 190 return -1; 191 } 192 193 return 0; 194} 195 196void 197Cocoa_VideoQuit(_THIS) 198{ 199 SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; 200 Cocoa_QuitModes(_this); 201 Cocoa_QuitKeyboard(_this); 202 Cocoa_QuitMouse(_this); 203 SDL_DestroyMutex(data->swaplock); 204 data->swaplock = NULL; 205} 206 207/* This function assumes that it's called from within an autorelease pool */ 208NSImage * 209Cocoa_CreateImage(SDL_Surface * surface) 210{ 211 SDL_Surface *converted; 212 NSBitmapImageRep *imgrep; 213 Uint8 *pixels; 214 int i; 215 NSImage *img; 216 217 converted = SDL_ConvertSurfaceFormat(surface, SDL_PIXELFORMAT_RGBA32, 0); 218 if (!converted) { 219 return nil; 220 } 221 222 imgrep = [[[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL 223 pixelsWide: converted->w 224 pixelsHigh: converted->h 225 bitsPerSample: 8 226 samplesPerPixel: 4 227 hasAlpha: YES 228 isPlanar: NO 229 colorSpaceName: NSDeviceRGBColorSpace 230 bytesPerRow: converted->pitch 231 bitsPerPixel: converted->format->BitsPerPixel] autorelease]; 232 if (imgrep == nil) { 233 SDL_FreeSurface(converted); 234 return nil; 235 } 236 237 /* Copy the pixels */ 238 pixels = [imgrep bitmapData]; 239 SDL_memcpy(pixels, converted->pixels, converted->h * converted->pitch); 240 SDL_FreeSurface(converted); 241 242 /* Premultiply the alpha channel */ 243 for (i = (surface->h * surface->w); i--; ) { 244 Uint8 alpha = pixels[3]; 245 pixels[0] = (Uint8)(((Uint16)pixels[0] * alpha) / 255); 246 pixels[1] = (Uint8)(((Uint16)pixels[1] * alpha) / 255); 247 pixels[2] = (Uint8)(((Uint16)pixels[2] * alpha) / 255); 248 pixels += 4; 249 } 250 251 img = [[[NSImage alloc] initWithSize: NSMakeSize(surface->w, surface->h)] autorelease]; 252 if (img != nil) { 253 [img addRepresentation: imgrep]; 254 } 255 return img; 256} 257 258/* 259 * Mac OS X log support. 260 * 261 * This doesn't really have aything to do with the interfaces of the SDL video 262 * subsystem, but we need to stuff this into an Objective-C source code file. 263 * 264 * NOTE: This is copypasted in src/video/uikit/SDL_uikitvideo.m! Be sure both 265 * versions remain identical! 266 */ 267 268void SDL_NSLog(const char *text) 269{ 270 NSLog(@"%s", text); 271} 272 273#endif /* SDL_VIDEO_DRIVER_COCOA */ 274 275/* vim: set ts=4 sw=4 expandtab: */ 276