21 #include "../../SDL_internal.h"
23 #if SDL_VIDEO_DRIVER_COCOA
28 #include <IOKit/graphics/IOGraphicsLib.h>
31 #include <CoreVideo/CVBase.h>
32 #include <CoreVideo/CVDisplayLink.h>
35 #include <Carbon/Carbon.h>
38 #include <AvailabilityMacros.h>
40 #ifndef MAC_OS_X_VERSION_10_13
41 #define NSAppKitVersionNumber10_12 1504
46 Cocoa_ToggleMenuBar(
const BOOL show)
53 #if (MAC_OS_X_VERSION_MIN_REQUIRED < 1070) && !defined(__LP64__)
63 CG_SetError(
const char *prefix, CGDisplayErr
result)
69 error =
"kCGErrorFailure";
71 case kCGErrorIllegalArgument:
72 error =
"kCGErrorIllegalArgument";
74 case kCGErrorInvalidConnection:
75 error =
"kCGErrorInvalidConnection";
77 case kCGErrorInvalidContext:
78 error =
"kCGErrorInvalidContext";
80 case kCGErrorCannotComplete:
81 error =
"kCGErrorCannotComplete";
83 case kCGErrorNotImplemented:
84 error =
"kCGErrorNotImplemented";
86 case kCGErrorRangeCheck:
87 error =
"kCGErrorRangeCheck";
89 case kCGErrorTypeCheck:
90 error =
"kCGErrorTypeCheck";
92 case kCGErrorInvalidOperation:
93 error =
"kCGErrorInvalidOperation";
95 case kCGErrorNoneAvailable:
96 error =
"kCGErrorNoneAvailable";
99 error =
"Unknown Error";
106 GetDisplayModeRefreshRate(CGDisplayModeRef vidmode, CVDisplayLinkRef link)
108 int refreshRate = (
int) (CGDisplayModeGetRefreshRate(vidmode) + 0.5);
111 if (refreshRate == 0 && link !=
NULL) {
112 CVTime
time = CVDisplayLinkGetNominalOutputVideoRefreshPeriod(link);
113 if ((
time.flags & kCVTimeIsIndefinite) == 0 &&
time.timeValue != 0) {
114 refreshRate = (
int) ((
time.timeScale / (
double)
time.timeValue) + 0.5);
122 HasValidDisplayModeFlags(CGDisplayModeRef vidmode)
124 uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
127 if (ioflags & (kDisplayModeNeverShowFlag | kDisplayModeNotGraphicsQualityFlag)) {
132 if (!(ioflags & kDisplayModeValidFlag) || !(ioflags & kDisplayModeSafeFlag)) {
140 GetDisplayModePixelFormat(CGDisplayModeRef vidmode)
143 CFStringRef fmt = CGDisplayModeCopyPixelEncoding(vidmode);
146 if (CFStringCompare(fmt, CFSTR(IO32BitDirectPixels),
147 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
149 }
else if (CFStringCompare(fmt, CFSTR(IO16BitDirectPixels),
150 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
152 }
else if (CFStringCompare(fmt, CFSTR(kIO30BitDirectPixels),
153 kCFCompareCaseInsensitive) == kCFCompareEqualTo) {
168 bool usableForGUI = CGDisplayModeIsUsableForDesktopGUI(vidmode);
169 int width = (
int) CGDisplayModeGetWidth(vidmode);
170 int height = (
int) CGDisplayModeGetHeight(vidmode);
171 uint32_t ioflags = CGDisplayModeGetIOFlags(vidmode);
172 int refreshrate = GetDisplayModeRefreshRate(vidmode, link);
174 bool interlaced = (ioflags & kDisplayModeInterlacedFlag) != 0;
175 CFMutableArrayRef modes;
181 if (!HasValidDisplayModeFlags(vidmode)) {
185 modes = CFArrayCreateMutable(
NULL, 0, &kCFTypeArrayCallBacks);
186 CFArrayAppendValue(modes, vidmode);
194 #ifdef MAC_OS_X_VERSION_10_8
195 if (modelist !=
NULL &&
floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
196 int pixelW = (
int) CGDisplayModeGetPixelWidth(vidmode);
197 int pixelH = (
int) CGDisplayModeGetPixelHeight(vidmode);
199 CFIndex modescount = CFArrayGetCount(modelist);
202 for (
i = 0;
i < modescount;
i++) {
203 CGDisplayModeRef othermode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modelist,
i);
204 uint32_t otherioflags = CGDisplayModeGetIOFlags(othermode);
206 if (CFEqual(vidmode, othermode)) {
210 if (!HasValidDisplayModeFlags(othermode)) {
214 int otherW = (
int) CGDisplayModeGetWidth(othermode);
215 int otherH = (
int) CGDisplayModeGetHeight(othermode);
216 int otherpixelW = (
int) CGDisplayModeGetPixelWidth(othermode);
217 int otherpixelH = (
int) CGDisplayModeGetPixelHeight(othermode);
218 int otherrefresh = GetDisplayModeRefreshRate(othermode, link);
219 Uint32 otherformat = GetDisplayModePixelFormat(othermode);
220 bool otherGUI = CGDisplayModeIsUsableForDesktopGUI(othermode);
227 && refreshrate == otherrefresh &&
format == otherformat
228 && (otherpixelW != otherW || otherpixelH != otherH)) {
236 if (interlaced && ((otherioflags & kDisplayModeInterlacedFlag) == 0)
237 &&
width == otherW &&
height == otherH && pixelW == otherpixelW
238 && pixelH == otherpixelH && refreshrate == otherrefresh
239 &&
format == otherformat && usableForGUI == otherGUI) {
247 if (
width == otherW &&
height == otherH && pixelW == otherpixelW
248 && pixelH == otherpixelH && !usableForGUI && otherGUI
249 && refreshrate == otherrefresh &&
format == otherformat) {
275 if (
width == otherW &&
height == otherH && pixelW == otherpixelW
276 && pixelH == otherpixelH && usableForGUI == otherGUI
277 && refreshrate == otherrefresh &&
format == otherformat) {
278 CFArrayAppendValue(modes, othermode);
293 mode->refresh_rate = refreshrate;
299 Cocoa_GetDisplayName(CGDirectDisplayID displayID)
302 io_service_t servicePort = CGDisplayIOServicePort(displayID);
303 CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
304 NSDictionary *localizedNames = [(NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
305 const char* displayName =
NULL;
307 if ([localizedNames
count] > 0) {
308 displayName =
SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
310 CFRelease(deviceInfo);
319 CGDirectDisplayID *displays;
320 CGDisplayCount numDisplays;
324 result = CGGetOnlineDisplayList(0,
NULL, &numDisplays);
325 if (
result != kCGErrorSuccess) {
326 CG_SetError(
"CGGetOnlineDisplayList()",
result);
330 result = CGGetOnlineDisplayList(numDisplays, displays, &numDisplays);
331 if (
result != kCGErrorSuccess) {
332 CG_SetError(
"CGGetOnlineDisplayList()",
result);
338 for (pass = 0; pass < 2; ++pass) {
339 for (
i = 0;
i < numDisplays; ++
i) {
343 CGDisplayModeRef moderef =
NULL;
344 CVDisplayLinkRef link =
NULL;
347 if (!CGDisplayIsMain(displays[
i])) {
351 if (CGDisplayIsMain(displays[
i])) {
356 if (CGDisplayMirrorsDisplay(displays[
i]) != kCGNullDirectDisplay) {
360 moderef = CGDisplayCopyDisplayMode(displays[
i]);
368 CGDisplayModeRelease(moderef);
371 displaydata->
display = displays[i];
373 CVDisplayLinkCreateWithCGDisplay(displays[
i], &link);
377 display.
name = (
char *)Cocoa_GetDisplayName(displays[
i]);
379 CVDisplayLinkRelease(link);
380 CGDisplayModeRelease(moderef);
386 CVDisplayLinkRelease(link);
387 CGDisplayModeRelease(moderef);
405 cgrect = CGDisplayBounds(displaydata->
display);
407 rect->
y = (
int)cgrect.origin.y;
409 rect->
h = (
int)cgrect.size.height;
417 const CGDirectDisplayID cgdisplay = displaydata->
display;
418 NSArray *screens = [NSScreen screens];
422 for (NSScreen *
i in screens) {
423 const CGDirectDisplayID thisDisplay = (CGDirectDisplayID) [[[
i deviceDescription] objectForKey:
@"NSScreenNumber"] unsignedIntValue];
424 if (thisDisplay == cgdisplay) {
435 const NSRect
frame = [screen visibleFrame];
448 const float MM_IN_INCH = 25.4f;
453 CGFloat scaleFactor = 1.0f;
454 NSArray *screens = [NSScreen screens];
456 const CGDirectDisplayID dpyid = (
const CGDirectDisplayID ) [[[
screen deviceDescription] objectForKey:
@"NSScreenNumber"] unsignedIntValue];
457 if (dpyid ==
data->display) {
458 if ([
screen respondsToSelector:
@selector(backingScaleFactor)]) {
459 scaleFactor = [screen backingScaleFactor];
465 const CGSize displaySize = CGDisplayScreenSize(
data->display);
466 const int pixelWidth = (
int) CGDisplayPixelsWide(
data->display);
467 const int pixelHeight = (
int) CGDisplayPixelsHigh(
data->display);
470 *ddpi = (
SDL_ComputeDiagonalDPI(pixelWidth, pixelHeight, displaySize.width / MM_IN_INCH, displaySize.height / MM_IN_INCH)) * scaleFactor;
473 *hdpi = (pixelWidth * MM_IN_INCH / displaySize.width) * scaleFactor;
476 *vdpi = (pixelHeight * MM_IN_INCH / displaySize.height) * scaleFactor;
486 CVDisplayLinkRef link =
NULL;
487 CGDisplayModeRef desktopmoderef;
490 CFDictionaryRef dict =
NULL;
492 CVDisplayLinkCreateWithCGDisplay(
data->display, &link);
494 desktopmoderef = CGDisplayCopyDisplayMode(
data->display);
502 if (desktopmoderef && GetDisplayMode(
_this, desktopmoderef,
NULL, link, &desktopmode)) {
509 CGDisplayModeRelease(desktopmoderef);
522 #ifdef MAC_OS_X_VERSION_10_8
523 if (
floor(NSAppKitVersionNumber) > NSAppKitVersionNumber10_7) {
524 const CFStringRef dictkeys[] = {kCGDisplayShowDuplicateLowResolutionModes};
525 const CFBooleanRef dictvalues[] = {kCFBooleanTrue};
526 dict = CFDictionaryCreate(
NULL,
527 (
const void **)dictkeys,
528 (
const void **)dictvalues,
530 &kCFCopyStringDictionaryKeyCallBacks,
531 &kCFTypeDictionaryValueCallBacks);
535 modes = CGDisplayCopyAllDisplayModes(
data->display, dict);
543 const CFIndex
count = CFArrayGetCount(modes);
546 CGDisplayModeRef moderef = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes,
i);
549 if (GetDisplayMode(
_this, moderef, modes, link, &
mode)) {
560 CVDisplayLinkRelease(link);
569 CGError
result = kCGErrorFailure;
570 for (CFIndex
i = 0;
i < CFArrayGetCount(
data->modes);
i++) {
571 CGDisplayModeRef moderef = (CGDisplayModeRef)CFArrayGetValueAtIndex(
data->modes,
i);
572 result = CGDisplaySetDisplayMode(display, moderef,
NULL);
573 if (
result == kCGErrorSuccess) {
575 CFArrayExchangeValuesAtIndices(
data->modes,
i, 0);
587 CGDisplayFadeReservationToken fade_token = kCGDisplayFadeReservationInvalidToken;
591 if (CGAcquireDisplayFadeReservation(5, &fade_token) == kCGErrorSuccess) {
592 CGDisplayFade(fade_token, 0.3, kCGDisplayBlendNormal, kCGDisplayBlendSolidColor, 0.0, 0.0, 0.0,
TRUE);
597 SetDisplayModeForDisplay(displaydata->
display,
data);
599 if (CGDisplayIsMain(displaydata->
display)) {
600 CGReleaseAllDisplays();
602 CGDisplayRelease(displaydata->
display);
605 if (CGDisplayIsMain(displaydata->
display)) {
606 Cocoa_ToggleMenuBar(YES);
610 if (CGDisplayIsMain(displaydata->
display)) {
612 result = CGCaptureAllDisplays();
616 if (
result != kCGErrorSuccess) {
617 CG_SetError(
"CGDisplayCapture()",
result);
623 if (
result != kCGErrorSuccess) {
624 CG_SetError(
"CGDisplaySwitchToMode()",
result);
629 if (CGDisplayIsMain(displaydata->
display)) {
630 Cocoa_ToggleMenuBar(NO);
635 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
636 CGDisplayFade(fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0,
FALSE);
637 CGReleaseDisplayFadeReservation(fade_token);
644 if (CGDisplayIsMain(displaydata->
display)) {
645 CGReleaseAllDisplays();
647 CGDisplayRelease(displaydata->
display);
650 if (fade_token != kCGDisplayFadeReservationInvalidToken) {
651 CGDisplayFade (fade_token, 0.5, kCGDisplayBlendSolidColor, kCGDisplayBlendNormal, 0.0, 0.0, 0.0,
FALSE);
652 CGReleaseDisplayFadeReservation(fade_token);
667 Cocoa_SetDisplayMode(_this, display, &display->desktop_mode);
671 CFRelease(
mode->modes);
675 CFRelease(
mode->modes);
678 Cocoa_ToggleMenuBar(YES);
#define SDL_assert(condition)
void Cocoa_QuitModes(_THIS)
int Cocoa_GetDisplayDPI(_THIS, SDL_VideoDisplay *display, float *ddpi, float *hpdi, float *vdpi)
int Cocoa_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
int Cocoa_GetDisplayUsableBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
void Cocoa_GetDisplayModes(_THIS, SDL_VideoDisplay *display)
void Cocoa_InitModes(_THIS)
int Cocoa_GetDisplayBounds(_THIS, SDL_VideoDisplay *display, SDL_Rect *rect)
#define SDL_small_alloc(type, count, pisstack)
#define SDL_small_free(ptr, isstack)
GLint GLint GLint GLint GLint GLint y
GLuint GLuint GLsizei count
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
GLint GLint GLsizei width
GLint GLint GLsizei GLsizei height
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
@ SDL_PIXELFORMAT_ARGB1555
@ SDL_PIXELFORMAT_ARGB8888
@ SDL_PIXELFORMAT_ARGB2101010
@ SDL_PIXELFORMAT_UNKNOWN
int SDL_AddVideoDisplay(const SDL_VideoDisplay *display, SDL_bool send_event)
float SDL_ComputeDiagonalDPI(int hpix, int vpix, float hinches, float vinches)
SDL_bool SDL_AddDisplayMode(SDL_VideoDisplay *display, const SDL_DisplayMode *mode)
static SDL_VideoDevice * _this
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int in i)
return Display return Display Bool Bool int int int return Display XEvent Bool(*) XPointer return Display return Display Drawable _Xconst char unsigned int unsigned int return Display Pixmap Pixmap XColor XColor unsigned int unsigned int return Display _Xconst char char int char return Display Visual unsigned int int int char unsigned int unsigned int int in j)
EGLSurface EGLnsecsANDROID time
CGDirectDisplayID display
The structure that defines a display mode.
A rectangle, with the origin at the upper left (integer).
SDL_VideoDisplay * displays
SDL_DisplayMode desktop_mode
SDL_DisplayMode * display_modes
SDL_DisplayMode current_mode
typedef int(__stdcall *FARPROC)()