Implemented scRGB colorspace and HDR support on macOS
This commit is contained in:
@@ -156,6 +156,11 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
||||
selector:@selector(focusSomeWindow:)
|
||||
name:NSApplicationDidBecomeActiveNotification
|
||||
object:nil];
|
||||
|
||||
[center addObserver:self
|
||||
selector:@selector(screenParametersChanged:)
|
||||
name:NSApplicationDidChangeScreenParametersNotification
|
||||
object:nil];
|
||||
}
|
||||
|
||||
[center addObserver:self
|
||||
@@ -178,6 +183,7 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
||||
|
||||
[center removeObserver:self name:NSWindowWillCloseNotification object:nil];
|
||||
[center removeObserver:self name:NSApplicationDidBecomeActiveNotification object:nil];
|
||||
[center removeObserver:self name:NSApplicationDidChangeScreenParametersNotification object:nil];
|
||||
[center removeObserver:self name:NSCurrentLocaleDidChangeNotification object:nil];
|
||||
[NSApp removeObserver:self forKeyPath:@"effectiveAppearance"];
|
||||
|
||||
@@ -276,6 +282,11 @@ static void Cocoa_DispatchEvent(NSEvent *theEvent)
|
||||
}
|
||||
}
|
||||
|
||||
- (void)screenParametersChanged:(NSNotification *)aNotification
|
||||
{
|
||||
Cocoa_UpdateDisplays(SDL_GetVideoDevice());
|
||||
}
|
||||
|
||||
- (void)localeDidChange:(NSNotification *)notification
|
||||
{
|
||||
SDL_SendLocaleChangedEvent();
|
||||
|
||||
@@ -34,6 +34,7 @@ struct SDL_DisplayModeData
|
||||
};
|
||||
|
||||
extern void Cocoa_InitModes(SDL_VideoDevice *_this);
|
||||
extern void Cocoa_UpdateDisplays(SDL_VideoDevice *_this);
|
||||
extern int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
extern int Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect);
|
||||
extern int Cocoa_GetDisplayModes(SDL_VideoDevice *_this, SDL_VideoDisplay *display);
|
||||
|
||||
@@ -83,6 +83,20 @@ static int CG_SetError(const char *prefix, CGDisplayErr result)
|
||||
return SDL_SetError("%s: %s", prefix, error);
|
||||
}
|
||||
|
||||
static NSScreen *GetNSScreenForDisplayID(CGDirectDisplayID displayID)
|
||||
{
|
||||
NSArray *screens = [NSScreen screens];
|
||||
|
||||
/* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
|
||||
for (NSScreen *screen in screens) {
|
||||
const CGDirectDisplayID thisDisplay = (CGDirectDisplayID)[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
|
||||
if (thisDisplay == displayID) {
|
||||
return screen;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
static float GetDisplayModeRefreshRate(CGDisplayModeRef vidmode, CVDisplayLinkRef link)
|
||||
{
|
||||
double refreshRate = CGDisplayModeGetRefreshRate(vidmode);
|
||||
@@ -261,13 +275,13 @@ static SDL_bool GetDisplayMode(SDL_VideoDevice *_this, CGDisplayModeRef vidmode,
|
||||
return SDL_TRUE;
|
||||
}
|
||||
|
||||
static const char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
||||
static char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
||||
{
|
||||
/* This API is deprecated in 10.9 with no good replacement (as of 10.15). */
|
||||
io_service_t servicePort = CGDisplayIOServicePort(displayID);
|
||||
CFDictionaryRef deviceInfo = IODisplayCreateInfoDictionary(servicePort, kIODisplayOnlyPreferredName);
|
||||
NSDictionary *localizedNames = [(__bridge NSDictionary *)deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]];
|
||||
const char *displayName = NULL;
|
||||
char *displayName = NULL;
|
||||
|
||||
if ([localizedNames count] > 0) {
|
||||
displayName = SDL_strdup([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]);
|
||||
@@ -276,6 +290,21 @@ static const char *Cocoa_GetDisplayName(CGDirectDisplayID displayID)
|
||||
return displayName;
|
||||
}
|
||||
|
||||
static void Cocoa_GetHDRProperties(CGDirectDisplayID displayID, SDL_HDRDisplayProperties *HDR)
|
||||
{
|
||||
HDR->enabled = SDL_FALSE;
|
||||
HDR->SDR_whitelevel = 0.0f;
|
||||
|
||||
if (@available(macOS 10.15, *)) {
|
||||
NSScreen *screen = GetNSScreenForDisplayID(displayID);
|
||||
|
||||
if (screen && screen.maximumPotentialExtendedDynamicRangeColorComponentValue > 1.0f) {
|
||||
HDR->enabled = SDL_TRUE;
|
||||
HDR->SDR_whitelevel = 80.0f; /* SDR content is always at scRGB 1.0 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_InitModes(SDL_VideoDevice *_this)
|
||||
{
|
||||
@autoreleasepool {
|
||||
@@ -337,8 +366,8 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
|
||||
CVDisplayLinkCreateWithCGDisplay(displays[i], &link);
|
||||
|
||||
SDL_zero(display);
|
||||
/* this returns a stddup'ed string */
|
||||
display.name = (char *)Cocoa_GetDisplayName(displays[i]);
|
||||
/* this returns a strdup'ed string */
|
||||
display.name = Cocoa_GetDisplayName(displays[i]);
|
||||
if (!GetDisplayMode(_this, moderef, SDL_TRUE, NULL, link, &mode)) {
|
||||
CVDisplayLinkRelease(link);
|
||||
CGDisplayModeRelease(moderef);
|
||||
@@ -350,6 +379,8 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
|
||||
CVDisplayLinkRelease(link);
|
||||
CGDisplayModeRelease(moderef);
|
||||
|
||||
Cocoa_GetHDRProperties(displaydata->display, &display.HDR);
|
||||
|
||||
display.desktop_mode = mode;
|
||||
display.driverdata = displaydata;
|
||||
SDL_AddVideoDisplay(&display, SDL_FALSE);
|
||||
@@ -360,6 +391,20 @@ void Cocoa_InitModes(SDL_VideoDevice *_this)
|
||||
}
|
||||
}
|
||||
|
||||
void Cocoa_UpdateDisplays(SDL_VideoDevice *_this)
|
||||
{
|
||||
SDL_HDRDisplayProperties HDR;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < _this->num_displays; ++i) {
|
||||
SDL_VideoDisplay *display = _this->displays[i];
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
|
||||
Cocoa_GetHDRProperties(displaydata->display, &HDR);
|
||||
SDL_SetDisplayHDRProperties(display, &HDR);
|
||||
}
|
||||
}
|
||||
|
||||
int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
@@ -376,22 +421,10 @@ int Cocoa_GetDisplayBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SD
|
||||
int Cocoa_GetDisplayUsableBounds(SDL_VideoDevice *_this, SDL_VideoDisplay *display, SDL_Rect *rect)
|
||||
{
|
||||
SDL_DisplayData *displaydata = (SDL_DisplayData *)display->driverdata;
|
||||
const CGDirectDisplayID cgdisplay = displaydata->display;
|
||||
NSArray *screens = [NSScreen screens];
|
||||
NSScreen *screen = nil;
|
||||
NSScreen *screen = GetNSScreenForDisplayID(displaydata->display);
|
||||
|
||||
/* !!! FIXME: maybe track the NSScreen in SDL_DisplayData? */
|
||||
for (NSScreen *i in screens) {
|
||||
const CGDirectDisplayID thisDisplay = (CGDirectDisplayID)[[[i deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue];
|
||||
if (thisDisplay == cgdisplay) {
|
||||
screen = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(screen != nil); /* didn't find it?! */
|
||||
if (screen == nil) {
|
||||
return -1;
|
||||
return SDL_SetError("Couldn't get NSScreen for display");
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
@@ -242,6 +242,15 @@ int UIKit_AddDisplay(UIScreen *uiscreen, SDL_bool send_event)
|
||||
}
|
||||
display.desktop_mode = mode;
|
||||
|
||||
#ifndef SDL_PLATFORM_TVOS
|
||||
if (@available(iOS 16.0, *)) {
|
||||
if (uiscreen.potentialEDRHeadroom > 1.0f) {
|
||||
display.HDR.enabled = SDL_TRUE;
|
||||
display.HDR.SDR_whitelevel = 80.0f; /* SDR content is always at scRGB 1.0 */
|
||||
}
|
||||
}
|
||||
#endif /* !SDL_PLATFORM_TVOS */
|
||||
|
||||
/* Allocate the display data */
|
||||
#ifdef SDL_PLATFORM_VISIONOS
|
||||
SDL_UIKitDisplayData *data = [[SDL_UIKitDisplayData alloc] init];
|
||||
@@ -273,13 +282,13 @@ int UIKit_AddDisplay(SDL_bool send_event){
|
||||
mode.pixel_density = 1;
|
||||
mode.format = SDL_PIXELFORMAT_ABGR8888;
|
||||
mode.refresh_rate = 60;
|
||||
|
||||
|
||||
display.natural_orientation = SDL_ORIENTATION_LANDSCAPE;
|
||||
|
||||
display.desktop_mode = mode;
|
||||
|
||||
|
||||
SDL_UIKitDisplayData *data = [[SDL_UIKitDisplayData alloc] init];
|
||||
|
||||
|
||||
if (!data) {
|
||||
UIKit_FreeDisplayModeData(&display.desktop_mode);
|
||||
return SDL_OutOfMemory();
|
||||
@@ -341,7 +350,7 @@ int UIKit_InitModes(SDL_VideoDevice *_this)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(SDL_PLATFORM_TVOS) && !defined(SDL_PLATFORM_VISIONOS)
|
||||
SDL_OnApplicationDidChangeStatusBarOrientation();
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user