diff options
Diffstat (limited to 'distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzVideo.m')
-rw-r--r-- | distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzVideo.m | 1691 |
1 files changed, 0 insertions, 1691 deletions
diff --git a/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzVideo.m b/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzVideo.m deleted file mode 100644 index 5edd60b..0000000 --- a/distrib/sdl-1.2.12/src/video/quartz/SDL_QuartzVideo.m +++ /dev/null @@ -1,1691 +0,0 @@ -/* - 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" -#include "SDL_QuartzWM.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 - - -/* 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); -#endif -static 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->SetWindowPos = QZ_SetWindowPos; - device->GetWindowPos = QZ_GetWindowPos; - device->IsWindowVisible = QZ_IsWindowVisible; - device->GetMonitorDPI = QZ_GetMonitorDPI; - device->GetMonitorRect = QZ_GetMonitorRect; - 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 = [[NSTextView 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 ) { - [ qz_window close ]; - [ qz_window release ]; - 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 { - - [ qz_window close ]; - [ qz_window release ]; - qz_window = nil; - window_view = nil; - - /* Release the OpenGL context */ - if ( mode_flags & SDL_OPENGL ) - QZ_TearDownOpenGL (this); - } - - /* Signal successful teardown */ - video_set = SDL_FALSE; -} - -static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width, - int height, int bpp, Uint32 flags) { - boolean_t exact_match = 0; - NSRect screen_rect; - CGError error; - NSRect contentRect; - BOOL isCustom = NO; - CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; - - /* Fade to black to hide resolution-switching flicker (and garbage - that is displayed by a destroyed OpenGL context, if applicable) */ - if ( CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess ) { - CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); - } - - /* Destroy any previous mode */ - if (video_set == SDL_TRUE) - QZ_UnsetVideoMode (this, FALSE); - - /* See if requested mode exists */ - mode = CGDisplayBestModeForParameters (display_id, bpp, width, - height, &exact_match); - - /* Require an exact match to the requested mode */ - if ( ! exact_match ) { - SDL_SetError ("Failed to find display resolution: %dx%dx%d", width, height, bpp); - goto ERR_NO_MATCH; - } - - /* Put up the blanking window (a window above all other windows) */ - if (getenv ("SDL_SINGLEDISPLAY")) - error = CGDisplayCapture (display_id); - else - error = CGCaptureAllDisplays (); - - if ( CGDisplayNoErr != error ) { - SDL_SetError ("Failed capturing display"); - goto ERR_NO_CAPTURE; - } - - /* Do the physical switch */ - if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) { - SDL_SetError ("Failed switching display resolution"); - goto ERR_NO_SWITCH; - } - - current->pixels = (Uint32*) CGDisplayBaseAddress (display_id); - current->pitch = CGDisplayBytesPerRow (display_id); - - current->flags = 0; - current->w = width; - current->h = height; - current->flags |= SDL_FULLSCREEN; - current->flags |= SDL_HWSURFACE; - current->flags |= SDL_PREALLOC; - - this->UpdateRects = QZ_DirectUpdate; - this->LockHWSurface = QZ_LockHWSurface; - this->UnlockHWSurface = QZ_UnlockHWSurface; - - /* Setup double-buffer emulation */ - if ( flags & SDL_DOUBLEBUF ) { - - /* - Setup a software backing store for reasonable results when - double buffering is requested (since a single-buffered hardware - surface looks hideous). - - The actual screen blit occurs in a separate thread to allow - other blitting while waiting on the VBL (and hence results in higher framerates). - */ - this->LockHWSurface = NULL; - this->UnlockHWSurface = NULL; - this->UpdateRects = NULL; - - current->flags |= (SDL_HWSURFACE|SDL_DOUBLEBUF); - this->UpdateRects = QZ_DoubleBufferUpdate; - this->LockHWSurface = QZ_LockDoubleBuffer; - this->UnlockHWSurface = QZ_UnlockDoubleBuffer; - this->FlipHWSurface = QZ_FlipDoubleBuffer; - - current->pixels = SDL_malloc (current->pitch * current->h * 2); - if (current->pixels == NULL) { - SDL_OutOfMemory (); - goto ERR_DOUBLEBUF; - } - - sw_buffers[0] = current->pixels; - sw_buffers[1] = (Uint8*)current->pixels + current->pitch * current->h; - - quit_thread = NO; - sem1 = SDL_CreateSemaphore (0); - sem2 = SDL_CreateSemaphore (1); - thread = SDL_CreateThread ((int (*)(void *))QZ_ThreadFlip, this); - } - - if ( CGDisplayCanSetPalette (display_id) ) - current->flags |= SDL_HWPALETTE; - - /* The code below checks for any valid custom windows and views. If none are - available, then we create new ones. Window/View code was added in FULLSCREEN - so that special events like the changing of the cursor image would be handled - ( only the front-most and active application can change the cursor appearance - and with no valid window/view in FULLSCREEN, SDL wouldn't update its cursor. ) - */ - /* Check for user-specified window and view */ - { - char *windowPtrString = getenv ("SDL_NSWindowPointer"); - char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer"); - - contentRect = NSMakeRect (0, 0, width, height); - - if (windowPtrString && viewPtrString) { - /* Release any previous window */ - if ( qz_window ) { - [ qz_window release ]; - qz_window = nil; - } - - qz_window = (NSWindow*)atoi(windowPtrString); - window_view = (NSQuickDrawView*)atoi(viewPtrString); - isCustom = YES; - /* - Retain reference to window because we - might release it in QZ_UnsetVideoMode - */ - [ qz_window retain ]; - } - } - /* Check if we should recreate the window */ - if (qz_window == nil) { - /* Manually create a window, avoids having a nib file resource */ - qz_window = [ [ SDL_QuartzWindow alloc ] - initWithContentRect:contentRect - styleMask:nil - backing:NSBackingStoreBuffered - defer:NO ]; - - if (qz_window != nil) { - [ qz_window setAcceptsMouseMovedEvents:YES ]; - [ qz_window setViewsNeedDisplay:NO ]; - } - } - /* We already have a window, just change its size */ - else { - if (!isCustom) { - [ qz_window setContentSize:contentRect.size ]; - current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags; - [ window_view setFrameSize:contentRect.size ]; - } - } - - /* Setup OpenGL for a fullscreen context */ - if (flags & SDL_OPENGL) { - - CGLError err; - CGLContextObj ctx; - - if ( ! QZ_SetupOpenGL (this, bpp, flags) ) { - goto ERR_NO_GL; - } - - /* Initialize the NSView and add it to our window. The presence of a valid window and - view allow the cursor to be changed whilst in fullscreen.*/ - window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; - [ [ qz_window contentView ] addSubview:window_view ]; - [ window_view release ]; - - ctx = [ gl_context cglContext ]; - err = CGLSetFullScreen (ctx); - - if (err) { - SDL_SetError ("Error setting OpenGL fullscreen: %s", CGLErrorString(err)); - goto ERR_NO_GL; - } - - [ gl_context makeCurrentContext]; - - glClear (GL_COLOR_BUFFER_BIT); - - [ gl_context flushBuffer ]; - - current->flags |= SDL_OPENGL; - } - - /* If we don't hide menu bar, it will get events and interrupt the program */ - HideMenuBar (); - - /* Fade in again (asynchronously) */ - if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation(fade_token); - } - - /* - There is a bug in Cocoa where NSScreen doesn't synchronize - with CGDirectDisplay, so the main screen's frame is wrong. - As a result, coordinate translation produces incorrect results. - We can hack around this bug by setting the screen rect - ourselves. This hack should be removed if/when the bug is fixed. - */ - screen_rect = NSMakeRect(0,0,width,height); - [ [ NSScreen mainScreen ] setFrame:screen_rect ]; - - /* Save the flags to ensure correct tear-down */ - mode_flags = current->flags; - - /* Set app state, hide cursor if necessary, ... */ - QZ_DoActivate(this); - - return current; - - /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */ -ERR_NO_GL: -ERR_DOUBLEBUF: CGDisplaySwitchToMode (display_id, save_mode); -ERR_NO_SWITCH: CGReleaseAllDisplays (); -ERR_NO_CAPTURE: -ERR_NO_MATCH: if ( fade_token != kCGDisplayFadeReservationInvalidToken ) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation (fade_token); - } - return NULL; -} - -static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width, - int height, int *bpp, Uint32 flags) { - unsigned int style; - NSRect contentRect; - BOOL isCustom = NO; - int center_window = 1; - int origin_x, origin_y; - CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; - - current->flags = 0; - current->w = width; - current->h = height; - - contentRect = NSMakeRect (0, 0, width, height); - - /* - Check if we should completely destroy the previous mode - - If it is fullscreen - - If it has different noframe or resizable attribute - - If it is OpenGL (since gl attributes could be different) - - If new mode is OpenGL, but previous mode wasn't - */ - if (video_set == SDL_TRUE) { - if (mode_flags & SDL_FULLSCREEN) { - /* Fade to black to hide resolution-switching flicker (and garbage - that is displayed by a destroyed OpenGL context, if applicable) */ - if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { - CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); - } - QZ_UnsetVideoMode (this, TRUE); - } - else if ( ((mode_flags ^ flags) & (SDL_NOFRAME|SDL_RESIZABLE)) || - (mode_flags & SDL_OPENGL) || - (flags & SDL_OPENGL) ) { - QZ_UnsetVideoMode (this, TRUE); - } - } - - /* Check for user-specified window and view */ - { - char *windowPtrString = getenv ("SDL_NSWindowPointer"); - char *viewPtrString = getenv ("SDL_NSQuickDrawViewPointer"); - - if (windowPtrString && viewPtrString) { - - /* Release any previous window */ - if ( qz_window ) { - [ qz_window release ]; - qz_window = nil; - } - - qz_window = (NSWindow*)atoi(windowPtrString); - window_view = (NSQuickDrawView*)atoi(viewPtrString); - isCustom = YES; - - /* - Retain reference to window because we - might release it in QZ_UnsetVideoMode - */ - [ qz_window retain ]; - - style = [ qz_window styleMask ]; - /* Check resizability */ - if ( style & NSResizableWindowMask ) - current->flags |= SDL_RESIZABLE; - - /* Check frame */ - if ( style & NSBorderlessWindowMask ) - current->flags |= SDL_NOFRAME; - } - } - - /* Check if we should recreate the window */ - if (qz_window == nil) { - - /* Set the window style based on input flags */ - if ( flags & SDL_NOFRAME ) { - style = NSBorderlessWindowMask; - current->flags |= SDL_NOFRAME; - } else { - style = NSTitledWindowMask; - style |= (NSMiniaturizableWindowMask | NSClosableWindowMask); - if ( flags & SDL_RESIZABLE ) { - style |= NSResizableWindowMask; - current->flags |= SDL_RESIZABLE; - } - } - /* Manually create a window, avoids having a nib file resource */ - qz_window = [ [ SDL_QuartzWindow alloc ] - initWithContentRect:contentRect - styleMask:style - backing:NSBackingStoreBuffered - defer:NO ]; - - if (qz_window == nil) { - SDL_SetError ("Could not create the Cocoa window"); - if (fade_token != kCGDisplayFadeReservationInvalidToken) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation (fade_token); - } - return NULL; - } - - /*[ qz_window setReleasedWhenClosed:YES ];*/ - QZ_SetCaption(this, this->wm_title, this->wm_icon); - [ qz_window setAcceptsMouseMovedEvents:YES ]; - [ qz_window setViewsNeedDisplay:NO ]; - - if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) { - [ qz_window setFrameTopLeftPoint:NSMakePoint(origin_x,this->info.current_h - origin_y) ]; - } else { - [ qz_window center ]; - } - [ qz_window setDelegate: - [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ]; - [ qz_window setContentView: [ [ [ SDL_QuartzView alloc ] init ] autorelease ] ]; - } - /* We already have a window, just change its size */ - else { - - if (!isCustom) { - [ qz_window setContentSize:contentRect.size ]; - current->flags |= (SDL_NOFRAME|SDL_RESIZABLE) & mode_flags; - [ window_view setFrameSize:contentRect.size ]; - } - } - - /* For OpenGL, we bind the context to a subview */ - if ( flags & SDL_OPENGL ) { - - if ( ! QZ_SetupOpenGL (this, *bpp, flags) ) { - if (fade_token != kCGDisplayFadeReservationInvalidToken) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation (fade_token); - } - return NULL; - } - - window_view = [ [ NSView alloc ] initWithFrame:contentRect ]; - [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; - [ [ qz_window contentView ] addSubview:window_view ]; - [ gl_context setView: window_view ]; - [ window_view release ]; - [ gl_context makeCurrentContext]; - [ qz_window makeKeyAndOrderFront:nil ]; - current->flags |= SDL_OPENGL; - } - /* For 2D, we set the subview to an NSQuickDrawView */ - else { - short qdbpp = 0; - CGrafPtr qdport; - - /* Only recreate the view if it doesn't already exist */ - if (window_view == nil) { - - window_view = [ [ NSQuickDrawView alloc ] initWithFrame:contentRect ]; - [ window_view setAutoresizingMask: NSViewWidthSizable | NSViewHeightSizable ]; - [ [ qz_window contentView ] addSubview:window_view ]; - [ window_view release ]; - [ qz_window makeKeyAndOrderFront:nil ]; - } - - qdport = [ window_view qdPort ]; - - LockPortBits ( qdport ); - current->pixels = GetPixBaseAddr ( GetPortPixMap ( qdport ) ); - current->pitch = GetPixRowBytes ( GetPortPixMap ( qdport ) ); - qdbpp = GetPixDepth ( GetPortPixMap ( qdport ) ); - UnlockPortBits ( qdport ); - - /* QuickDraw may give a 16-bit shadow surface on 8-bit displays! */ - *bpp = qdbpp; - - current->flags |= SDL_SWSURFACE; - current->flags |= SDL_PREALLOC; - current->flags |= SDL_ASYNCBLIT; - - /* - current->pixels now points to the window's pixels - We want it to point to the *view's* pixels - */ - { - NSRect winFrame = [ qz_window frame ]; - NSRect viewFrame = [ window_view frame ]; - - int vOffset = winFrame.size.height - viewFrame.size.height - viewFrame.origin.y; - int hOffset = viewFrame.origin.x; - - current->pixels = (Uint8 *)current->pixels + (vOffset * current->pitch) + hOffset * (qdbpp/8); - } - this->UpdateRects = QZ_UpdateRects; - this->LockHWSurface = QZ_LockWindow; - this->UnlockHWSurface = QZ_UnlockWindow; - } - - /* Save flags to ensure correct teardown */ - mode_flags = current->flags; - - /* Fade in again (asynchronously) if we came from a fullscreen mode and faded to black */ - if (fade_token != kCGDisplayFadeReservationInvalidToken) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation (fade_token); - } - - return current; -} - -static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, - int height, int bpp, Uint32 flags) { - - current->flags = 0; - current->pixels = NULL; - - /* Setup full screen video */ - if ( flags & SDL_FULLSCREEN ) { - current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags ); - if (current == NULL) - return NULL; - } - /* Setup windowed video */ - else { - /* Force bpp to the device's bpp */ - bpp = device_bpp; - current = QZ_SetVideoWindowed (this, current, width, height, &bpp, flags); - if (current == NULL) - return NULL; - } - - /* Setup the new pixel format */ - { - int amask = 0, - rmask = 0, - gmask = 0, - bmask = 0; - - switch (bpp) { - case 16: /* (1)-5-5-5 RGB */ - amask = 0; - rmask = 0x7C00; - gmask = 0x03E0; - bmask = 0x001F; - break; - case 24: - SDL_SetError ("24bpp is not available"); - return NULL; - case 32: /* (8)-8-8-8 ARGB */ - amask = 0x00000000; - rmask = 0x00FF0000; - gmask = 0x0000FF00; - bmask = 0x000000FF; - break; - } - - if ( ! SDL_ReallocFormat (current, bpp, - rmask, gmask, bmask, amask ) ) { - SDL_SetError ("Couldn't reallocate pixel format"); - return NULL; - } - } - - /* Signal successful completion (used internally) */ - video_set = SDL_TRUE; - - return current; -} - -static int QZ_ToggleFullScreen (_THIS, int on) { - return 0; -} - -static int QZ_SetColors (_THIS, int first_color, int num_colors, - SDL_Color *colors) { - - CGTableCount index; - CGDeviceColor color; - - for (index = first_color; index < first_color+num_colors; index++) { - - /* Clamp colors between 0.0 and 1.0 */ - color.red = colors->r / 255.0; - color.blue = colors->b / 255.0; - color.green = colors->g / 255.0; - - colors++; - - CGPaletteSetColorAtIndex (palette, color, index); - } - - if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) ) - return 0; - - return 1; -} - -static int QZ_LockDoubleBuffer (_THIS, SDL_Surface *surface) { - - return 1; -} - -static void QZ_UnlockDoubleBuffer (_THIS, SDL_Surface *surface) { - -} - - /* The VBL delay is based on code by Ian R Ollmann's RezLib <iano@cco.caltech.edu> */ - static AbsoluteTime QZ_SecondsToAbsolute ( double seconds ) { - - union - { - UInt64 i; - Nanoseconds ns; - } temp; - - temp.i = seconds * 1000000000.0; - - return NanosecondsToAbsolute ( temp.ns ); -} - -static int QZ_ThreadFlip (_THIS) { - - Uint8 *src, *dst; - int skip, len, h; - - /* - Give this thread the highest scheduling priority possible, - in the hopes that it will immediately run after the VBL delay - */ - { - pthread_t current_thread; - int policy; - struct sched_param param; - - current_thread = pthread_self (); - pthread_getschedparam (current_thread, &policy, ¶m); - policy = SCHED_RR; - param.sched_priority = sched_get_priority_max (policy); - pthread_setschedparam (current_thread, policy, ¶m); - } - - while (1) { - - SDL_SemWait (sem1); - if (quit_thread) - return 0; - - /* - * We have to add SDL_VideoSurface->offset here, since we might be a - * smaller surface in the center of the framebuffer (you asked for - * a fullscreen resolution smaller than the hardware could supply - * so SDL is centering it in a bigger resolution)... - */ - dst = (Uint8 *)CGDisplayBaseAddress (display_id) + SDL_VideoSurface->offset; - src = current_buffer + SDL_VideoSurface->offset; - len = SDL_VideoSurface->w * SDL_VideoSurface->format->BytesPerPixel; - h = SDL_VideoSurface->h; - skip = SDL_VideoSurface->pitch; - - /* Wait for the VBL to occur (estimated since we don't have a hardware interrupt) */ - { - - /* The VBL delay is based on Ian Ollmann's RezLib <iano@cco.caltech.edu> */ - double refreshRate; - double linesPerSecond; - double target; - double position; - double adjustment; - AbsoluteTime nextTime; - CFNumberRef refreshRateCFNumber; - - refreshRateCFNumber = CFDictionaryGetValue (mode, kCGDisplayRefreshRate); - if ( NULL == refreshRateCFNumber ) { - SDL_SetError ("Mode has no refresh rate"); - goto ERROR; - } - - if ( 0 == CFNumberGetValue (refreshRateCFNumber, kCFNumberDoubleType, &refreshRate) ) { - SDL_SetError ("Error getting refresh rate"); - goto ERROR; - } - - if ( 0 == refreshRate ) { - - SDL_SetError ("Display has no refresh rate, using 60hz"); - - /* ok, for LCD's we'll emulate a 60hz refresh, which may or may not look right */ - refreshRate = 60.0; - } - - linesPerSecond = refreshRate * h; - target = h; - - /* Figure out the first delay so we start off about right */ - position = CGDisplayBeamPosition (display_id); - if (position > target) - position = 0; - - adjustment = (target - position) / linesPerSecond; - - nextTime = AddAbsoluteToAbsolute (UpTime (), QZ_SecondsToAbsolute (adjustment)); - - MPDelayUntil (&nextTime); - } - - - /* On error, skip VBL delay */ - ERROR: - - while ( h-- ) { - - SDL_memcpy (dst, src, len); - src += skip; - dst += skip; - } - - /* signal flip completion */ - SDL_SemPost (sem2); - } - - return 0; -} - -static int QZ_FlipDoubleBuffer (_THIS, SDL_Surface *surface) { - - /* wait for previous flip to complete */ - SDL_SemWait (sem2); - - current_buffer = surface->pixels; - - if (surface->pixels == sw_buffers[0]) - surface->pixels = sw_buffers[1]; - else - surface->pixels = sw_buffers[0]; - - /* signal worker thread to do the flip */ - SDL_SemPost (sem1); - - return 0; -} - - -static void QZ_DoubleBufferUpdate (_THIS, int num_rects, SDL_Rect *rects) { - - /* perform a flip if someone calls updaterects on a doublebuferred surface */ - this->FlipHWSurface (this, SDL_VideoSurface); -} - -static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) { -#pragma unused(this,num_rects,rects) -} - -/* - The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com, - who supplied sample code for Carbon. -*/ - -/*#define TEST_OBSCURED 1*/ - -#if TEST_OBSCURED -#include "CGS.h" -#endif - -static int QZ_IsWindowObscured (NSWindow *window) { - - -#if TEST_OBSCURED - - /* - In order to determine if a direct copy to the screen is possible, - we must figure out if there are any windows covering ours (including shadows). - This can be done by querying the window server about the on screen - windows for their screen rectangle and window level. - The procedure used below is puts accuracy before speed; however, it aims to call - the window server the fewest number of times possible to keep things reasonable. - In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW - - Notes: - -Calls into the Window Server involve IPC which is slow. - -Getting a rectangle seems slower than getting the window level - -The window list we get back is in sorted order, top to bottom - -On average, I suspect, most windows above ours are dock icon windows (hence optimization) - -Some windows above ours are always there, and cannot move or obscure us (menu bar) - - Bugs: - -no way (yet) to deactivate direct drawing when a window is dragged, - or suddenly obscured, so drawing continues and can produce garbage - We need some kind of locking mechanism on window movement to prevent this - - -deactivated normal windows use activated normal - window shadows (slight inaccuraccy) - */ - - /* Cache the connection to the window server */ - static CGSConnectionID cgsConnection = (CGSConnectionID) -1; - - /* Cache the dock icon windows */ - static CGSWindowID dockIcons[kMaxWindows]; - static int numCachedDockIcons = 0; - - CGSWindowID windows[kMaxWindows]; - CGSWindowCount i, count; - CGSWindowLevel winLevel; - CGSRect winRect; - - CGSRect contentRect; - int windowNumber; - int firstDockIcon; - int dockIconCacheMiss; - int windowContentOffset; - - int obscured = SDL_TRUE; - - if ( [ window isVisible ] ) { - - /* - walk the window list looking for windows over top of - (or casting a shadow on) ours - */ - - /* - Get a connection to the window server - Should probably be moved out into SetVideoMode() or InitVideo() - */ - if (cgsConnection == (CGSConnectionID) -1) { - cgsConnection = (CGSConnectionID) 0; - cgsConnection = _CGSDefaultConnection (); - } - - if (cgsConnection) { - - if ( ! [ window styleMask ] & NSBorderlessWindowMask ) - windowContentOffset = 22; - else - windowContentOffset = 0; - - windowNumber = [ window windowNumber ]; - - /* The window list is sorted according to order on the screen */ - count = 0; - CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count); - CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect); - - /* adjust rect for window title bar (if present) */ - contentRect.origin.y += windowContentOffset; - contentRect.size.height -= windowContentOffset; - - firstDockIcon = -1; - dockIconCacheMiss = SDL_FALSE; - - /* - The first window is always an empty window with level kCGSWindowLevelTop - so start at index 1 - */ - for (i = 1; i < count; i++) { - - /* If we reach our window in the list, it cannot be obscured */ - if (windows[i] == windowNumber) { - - obscured = SDL_FALSE; - break; - } - else { - - float shadowSide; - float shadowTop; - float shadowBottom; - - CGSGetWindowLevel (cgsConnection, windows[i], &winLevel); - - if (winLevel == kCGSWindowLevelDockIcon) { - - int j; - - if (firstDockIcon < 0) { - - firstDockIcon = i; - - if (numCachedDockIcons > 0) { - - for (j = 0; j < numCachedDockIcons; j++) { - - if (windows[i] == dockIcons[j]) - i++; - else - break; - } - - if (j != 0) { - - i--; - - if (j < numCachedDockIcons) { - - dockIconCacheMiss = SDL_TRUE; - } - } - - } - } - - continue; - } - else if (winLevel == kCGSWindowLevelMenuIgnore - /* winLevel == kCGSWindowLevelTop */) { - - continue; /* cannot obscure window */ - } - else if (winLevel == kCGSWindowLevelDockMenu || - winLevel == kCGSWindowLevelMenu) { - - shadowSide = 18; - shadowTop = 4; - shadowBottom = 22; - } - else if (winLevel == kCGSWindowLevelUtility) { - - shadowSide = 8; - shadowTop = 4; - shadowBottom = 12; - } - else if (winLevel == kCGSWindowLevelNormal) { - - /* - These numbers are for foreground windows, - they are too big (but will work) for background windows - */ - shadowSide = 20; - shadowTop = 10; - shadowBottom = 24; - } - else if (winLevel == kCGSWindowLevelDock) { - - /* Create dock icon cache */ - if (numCachedDockIcons != (i-firstDockIcon) || - dockIconCacheMiss) { - - numCachedDockIcons = i - firstDockIcon; - SDL_memcpy (dockIcons, &(windows[firstDockIcon]), - numCachedDockIcons * sizeof(*windows)); - } - - /* no shadow */ - shadowSide = 0; - shadowTop = 0; - shadowBottom = 0; - } - else { - - /* - kCGSWindowLevelDockLabel, - kCGSWindowLevelDock, - kOther??? - */ - - /* no shadow */ - shadowSide = 0; - shadowTop = 0; - shadowBottom = 0; - } - - CGSGetScreenRectForWindow (cgsConnection, windows[i], &winRect); - - winRect.origin.x -= shadowSide; - winRect.origin.y -= shadowTop; - winRect.size.width += shadowSide; - winRect.size.height += shadowBottom; - - if (NSIntersectsRect (contentRect, winRect)) { - - obscured = SDL_TRUE; - break; - } - - } /* window was not our window */ - - } /* iterate over windows */ - - } /* get cgsConnection */ - - } /* window is visible */ - - return obscured; -#else - return SDL_TRUE; -#endif -} - - -/* Locking functions for the software window buffer */ -static int QZ_LockWindow (_THIS, SDL_Surface *surface) { -#if 1 - return LockPortBits( [ window_view qdPort ] ); -#else - CGrafPtr qdport = [ window_view qdPort ]; - int result = LockPortBits ( qdport ); - - if ( !result ) { - Uint8* pixels = GetPixBaseAddr ( GetPortPixMap ( qdport ) ); - NSRect viewFrame = [ window_view frame ]; - NSRect winFrame = [ qz_window frame ]; - int vOffset = winFrame.size.height - viewFrame.size.height - viewFrame.origin.y; - int hOffset = viewFrame.origin.x; - - pixels = pixels + (vOffset * surface->pitch) + hOffset *4; - - if ( surface->pixels != pixels ) { - fprintf(stderr,"XXX: surface->pixels is %p, should be %p\n", surface->pixels, pixels); - } - } else { - fprintf(stderr, "XXX: could not lock port %p for surface %p\n", qdport, surface); - } - return result; -#endif -} - -static void QZ_UnlockWindow (_THIS, SDL_Surface *surface) { - - UnlockPortBits ( [ window_view qdPort ] ); -} - -/* Resize icon, BMP format */ -static const unsigned char QZ_ResizeIcon[] = { - 0x42,0x4d,0x31,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x00,0x00,0x00,0x28,0x00, - 0x00,0x00,0x0d,0x00,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x18,0x00,0x00,0x00, - 0x00,0x00,0xfb,0x01,0x00,0x00,0x13,0x0b,0x00,0x00,0x13,0x0b,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda, - 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, - 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xda,0xda,0xda,0x87, - 0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8, - 0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd5,0xd5,0xd5,0x87,0x87,0x87,0xe8,0xe8,0xe8, - 0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda, - 0xda,0xda,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda, - 0xda,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7, - 0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xda,0xda,0xda,0x87,0x87,0x87,0xe8, - 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xd7,0xd7,0xd7,0x87,0x87,0x87,0xe8,0xe8, - 0xe8,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xd9,0xd9,0xd9,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xdc, - 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb, - 0xdb,0x87,0x87,0x87,0xe8,0xe8,0xe8,0xff,0xff,0xff,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0xdb,0xdb,0x87,0x87,0x87,0xe8, - 0xe8,0xe8,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xdc,0xdc,0xdc,0x87,0x87,0x87,0xff,0xff,0xff,0x0b,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdc, - 0xdc,0xdc,0xff,0xff,0xff,0x0b,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff, - 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0b -}; - -static void QZ_DrawResizeIcon (_THIS, RgnHandle dirtyRegion) { - - /* Check if we should draw the resize icon */ - if (SDL_VideoSurface->flags & SDL_RESIZABLE) { - - Rect icon; - SetRect (&icon, SDL_VideoSurface->w - 13, SDL_VideoSurface->h - 13, - SDL_VideoSurface->w, SDL_VideoSurface->h); - - if (RectInRgn (&icon, dirtyRegion)) { - - SDL_Rect icon_rect; - - /* Create the icon image */ - if (resize_icon == NULL) { - - SDL_RWops *rw; - SDL_Surface *tmp; - - rw = SDL_RWFromConstMem (QZ_ResizeIcon, sizeof(QZ_ResizeIcon)); - tmp = SDL_LoadBMP_RW (rw, SDL_TRUE); - - resize_icon = SDL_ConvertSurface (tmp, SDL_VideoSurface->format, SDL_SRCCOLORKEY); - SDL_SetColorKey (resize_icon, SDL_SRCCOLORKEY, 0xFFFFFF); - - SDL_FreeSurface (tmp); - } - - icon_rect.x = SDL_VideoSurface->w - 13; - icon_rect.y = SDL_VideoSurface->h - 13; - icon_rect.w = 13; - icon_rect.h = 13; - - SDL_BlitSurface (resize_icon, NULL, SDL_VideoSurface, &icon_rect); - } - } -} - -static void QZ_UpdateRects (_THIS, int numRects, SDL_Rect *rects) { - - if (SDL_VideoSurface->flags & SDL_OPENGLBLIT) { - QZ_GL_SwapBuffers (this); - } - else if ( [ qz_window isMiniaturized ] ) { - - /* Do nothing if miniaturized */ - } - - else if ( ! QZ_IsWindowObscured (qz_window) ) { - - /* Use direct copy to flush contents to the display */ - CGrafPtr savePort; - CGrafPtr dstPort, srcPort; - const BitMap *dstBits, *srcBits; - Rect dstRect, srcRect; - Point offset; - int i; - - GetPort (&savePort); - - dstPort = CreateNewPortForCGDisplayID ((UInt32)display_id); - srcPort = [ window_view qdPort ]; - - offset.h = 0; - offset.v = 0; - SetPort (srcPort); - LocalToGlobal (&offset); - - SetPort (dstPort); - - LockPortBits (dstPort); - LockPortBits (srcPort); - - dstBits = GetPortBitMapForCopyBits (dstPort); - srcBits = GetPortBitMapForCopyBits (srcPort); - - for (i = 0; i < numRects; i++) { - - SetRect (&srcRect, rects[i].x, rects[i].y, - rects[i].x + rects[i].w, - rects[i].y + rects[i].h); - - SetRect (&dstRect, - rects[i].x + offset.h, - rects[i].y + offset.v, - rects[i].x + rects[i].w + offset.h, - rects[i].y + rects[i].h + offset.v); - - CopyBits (srcBits, dstBits, - &srcRect, &dstRect, srcCopy, NULL); - - } - - SetPort (savePort); - } - else { - /* Use QDFlushPortBuffer() to flush content to display */ - int i; - RgnHandle dirty = NewRgn (); - RgnHandle temp = NewRgn (); - - SetEmptyRgn (dirty); - - /* Build the region of dirty rectangles */ - for (i = 0; i < numRects; i++) { - - MacSetRectRgn (temp, rects[i].x, rects[i].y, - rects[i].x + rects[i].w, rects[i].y + rects[i].h); - MacUnionRgn (dirty, temp, dirty); - } - - QZ_DrawResizeIcon (this, dirty); - - /* Flush the dirty region */ - QDFlushPortBuffer ( [ window_view qdPort ], dirty ); - DisposeRgn (dirty); - DisposeRgn (temp); - } -} - -static void QZ_VideoQuit (_THIS) { - - CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken; - - /* Restore gamma settings */ - CGDisplayRestoreColorSyncSettings (); - - /* Ensure the cursor will be visible and working when we quit */ - CGDisplayShowCursor (display_id); - CGAssociateMouseAndMouseCursorPosition (1); - - if (mode_flags & SDL_FULLSCREEN) { - /* Fade to black to hide resolution-switching flicker (and garbage - that is displayed by a destroyed OpenGL context, if applicable) */ - if (CGAcquireDisplayFadeReservation (5, &fade_token) == kCGErrorSuccess) { - CGDisplayFade (fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE); - } - QZ_UnsetVideoMode (this, TRUE); - if (fade_token != kCGDisplayFadeReservationInvalidToken) { - CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE); - CGReleaseDisplayFadeReservation (fade_token); - } - } - else - QZ_UnsetVideoMode (this, TRUE); - - CGPaletteRelease (palette); - - if (opengl_library) { - SDL_UnloadObject(opengl_library); - opengl_library = NULL; - } - this->gl_config.driver_loaded = 0; - - if (field_edit) { - [field_edit release]; - field_edit = NULL; - } -} - -#if 0 /* Not used (apparently, it's really slow) */ -static int QZ_FillHWRect (_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color) { - - CGSDisplayHWFill (display_id, rect->x, rect->y, rect->w, rect->h, color); - - return 0; -} -#endif - -static int QZ_LockHWSurface(_THIS, SDL_Surface *surface) { - - return 1; -} - -static void QZ_UnlockHWSurface(_THIS, SDL_Surface *surface) { - -} - -static int QZ_AllocHWSurface(_THIS, SDL_Surface *surface) { - return(-1); /* unallowed (no HWSURFACE support here). */ -} - -static void QZ_FreeHWSurface (_THIS, SDL_Surface *surface) { -} - -/* - int QZ_FlipHWSurface (_THIS, SDL_Surface *surface) { - return 0; - } - */ - -/* Gamma functions */ -int QZ_SetGamma (_THIS, float red, float green, float blue) { - - const CGGammaValue min = 0.0, max = 1.0; - - if (red == 0.0) - red = FLT_MAX; - else - red = 1.0 / red; - - if (green == 0.0) - green = FLT_MAX; - else - green = 1.0 / green; - - if (blue == 0.0) - blue = FLT_MAX; - else - blue = 1.0 / blue; - - if ( CGDisplayNoErr == CGSetDisplayTransferByFormula - (display_id, min, max, red, min, max, green, min, max, blue) ) { - - return 0; - } - else { - - return -1; - } -} - -int QZ_GetGamma (_THIS, float *red, float *green, float *blue) { - - CGGammaValue dummy; - if ( CGDisplayNoErr == CGGetDisplayTransferByFormula - (display_id, &dummy, &dummy, red, - &dummy, &dummy, green, &dummy, &dummy, blue) ) - - return 0; - else - return -1; -} - -int QZ_SetGammaRamp (_THIS, Uint16 *ramp) { - - const CGTableCount tableSize = 255; - CGGammaValue redTable[tableSize]; - CGGammaValue greenTable[tableSize]; - CGGammaValue blueTable[tableSize]; - - int i; - - /* Extract gamma values into separate tables, convert to floats between 0.0 and 1.0 */ - for (i = 0; i < 256; i++) - redTable[i % 256] = ramp[i] / 65535.0; - - for (i=256; i < 512; i++) - greenTable[i % 256] = ramp[i] / 65535.0; - - for (i=512; i < 768; i++) - blueTable[i % 256] = ramp[i] / 65535.0; - - if ( CGDisplayNoErr == CGSetDisplayTransferByTable - (display_id, tableSize, redTable, greenTable, blueTable) ) - return 0; - else - return -1; -} - -int QZ_GetGammaRamp (_THIS, Uint16 *ramp) { - - const CGTableCount tableSize = 255; - CGGammaValue redTable[tableSize]; - CGGammaValue greenTable[tableSize]; - CGGammaValue blueTable[tableSize]; - CGTableCount actual; - int i; - - if ( CGDisplayNoErr != CGGetDisplayTransferByTable - (display_id, tableSize, redTable, greenTable, blueTable, &actual) || - actual != tableSize) - - return -1; - - /* Pack tables into one array, with values from 0 to 65535 */ - for (i = 0; i < 256; i++) - ramp[i] = redTable[i % 256] * 65535.0; - - for (i=256; i < 512; i++) - ramp[i] = greenTable[i % 256] * 65535.0; - - for (i=512; i < 768; i++) - ramp[i] = blueTable[i % 256] * 65535.0; - - return 0; -} - |