macOS: fix colors appearing oversaturated on P3 displays.

The fix only applies to macOS 11+ when using OpenGL.
This commit is contained in:
slime
2022-09-30 15:17:46 -03:00
parent 60036d5dfe
commit 6173c1638d
4 changed files with 49 additions and 28 deletions
+8
View File
@@ -26,6 +26,8 @@
#include <string> #include <string>
typedef struct SDL_Window SDL_Window;
namespace love namespace love
{ {
namespace macos namespace macos
@@ -55,6 +57,12 @@ void requestAttention(bool continuous);
void setMetalLayerVSync(void *metallayer, bool vsync); void setMetalLayerVSync(void *metallayer, bool vsync);
bool getMetalLayerVSync(void *metallayer); bool getMetalLayerVSync(void *metallayer);
/**
* Explicitly sets the window's color space to be sRGB - which stops the OS
* from interpreting the backbuffer output as P3 on P3-capable displays.
**/
void setWindowSRGBColorSpace(SDL_Window *window);
} // macos } // macos
} // love } // love
+20 -3
View File
@@ -27,9 +27,11 @@
#import <QuartzCore/CAMetalLayer.h> #import <QuartzCore/CAMetalLayer.h>
#ifdef LOVE_MACOSX_SDL_DIRECT_INCLUDE #ifdef LOVE_MACOSX_SDL_DIRECT_INCLUDE
# include <SDL.h> #include <SDL.h>
#include <SDL_syswm.h>
#else #else
# include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_syswm.h>
#endif #endif
namespace love namespace love
@@ -112,7 +114,22 @@ bool getMetalLayerVSync(void *metallayer)
return true; return true;
} }
} // osx void setWindowSRGBColorSpace(SDL_Window *window)
{
@autoreleasepool
{
// This works on earlier macOS versions, but performance may be worse
// (at least, it was back when I tested in December 2016).
if (@available(macOS 11.0, *))
{
SDL_SysWMinfo info = {};
if (SDL_GetWindowWMInfo(window, &info))
info.info.cocoa.window.colorSpace = [NSColorSpace sRGBColorSpace];
}
}
}
} // macos
} // love } // love
#endif // LOVE_MACOS #endif // LOVE_MACOS
-6
View File
@@ -479,12 +479,6 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int
metalLayer.device = device; metalLayer.device = device;
metalLayer.pixelFormat = isGammaCorrect() ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm; metalLayer.pixelFormat = isGammaCorrect() ? MTLPixelFormatBGRA8Unorm_sRGB : MTLPixelFormatBGRA8Unorm;
// Explicitly turn off color matching, for now (eg don't make sRGB content
// appear correct on P3 displays). It looks better with color matching, but
// having it off matches the OpenGL backend and there's some cost to it.
// TODO: revisit this?
metalLayer.colorspace = nil;
// This is set to NO when there are pending screen captures. // This is set to NO when there are pending screen captures.
metalLayer.framebufferOnly = YES; metalLayer.framebufferOnly = YES;
+21 -19
View File
@@ -366,27 +366,29 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla
return false; return false;
} }
if (renderer == love::graphics::Renderer::RENDERER_OPENGL) { if (attribs != nullptr && renderer == love::graphics::Renderer::RENDERER_OPENGL)
if (attribs != nullptr) {
#ifdef LOVE_MACOS
love::macos::setWindowSRGBColorSpace(window);
#endif
glcontext = SDL_GL_CreateContext(window);
if (!glcontext)
contexterror = std::string(SDL_GetError());
// Make sure the context's version is at least what we requested.
if (glcontext && !checkGLVersion(*attribs, glversion))
{ {
glcontext = SDL_GL_CreateContext(window); SDL_GL_DeleteContext(glcontext);
glcontext = nullptr;
}
if (!glcontext) if (!glcontext)
contexterror = std::string(SDL_GetError()); {
SDL_DestroyWindow(window);
// Make sure the context's version is at least what we requested. window = nullptr;
if (glcontext && !checkGLVersion(*attribs, glversion)) return false;
{
SDL_GL_DeleteContext(glcontext);
glcontext = nullptr;
}
if (!glcontext)
{
SDL_DestroyWindow(window);
window = nullptr;
return false;
}
} }
} }