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
|
#ifndef _SDL_cocoamodes_h
|
||||||
#define _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_InitModes(_THIS);
|
||||||
extern void Cocoa_GetDisplayModes(_THIS);
|
extern void Cocoa_GetDisplayModes(_THIS);
|
||||||
extern int Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
|
extern int Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode);
|
||||||
|
|
|
@ -23,34 +23,237 @@
|
||||||
|
|
||||||
#include "SDL_cocoavideo.h"
|
#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
|
void
|
||||||
Cocoa_InitModes(_THIS)
|
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_DisplayMode mode;
|
||||||
|
|
||||||
SDL_zero(display);
|
if (GetDisplayMode(moderef, &mode)) {
|
||||||
SDL_zero(mode);
|
SDL_AddDisplayMode(_this->current_display, &mode);
|
||||||
display.desktop_mode = mode;
|
}
|
||||||
display.current_mode = mode;
|
|
||||||
SDL_AddVideoDisplay(&display);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Cocoa_GetDisplayModes(_THIS)
|
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
|
int
|
||||||
Cocoa_SetDisplayMode(_THIS, SDL_DisplayMode * mode)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Cocoa_QuitModes(_THIS)
|
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: */
|
/* vi: set ts=4 sw=4 expandtab: */
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#ifndef _SDL_cocoavideo_h
|
#ifndef _SDL_cocoavideo_h
|
||||||
#define _SDL_cocoavideo_h
|
#define _SDL_cocoavideo_h
|
||||||
|
|
||||||
|
#include <ApplicationServices/ApplicationServices.h>
|
||||||
#include <Cocoa/Cocoa.h>
|
#include <Cocoa/Cocoa.h>
|
||||||
|
|
||||||
#include "../SDL_sysvideo.h"
|
#include "../SDL_sysvideo.h"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue