Implemented Mac OS X video mode selection.
--HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401979
This commit is contained in:
parent
56c1ba8073
commit
1474493514
3 changed files with 220 additions and 6 deletions
|
@ -24,6 +24,16 @@
|
|||
#ifndef _SDL_cocoamodes_h
|
||||
#define _SDL_cocoamodes_h
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CGDirectDisplayID display;
|
||||
} SDL_DisplayData;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CFDictionaryRef moderef;
|
||||
} SDL_DisplayModeData;
|
||||
|
||||
extern void Cocoa_InitModes(_THIS);
|
||||
extern void Cocoa_GetDisplayModes(_THIS);
|
||||
extern int Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
|
||||
|
|
|
@ -23,34 +23,237 @@
|
|||
|
||||
#include "SDL_cocoavideo.h"
|
||||
|
||||
static void
|
||||
CG_SetError(const char *prefix, CGDisplayErr result)
|
||||
{
|
||||
const char *error;
|
||||
|
||||
switch (result) {
|
||||
case kCGErrorFailure:
|
||||
error = "kCGErrorFailure";
|
||||
break;
|
||||
case kCGErrorIllegalArgument:
|
||||
error = "kCGErrorIllegalArgument";
|
||||
break;
|
||||
case kCGErrorInvalidConnection:
|
||||
error = "kCGErrorInvalidConnection";
|
||||
break;
|
||||
case kCGErrorInvalidContext:
|
||||
error = "kCGErrorInvalidContext";
|
||||
break;
|
||||
case kCGErrorCannotComplete:
|
||||
error = "kCGErrorCannotComplete";
|
||||
break;
|
||||
case kCGErrorNameTooLong:
|
||||
error = "kCGErrorNameTooLong";
|
||||
break;
|
||||
case kCGErrorNotImplemented:
|
||||
error = "kCGErrorNotImplemented";
|
||||
break;
|
||||
case kCGErrorRangeCheck:
|
||||
error = "kCGErrorRangeCheck";
|
||||
break;
|
||||
case kCGErrorTypeCheck:
|
||||
error = "kCGErrorTypeCheck";
|
||||
break;
|
||||
case kCGErrorNoCurrentPoint:
|
||||
error = "kCGErrorNoCurrentPoint";
|
||||
break;
|
||||
case kCGErrorInvalidOperation:
|
||||
error = "kCGErrorInvalidOperation";
|
||||
break;
|
||||
case kCGErrorNoneAvailable:
|
||||
error = "kCGErrorNoneAvailable";
|
||||
break;
|
||||
default:
|
||||
error = "Unknown Error";
|
||||
break;
|
||||
}
|
||||
SDL_SetError("%s: %s", prefix, error);
|
||||
}
|
||||
|
||||
static SDL_bool
|
||||
GetDisplayMode(CFDictionaryRef moderef, SDL_DisplayMode *mode)
|
||||
{
|
||||
SDL_DisplayModeData *data;
|
||||
CFNumberRef number;
|
||||
long width, height, bpp, refreshRate;
|
||||
|
||||
data = (SDL_DisplayModeData *) SDL_malloc(sizeof(*data));
|
||||
if (!data) {
|
||||
return SDL_FALSE;
|
||||
}
|
||||
data->moderef = moderef;
|
||||
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayWidth);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &width);
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayHeight);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &height);
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayBitsPerPixel);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &bpp);
|
||||
number = CFDictionaryGetValue(moderef, kCGDisplayRefreshRate);
|
||||
CFNumberGetValue(number, kCFNumberLongType, &refreshRate);
|
||||
|
||||
mode->format = SDL_PixelFormat_Unknown;
|
||||
switch (bpp) {
|
||||
case 8:
|
||||
mode->format = SDL_PixelFormat_Index8;
|
||||
break;
|
||||
case 16:
|
||||
mode->format = SDL_PixelFormat_RGB555;
|
||||
break;
|
||||
case 32:
|
||||
mode->format = SDL_PixelFormat_RGB888;
|
||||
break;
|
||||
}
|
||||
mode->w = width;
|
||||
mode->h = height;
|
||||
mode->refresh_rate = refreshRate;
|
||||
mode->driverdata = data;
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_InitModes(_THIS)
|
||||
{
|
||||
SDL_VideoDisplay display;
|
||||
CGDisplayErr result;
|
||||
CGDirectDisplayID *displays;
|
||||
CGDisplayCount numDisplays;
|
||||
int i;
|
||||
|
||||
result = CGGetOnlineDisplayList(0, NULL, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
return;
|
||||
}
|
||||
displays = SDL_stack_alloc(CGDirectDisplayID, numDisplays);
|
||||
result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGGetOnlineDisplayList()", result);
|
||||
SDL_stack_free(displays);
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < numDisplays; ++i) {
|
||||
SDL_VideoDisplay display;
|
||||
SDL_DisplayData *displaydata;
|
||||
SDL_DisplayMode mode;
|
||||
CFDictionaryRef moderef;
|
||||
|
||||
if (CGDisplayIsInMirrorSet(displays[i])) {
|
||||
continue;
|
||||
}
|
||||
moderef = CGDisplayCurrentMode(displays[i]);
|
||||
if (!moderef) {
|
||||
continue;
|
||||
}
|
||||
|
||||
displaydata = (SDL_DisplayData *) SDL_malloc(sizeof(*displaydata));
|
||||
if (!displaydata) {
|
||||
continue;
|
||||
}
|
||||
displaydata->display = displays[i];
|
||||
|
||||
SDL_zero(display);
|
||||
if (!GetDisplayMode (moderef, &mode)) {
|
||||
SDL_free(displaydata);
|
||||
continue;
|
||||
}
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
AddDisplayMode(const void *moderef, void *context)
|
||||
{
|
||||
SDL_VideoDevice *_this = (SDL_VideoDevice *) context;
|
||||
SDL_DisplayMode mode;
|
||||
|
||||
SDL_zero(display);
|
||||
SDL_zero(mode);
|
||||
display.desktop_mode = mode;
|
||||
display.current_mode = mode;
|
||||
SDL_AddVideoDisplay(&display);
|
||||
if (GetDisplayMode(moderef, &mode)) {
|
||||
SDL_AddDisplayMode(_this->current_display, &mode);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_GetDisplayModes(_THIS)
|
||||
{
|
||||
SDL_DisplayData *data = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
|
||||
CFArrayRef modes;
|
||||
CFRange range;
|
||||
|
||||
modes = CGDisplayAvailableModes(data->display);
|
||||
if (!modes) {
|
||||
return;
|
||||
}
|
||||
range.location = 0;
|
||||
range.length = CFArrayGetCount(modes);
|
||||
CFArrayApplyFunction(modes, range, AddDisplayMode, _this);
|
||||
}
|
||||
|
||||
int
|
||||
Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *) SDL_CurrentDisplay.driverdata;
|
||||
SDL_DisplayModeData *data = (SDL_DisplayModeData *) mode->driverdata;
|
||||
CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
|
||||
CGError result;
|
||||
|
||||
/* Fade to black to hide resolution-switching flicker */
|
||||
if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
|
||||
CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0, TRUE);
|
||||
}
|
||||
|
||||
/* Put up the blanking window (a window above all other windows) */
|
||||
result = CGDisplayCapture(displaydata->display);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGDisplayCapture()", result);
|
||||
goto ERR_NO_CAPTURE;
|
||||
}
|
||||
|
||||
/* Do the physical switch */
|
||||
result = CGDisplaySwitchToMode(displaydata->display, data->moderef);
|
||||
if (result != kCGErrorSuccess) {
|
||||
CG_SetError("CGDisplaySwitchToMode()", result);
|
||||
goto ERR_NO_SWITCH;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
return 0;
|
||||
|
||||
/* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
|
||||
ERR_NO_SWITCH:
|
||||
CGDisplayRelease(displaydata->display);
|
||||
ERR_NO_CAPTURE:
|
||||
if (fade_token != kCGDisplayFadeReservationInvalidToken) {
|
||||
CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0, FALSE);
|
||||
CGReleaseDisplayFadeReservation(fade_token);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
Cocoa_QuitModes(_THIS)
|
||||
{
|
||||
int i, saved_display;
|
||||
|
||||
saved_display = _this->current_display;
|
||||
for (i = 0; i < _this->num_displays; ++i) {
|
||||
SDL_VideoDisplay *display = &_this->displays[i];
|
||||
|
||||
if (display->current_mode.driverdata != display->desktop_mode.driverdata) {
|
||||
_this->current_display = i;
|
||||
Cocoa_SetDisplayMode(_this, &display->desktop_mode);
|
||||
}
|
||||
}
|
||||
CGReleaseAllDisplays();
|
||||
_this->current_display = saved_display;
|
||||
}
|
||||
|
||||
/* vi: set ts=4 sw=4 expandtab: */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#ifndef _SDL_cocoavideo_h
|
||||
#define _SDL_cocoavideo_h
|
||||
|
||||
#include <ApplicationServices/ApplicationServices.h>
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
#include "../SDL_sysvideo.h"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue