📄 sdl_quartzvideo.m
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2003 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org*/#include "SDL_config.h"#include "SDL_QuartzVideo.h"#include "SDL_QuartzWindow.h"/* Add methods to get at private members of NSScreen. Since there is a bug in Apple's screen switching code that does not update this variable when switching to fullscreen, we'll set it manually (but only for the main screen).*/@interface NSScreen (NSScreenAccess)- (void) setFrame:(NSRect)frame;@end@implementation NSScreen (NSScreenAccess)- (void) setFrame:(NSRect)frame;{ _frame = frame;}@end@interface SDLTranslatorResponder : NSTextView{}- (void) doCommandBySelector:(SEL)myselector;@end@implementation SDLTranslatorResponder- (void) doCommandBySelector:(SEL) myselector {}@end/* Bootstrap functions */static int QZ_Available ();static SDL_VideoDevice* QZ_CreateDevice (int device_index);static void QZ_DeleteDevice (SDL_VideoDevice *device);/* Initialization, Query, Setup, and Redrawing functions */static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format);static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags);static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop);static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);static int QZ_ToggleFullScreen (_THIS, int on);static int QZ_SetColors (_THIS, int first_color, int num_colors, SDL_Color *colors);static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface);static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface);static int QZ_ThreadFlip (_THIS);static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface);static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects);static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects);static int QZ_LockWindow (_THIS, SDL_Surface *surface);static void QZ_UnlockWindow (_THIS, SDL_Surface *surface);static void QZ_UpdateRects (_THIS, int num_rects, SDL_Rect *rects);static void QZ_VideoQuit (_THIS);/* Hardware surface functions (for fullscreen mode only) */#if 0 /* Not used (apparently, it's really slow) */static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);#endifstatic int QZ_LockHWSurface(_THIS, SDL_Surface *surface);static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface);static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface);static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface);/* static int QZ_FlipHWSurface (_THIS, SDL_Surface *surface); *//* Bootstrap binding, enables entry point into the driver */VideoBootStrap QZ_bootstrap = { "Quartz", "Mac OS X CoreGraphics", QZ_Available, QZ_CreateDevice};/* Bootstrap functions */static int QZ_Available () { return 1;}static SDL_VideoDevice* QZ_CreateDevice (int device_index) {#pragma unused (device_index) SDL_VideoDevice *device; SDL_PrivateVideoData *hidden; device = (SDL_VideoDevice*) SDL_malloc (sizeof (*device) ); hidden = (SDL_PrivateVideoData*) SDL_malloc (sizeof (*hidden) ); if (device == NULL || hidden == NULL) SDL_OutOfMemory (); SDL_memset (device, 0, sizeof (*device) ); SDL_memset (hidden, 0, sizeof (*hidden) ); device->hidden = hidden; device->VideoInit = QZ_VideoInit; device->ListModes = QZ_ListModes; device->SetVideoMode = QZ_SetVideoMode; device->ToggleFullScreen = QZ_ToggleFullScreen; device->UpdateMouse = QZ_UpdateMouse; device->SetColors = QZ_SetColors; /* device->UpdateRects = QZ_UpdateRects; this is determined by SetVideoMode() */ device->VideoQuit = QZ_VideoQuit; device->LockHWSurface = QZ_LockHWSurface; device->UnlockHWSurface = QZ_UnlockHWSurface; device->AllocHWSurface = QZ_AllocHWSurface; device->FreeHWSurface = QZ_FreeHWSurface; /* device->FlipHWSurface = QZ_FlipHWSurface */; device->SetGamma = QZ_SetGamma; device->GetGamma = QZ_GetGamma; device->SetGammaRamp = QZ_SetGammaRamp; device->GetGammaRamp = QZ_GetGammaRamp; device->GL_GetProcAddress = QZ_GL_GetProcAddress; device->GL_GetAttribute = QZ_GL_GetAttribute; device->GL_MakeCurrent = QZ_GL_MakeCurrent; device->GL_SwapBuffers = QZ_GL_SwapBuffers; device->GL_LoadLibrary = QZ_GL_LoadLibrary; device->FreeWMCursor = QZ_FreeWMCursor; device->CreateWMCursor = QZ_CreateWMCursor; device->ShowWMCursor = QZ_ShowWMCursor; device->WarpWMCursor = QZ_WarpWMCursor; device->MoveWMCursor = QZ_MoveWMCursor; device->CheckMouseMode = QZ_CheckMouseMode; device->InitOSKeymap = QZ_InitOSKeymap; device->PumpEvents = QZ_PumpEvents; device->SetCaption = QZ_SetCaption; device->SetIcon = QZ_SetIcon; device->IconifyWindow = QZ_IconifyWindow; /*device->GetWMInfo = QZ_GetWMInfo;*/ device->GrabInput = QZ_GrabInput; device->CreateYUVOverlay = QZ_CreateYUVOverlay; device->free = QZ_DeleteDevice; return device;}static void QZ_DeleteDevice (SDL_VideoDevice *device) { SDL_free (device->hidden); SDL_free (device);}static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) { NSRect r = NSMakeRect(0.0, 0.0, 0.0, 0.0); const char *env = NULL; /* Initialize the video settings; this data persists between mode switches */ display_id = kCGDirectMainDisplay; save_mode = CGDisplayCurrentMode (display_id); mode_list = CGDisplayAvailableModes (display_id); palette = CGPaletteCreateDefaultColorPalette (); env = SDL_getenv("SDL_VIDEO_ALLOW_SCREENSAVER"); allow_screensaver = ( env && SDL_atoi(env) ) ? YES : NO; /* Gather some information that is useful to know about the display */ CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayBitsPerPixel), kCFNumberSInt32Type, &device_bpp); CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayWidth), kCFNumberSInt32Type, &device_width); CFNumberGetValue (CFDictionaryGetValue (save_mode, kCGDisplayHeight), kCFNumberSInt32Type, &device_height); /* Determine the current screen size */ this->info.current_w = device_width; this->info.current_h = device_height; /* Determine the default screen depth */ video_format->BitsPerPixel = device_bpp; /* Set misc globals */ current_grab_mode = SDL_GRAB_OFF; cursor_should_be_visible = YES; cursor_visible = YES; current_mods = 0; field_edit = [[SDLTranslatorResponder alloc] initWithFrame:r]; if ( Gestalt(gestaltSystemVersion, &system_version) != noErr ) system_version = 0; /* register for sleep notifications so wake from sleep generates SDL_VIDEOEXPOSE */ QZ_RegisterForSleepNotifications (this); /* Fill in some window manager capabilities */ this->info.wm_available = 1; return 0;}static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) { CFIndex num_modes; CFIndex i; int list_size = 0; /* Any windowed mode is acceptable */ if ( (flags & SDL_FULLSCREEN) == 0 ) return (SDL_Rect**)-1; /* Free memory from previous call, if any */ if ( client_mode_list != NULL ) { int i; for (i = 0; client_mode_list[i] != NULL; i++) SDL_free (client_mode_list[i]); SDL_free (client_mode_list); client_mode_list = NULL; } num_modes = CFArrayGetCount (mode_list); /* Build list of modes with the requested bpp */ for (i = 0; i < num_modes; i++) { CFDictionaryRef onemode; CFNumberRef number; int bpp; onemode = CFArrayGetValueAtIndex (mode_list, i); number = CFDictionaryGetValue (onemode, kCGDisplayBitsPerPixel); CFNumberGetValue (number, kCFNumberSInt32Type, &bpp); if (bpp == format->BitsPerPixel) { int intvalue; int hasMode; int width, height; number = CFDictionaryGetValue (onemode, kCGDisplayWidth); CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); width = (Uint16) intvalue; number = CFDictionaryGetValue (onemode, kCGDisplayHeight); CFNumberGetValue (number, kCFNumberSInt32Type, &intvalue); height = (Uint16) intvalue; /* Check if mode is already in the list */ { int i; hasMode = SDL_FALSE; for (i = 0; i < list_size; i++) { if (client_mode_list[i]->w == width && client_mode_list[i]->h == height) { hasMode = SDL_TRUE; break; } } } /* Grow the list and add mode to the list */ if ( ! hasMode ) { SDL_Rect *rect; list_size++; if (client_mode_list == NULL) client_mode_list = (SDL_Rect**) SDL_malloc (sizeof(*client_mode_list) * (list_size+1) ); else client_mode_list = (SDL_Rect**) SDL_realloc (client_mode_list, sizeof(*client_mode_list) * (list_size+1)); rect = (SDL_Rect*) SDL_malloc (sizeof(**client_mode_list)); if (client_mode_list == NULL || rect == NULL) { SDL_OutOfMemory (); return NULL; } rect->x = rect->y = 0; rect->w = width; rect->h = height; client_mode_list[list_size-1] = rect; client_mode_list[list_size] = NULL; } } } /* Sort list largest to smallest (by area) */ { int i, j; for (i = 0; i < list_size; i++) { for (j = 0; j < list_size-1; j++) { int area1, area2; area1 = client_mode_list[j]->w * client_mode_list[j]->h; area2 = client_mode_list[j+1]->w * client_mode_list[j+1]->h; if (area1 < area2) { SDL_Rect *tmp = client_mode_list[j]; client_mode_list[j] = client_mode_list[j+1]; client_mode_list[j+1] = tmp; } } } } return client_mode_list;}static SDL_bool QZ_WindowPosition(_THIS, int *x, int *y){ const char *window = getenv("SDL_VIDEO_WINDOW_POS"); if ( window ) { if ( sscanf(window, "%d,%d", x, y) == 2 ) { return SDL_TRUE; } } return SDL_FALSE;}static void QZ_UnsetVideoMode (_THIS, BOOL to_desktop) { /* Reset values that may change between switches */ this->info.blit_fill = 0; this->FillHWRect = NULL; this->UpdateRects = NULL; this->LockHWSurface = NULL; this->UnlockHWSurface = NULL; /* Release fullscreen resources */ if ( mode_flags & SDL_FULLSCREEN ) { NSRect screen_rect; /* Release double buffer stuff */ if ( mode_flags & SDL_DOUBLEBUF) { quit_thread = YES; SDL_SemPost (sem1); SDL_WaitThread (thread, NULL); SDL_DestroySemaphore (sem1); SDL_DestroySemaphore (sem2); SDL_free (sw_buffers[0]); } /* If we still have a valid window, close it. */ if ( qz_window ) { NSCAssert([ qz_window delegate ] == nil, @"full screen window shouldn't have a delegate"); /* if that should ever change, we'd have to release it here */ [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ qz_window = nil; window_view = nil; } /* Release the OpenGL context Do this first to avoid trash on the display before fade */ if ( mode_flags & SDL_OPENGL ) { QZ_TearDownOpenGL (this); CGLSetFullScreen (NULL); } if (to_desktop) { ShowMenuBar (); /* Restore original screen resolution/bpp */ CGDisplaySwitchToMode (display_id, save_mode); CGReleaseAllDisplays (); /* Reset the main screen's rectangle See comment in QZ_SetVideoFullscreen for why we do this */ screen_rect = NSMakeRect(0,0,device_width,device_height); [ [ NSScreen mainScreen ] setFrame:screen_rect ]; } } /* Release window mode resources */ else { id delegate = [ qz_window delegate ]; [ qz_window close ]; /* includes release because [qz_window isReleasedWhenClosed] */ if (delegate != nil) [ delegate release ]; qz_window = nil; window_view = nil; /* Release the OpenGL context */ if ( mode_flags & SDL_OPENGL ) QZ_TearDownOpenGL (this);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -