diff --git a/src/common/macos.h b/src/common/macos.h index 5ac8e9e94..929de36fc 100644 --- a/src/common/macos.h +++ b/src/common/macos.h @@ -26,6 +26,8 @@ #include +typedef struct SDL_Window SDL_Window; + namespace love { namespace macos @@ -55,6 +57,12 @@ void requestAttention(bool continuous); void setMetalLayerVSync(void *metallayer, bool vsync); 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 } // love diff --git a/src/common/macos.mm b/src/common/macos.mm index 6a07c19c1..4cc7de5df 100644 --- a/src/common/macos.mm +++ b/src/common/macos.mm @@ -27,9 +27,11 @@ #import #ifdef LOVE_MACOSX_SDL_DIRECT_INCLUDE -# include +#include +#include #else -# include +#include +#include #endif namespace love @@ -112,7 +114,22 @@ bool getMetalLayerVSync(void *metallayer) 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 #endif // LOVE_MACOS diff --git a/src/modules/graphics/metal/Graphics.mm b/src/modules/graphics/metal/Graphics.mm index 5d2f42645..deb7e151e 100644 --- a/src/modules/graphics/metal/Graphics.mm +++ b/src/modules/graphics/metal/Graphics.mm @@ -479,12 +479,6 @@ bool Graphics::setMode(void *context, int width, int height, int pixelwidth, int metalLayer.device = device; 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. metalLayer.framebufferOnly = YES; diff --git a/src/modules/window/sdl/Window.cpp b/src/modules/window/sdl/Window.cpp index aca41006a..72dfacf72 100644 --- a/src/modules/window/sdl/Window.cpp +++ b/src/modules/window/sdl/Window.cpp @@ -366,27 +366,29 @@ bool Window::createWindowAndContext(int x, int y, int w, int h, Uint32 windowfla return false; } - if (renderer == love::graphics::Renderer::RENDERER_OPENGL) { - if (attribs != nullptr) + if (attribs != nullptr && renderer == love::graphics::Renderer::RENDERER_OPENGL) + { +#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) - contexterror = std::string(SDL_GetError()); - - // Make sure the context's version is at least what we requested. - if (glcontext && !checkGLVersion(*attribs, glversion)) - { - SDL_GL_DeleteContext(glcontext); - glcontext = nullptr; - } - - if (!glcontext) - { - SDL_DestroyWindow(window); - window = nullptr; - return false; - } + if (!glcontext) + { + SDL_DestroyWindow(window); + window = nullptr; + return false; } }