📄 sdl_quartzvideo.m
字号:
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 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_QuartzVideo.h"
/* Some variables to share among files, put in device structure eventually */
static SDL_GrabMode currentGrabMode = SDL_GRAB_OFF;
static BOOL inForeground = YES;
static char QZ_Error[255]; /* Global error buffer to temporarily store more informative error messages */
/* Include files into one compile unit...break apart eventually */
#include "SDL_QuartzWM.m"
#include "SDL_QuartzEvents.m"
#include "SDL_QuartzWindow.m"
/* 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*) malloc (sizeof (*device) );
hidden = (SDL_PrivateVideoData*) malloc (sizeof (*hidden) );
if (device == NULL || hidden == NULL)
SDL_OutOfMemory ();
memset (device, 0, sizeof (*device) );
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->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->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->free = QZ_DeleteDevice;
return device;
}
static void QZ_DeleteDevice (SDL_VideoDevice *device) {
free (device->hidden);
free (device);
}
static int QZ_VideoInit (_THIS, SDL_PixelFormat *video_format) {
/* 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 ();
/* 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);
video_format->BitsPerPixel = device_bpp;
return 0;
}
static SDL_Rect** QZ_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags) {
CFIndex num_modes;
CFIndex i;
static SDL_Rect **list = NULL;
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 ( list != NULL ) {
int i;
for (i = 0; list[i] != NULL; i++)
free (list[i]);
free (list);
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 (list[i]->w == width && 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 (list == NULL)
list = (SDL_Rect**) malloc (sizeof(*list) * (list_size+1) );
else
list = (SDL_Rect**) realloc (list, sizeof(*list) * (list_size+1));
rect = (SDL_Rect*) malloc (sizeof(**list));
if (list == NULL || rect == NULL) {
SDL_OutOfMemory ();
return NULL;
}
rect->w = width;
rect->h = height;
list[list_size-1] = rect;
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 = list[j]->w * list[j]->h;
area2 = list[j+1]->w * list[j+1]->h;
if (area1 < area2) {
SDL_Rect *tmp = list[j];
list[j] = list[j+1];
list[j+1] = tmp;
}
}
}
}
return list;
}
/* Gamma functions to try to hide the flash from a rez switch */
/* Fade the display from normal to black */
/* Save gamma tables for fade back to normal */
static UInt32 QZ_FadeGammaOut (_THIS, SDL_QuartzGammaTable *table) {
CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
greenTable[QZ_GAMMA_TABLE_SIZE],
blueTable[QZ_GAMMA_TABLE_SIZE];
float percent;
int j;
int actual;
if ( (CGDisplayNoErr != CGGetDisplayTransferByTable
(display_id, QZ_GAMMA_TABLE_SIZE,
table->red, table->green, table->blue, &actual)) ||
actual != QZ_GAMMA_TABLE_SIZE) {
return 1;
}
memcpy (redTable, table->red, sizeof(redTable));
memcpy (greenTable, table->green, sizeof(greenTable));
memcpy (blueTable, table->blue, sizeof(greenTable));
for (percent = 1.0; percent >= 0.0; percent -= 0.01) {
for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
redTable[j] = redTable[j] * percent;
greenTable[j] = greenTable[j] * percent;
blueTable[j] = blueTable[j] * percent;
}
if (CGDisplayNoErr != CGSetDisplayTransferByTable
(display_id, QZ_GAMMA_TABLE_SIZE,
redTable, greenTable, blueTable)) {
CGDisplayRestoreColorSyncSettings();
return 1;
}
SDL_Delay (10);
}
return 0;
}
/* Fade the display from black to normal */
/* Restore previously saved gamma values */
static UInt32 QZ_FadeGammaIn (_THIS, SDL_QuartzGammaTable *table) {
CGGammaValue redTable[QZ_GAMMA_TABLE_SIZE],
greenTable[QZ_GAMMA_TABLE_SIZE],
blueTable[QZ_GAMMA_TABLE_SIZE];
float percent;
int j;
memset (redTable, 0, sizeof(redTable));
memset (greenTable, 0, sizeof(greenTable));
memset (blueTable, 0, sizeof(greenTable));
for (percent = 0.0; percent <= 1.0; percent += 0.01) {
for (j = 0; j < QZ_GAMMA_TABLE_SIZE; j++) {
redTable[j] = table->red[j] * percent;
greenTable[j] = table->green[j] * percent;
blueTable[j] = table->blue[j] * percent;
}
if (CGDisplayNoErr != CGSetDisplayTransferByTable
(display_id, QZ_GAMMA_TABLE_SIZE,
redTable, greenTable, blueTable)) {
CGDisplayRestoreColorSyncSettings();
return 1;
}
SDL_Delay (10);
}
return 0;
}
static void QZ_UnsetVideoMode (_THIS) {
/* Reset values that may change between switches */
this->info.blit_fill = 0;
this->FillHWRect = NULL;
this->UpdateRects = NULL;
/* Release fullscreen resources */
if ( mode_flags & SDL_FULLSCREEN ) {
SDL_QuartzGammaTable gamma_table;
int gamma_error;
gamma_error = QZ_FadeGammaOut (this, &gamma_table);
/* Release the OpenGL context */
/* Do this first to avoid trash on the display before fade */
if ( mode_flags & SDL_OPENGL )
QZ_TearDownOpenGL (this);
if (mode_flags & SDL_OPENGL)
CGLSetFullScreen(NULL);
/* Restore original screen resolution/bpp */
CGDisplaySwitchToMode (display_id, save_mode);
CGDisplayRelease (display_id);
ShowMenuBar ();
if (! gamma_error)
QZ_FadeGammaIn (this, &gamma_table);
}
/* Release window mode resources */
else {
if ( (mode_flags & SDL_OPENGL) == 0 ) {
UnlockPortBits ( [ window_view qdPort ] );
[ window_view release ];
}
[ qz_window setContentView:nil ];
[ qz_window setDelegate:nil ];
[ qz_window close ];
[ qz_window release ];
/* Release the OpenGL context */
if ( mode_flags & SDL_OPENGL )
QZ_TearDownOpenGL (this);
}
/* Restore gamma settings */
CGDisplayRestoreColorSyncSettings ();
/* Set pixels to null (so other code doesn't try to free it) */
if (this->screen != NULL)
this->screen->pixels = NULL;
/* Ensure the cursor will be visible and working when we quit */
CGDisplayShowCursor (display_id);
CGAssociateMouseAndMouseCursorPosition (1);
/* Signal successful teardown */
video_set = SDL_FALSE;
}
static SDL_Surface* QZ_SetVideoFullScreen (_THIS, SDL_Surface *current, int width,
int height, int bpp, Uint32 flags) {
int exact_match;
int gamma_error;
SDL_QuartzGammaTable gamma_table;
/* 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 ) {
sprintf (QZ_Error, "Failed to find display resolution: %dx%dx%d", width, height, bpp);
SDL_SetError (QZ_Error);
goto ERR_NO_MATCH;
}
/* Fade display to zero gamma */
gamma_error = QZ_FadeGammaOut (this, &gamma_table);
/* Put up the blanking window (a window above all other windows) */
if ( CGDisplayNoErr != CGDisplayCapture (display_id) ) {
SDL_SetError ("Failed capturing display");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -