📄 sdl_quartzvideo.m
字号:
} /* 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; } } if ( QZ_WindowPosition(this, &origin_x, &origin_y) ) { center_window = 0; contentRect.origin.x = (float)origin_x; contentRect.origin.y = (float)origin_y; } /* 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 ];*/ /* no need to set this as it's the default for NSWindows */ QZ_SetCaption(this, this->wm_title, this->wm_icon); [ qz_window setAcceptsMouseMovedEvents:YES ]; [ qz_window setViewsNeedDisplay:NO ]; if ( center_window ) { [ qz_window center ]; } [ qz_window setDelegate: [ [ SDL_QuartzWindowDelegate alloc ] init ] ]; [ 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; /* 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 ]; } LockPortBits ( [ window_view qdPort ] ); current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) ); current->pitch = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) ); qdbpp = GetPixDepth ( GetPortPixMap ( [ window_view qdPort ] ) ); UnlockPortBits ( [ window_view 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 */ { int vOffset = [ qz_window frame ].size.height - [ window_view frame ].size.height - [ window_view frame ].origin.y; int hOffset = [ window_view frame ].origin.x; current->pixels = (Uint8 *)current->pixels + (vOffset * current->pitch) + hOffset * (qdbpp/8);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -