diff --git a/glad/generate.py b/glad/generate.py index d05c30a60..0f752be89 100755 --- a/glad/generate.py +++ b/glad/generate.py @@ -10,7 +10,8 @@ cmdline = ( 'glad --out-path {dest} --api gl:core=3.1 ' - ' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_ARB_instanced_arrays,GL_KHR_debug ' + ' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,' + 'GL_ARB_instanced_arrays,GL_KHR_debug,GL_ARB_framebuffer_sRGB,GL_EXT_framebuffer_sRGB ' 'c --header-only --debug' ) diff --git a/kitty/child-monitor.c b/kitty/child-monitor.c index ac73ef177..f99d6a52f 100644 --- a/kitty/child-monitor.c +++ b/kitty/child-monitor.c @@ -709,8 +709,10 @@ prepare_to_render_os_window(OSWindow *os_window, monotonic_t now, unsigned int * #define TD os_window->tab_bar_render_data bool needs_render = os_window->needs_render; os_window->needs_render = false; - os_window->needs_layers = os_window->is_semi_transparent || os_window->live_resize.in_progress || ( - os_window->bgimage && os_window->bgimage->texture_id > 0); + os_window->needs_layers = ( + !global_state.supports_framebuffer_srgb || os_window->is_semi_transparent || + os_window->live_resize.in_progress || (os_window->bgimage && os_window->bgimage->texture_id > 0) + ); if (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) { if (!os_window->tab_bar_data_updated) { call_boss(update_tab_bar_data, "K", os_window->id); diff --git a/kitty/gl-wrapper.h b/kitty/gl-wrapper.h index 8d41a1852..03b16855f 100644 --- a/kitty/gl-wrapper.h +++ b/kitty/gl-wrapper.h @@ -1,11 +1,11 @@ /** - * Loader generated by glad 2.0.8 on Mon Aug 4 08:35:54 2025 + * Loader generated by glad 2.0.8 on Mon Aug 11 01:10:28 2025 * * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0 * * Generator: C/C++ * Specification: gl - * Extensions: 6 + * Extensions: 8 * * APIs: * - gl:core=3.1 @@ -19,10 +19,10 @@ * - ON_DEMAND = False * * Commandline: - * --api='gl:core=3.1' --extensions='GL_ARB_copy_image,GL_ARB_instanced_arrays,GL_ARB_multisample,GL_ARB_robustness,GL_ARB_texture_storage,GL_KHR_debug' c --debug --header-only + * --api='gl:core=3.1' --extensions='GL_ARB_copy_image,GL_ARB_framebuffer_sRGB,GL_ARB_instanced_arrays,GL_ARB_multisample,GL_ARB_robustness,GL_ARB_texture_storage,GL_EXT_framebuffer_sRGB,GL_KHR_debug' c --debug --header-only * * Online: - * http://glad.sh/#api=gl%3Acore%3D3.1&extensions=GL_ARB_copy_image%2CGL_ARB_instanced_arrays%2CGL_ARB_multisample%2CGL_ARB_robustness%2CGL_ARB_texture_storage%2CGL_KHR_debug&generator=c&options=DEBUG%2CHEADER_ONLY + * http://glad.sh/#api=gl%3Acore%3D3.1&extensions=GL_ARB_copy_image%2CGL_ARB_framebuffer_sRGB%2CGL_ARB_instanced_arrays%2CGL_ARB_multisample%2CGL_ARB_robustness%2CGL_ARB_texture_storage%2CGL_EXT_framebuffer_sRGB%2CGL_KHR_debug&generator=c&options=DEBUG%2CHEADER_ONLY * */ #ifndef GLAD_GL_H_ @@ -561,6 +561,8 @@ typedef void (*GLADpostcallback)(void *ret, const char *name, GLADapiproc apipro #define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC #define GL_FRAMEBUFFER_SRGB 0x8DB9 +#define GL_FRAMEBUFFER_SRGB_CAPABLE_EXT 0x8DBA +#define GL_FRAMEBUFFER_SRGB_EXT 0x8DB9 #define GL_FRAMEBUFFER_UNDEFINED 0x8219 #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD #define GL_FRONT 0x0404 @@ -1744,6 +1746,8 @@ GLAD_API_CALL int GLAD_GL_VERSION_3_0; GLAD_API_CALL int GLAD_GL_VERSION_3_1; #define GL_ARB_copy_image 1 GLAD_API_CALL int GLAD_GL_ARB_copy_image; +#define GL_ARB_framebuffer_sRGB 1 +GLAD_API_CALL int GLAD_GL_ARB_framebuffer_sRGB; #define GL_ARB_instanced_arrays 1 GLAD_API_CALL int GLAD_GL_ARB_instanced_arrays; #define GL_ARB_multisample 1 @@ -1752,6 +1756,8 @@ GLAD_API_CALL int GLAD_GL_ARB_multisample; GLAD_API_CALL int GLAD_GL_ARB_robustness; #define GL_ARB_texture_storage 1 GLAD_API_CALL int GLAD_GL_ARB_texture_storage; +#define GL_EXT_framebuffer_sRGB 1 +GLAD_API_CALL int GLAD_GL_EXT_framebuffer_sRGB; #define GL_KHR_debug 1 GLAD_API_CALL int GLAD_GL_KHR_debug; typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum op, GLfloat value); @@ -4478,10 +4484,12 @@ int GLAD_GL_VERSION_2_1 = 0; int GLAD_GL_VERSION_3_0 = 0; int GLAD_GL_VERSION_3_1 = 0; int GLAD_GL_ARB_copy_image = 0; +int GLAD_GL_ARB_framebuffer_sRGB = 0; int GLAD_GL_ARB_instanced_arrays = 0; int GLAD_GL_ARB_multisample = 0; int GLAD_GL_ARB_robustness = 0; int GLAD_GL_ARB_texture_storage = 0; +int GLAD_GL_EXT_framebuffer_sRGB = 0; int GLAD_GL_KHR_debug = 0; static void _pre_call_gl_callback_default(const char *name, GLADapiproc apiproc, int len_args, ...) { GLAD_UNUSED(len_args); @@ -10077,10 +10085,12 @@ static int glad_gl_find_extensions_gl(void) { char **exts_i = NULL; if (!glad_gl_get_extensions(&exts, &exts_i)) return 0; GLAD_GL_ARB_copy_image = glad_gl_has_extension(exts, exts_i, "GL_ARB_copy_image"); + GLAD_GL_ARB_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_ARB_framebuffer_sRGB"); GLAD_GL_ARB_instanced_arrays = glad_gl_has_extension(exts, exts_i, "GL_ARB_instanced_arrays"); GLAD_GL_ARB_multisample = glad_gl_has_extension(exts, exts_i, "GL_ARB_multisample"); GLAD_GL_ARB_robustness = glad_gl_has_extension(exts, exts_i, "GL_ARB_robustness"); GLAD_GL_ARB_texture_storage = glad_gl_has_extension(exts, exts_i, "GL_ARB_texture_storage"); + GLAD_GL_EXT_framebuffer_sRGB = glad_gl_has_extension(exts, exts_i, "GL_EXT_framebuffer_sRGB"); GLAD_GL_KHR_debug = glad_gl_has_extension(exts, exts_i, "GL_KHR_debug"); glad_gl_free_extensions(exts_i); return 1; diff --git a/kitty/gl.c b/kitty/gl.c index b1f025b1f..19133a704 100644 --- a/kitty/gl.c +++ b/kitty/gl.c @@ -67,6 +67,13 @@ gl_init(void) { } ARB_TEST(texture_storage); #undef ARB_TEST +#ifdef __APPLE__ + // See nsgl_context.m srgb is always supported on macOS but its OpenGL + // drivers dont report the extensions, so hardcode to true. + global_state.supports_framebuffer_srgb = true; +#else + global_state.supports_framebuffer_srgb = (GLAD_GL_ARB_framebuffer_sRGB + GLAD_GL_EXT_framebuffer_sRGB) != 0; +#endif glad_loaded = true; int gl_major = GLAD_VERSION_MAJOR(global_state.gl_version); int gl_minor = GLAD_VERSION_MINOR(global_state.gl_version); diff --git a/kitty/glfw.c b/kitty/glfw.c index c41a2fde0..8928fd1af 100644 --- a/kitty/glfw.c +++ b/kitty/glfw.c @@ -1381,6 +1381,7 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { // Also apparently mesa has introduced a bug with sRGB surfaces and Wayland. // Sigh. Wayland is such a pile of steaming crap. // See https://github.com/kovidgoyal/kitty/issues/7174#issuecomment-2000033873 + // GL_FRAMEBUFFER_SRGB works anyway without this on Wayland. if (!global_state.is_wayland) glfwWindowHint(GLFW_SRGB_CAPABLE, true); #ifdef __APPLE__ cocoa_set_activation_policy(OPT(macos_hide_from_tasks) || lsc != NULL); @@ -1459,7 +1460,6 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { #undef glfw_failure glfwMakeContextCurrent(glfw_window); if (is_first_window) gl_init(); - // Will make the GPU automatically apply SRGB gamma curve on the resulting framebuffer bool is_semi_transparent = glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER); // blank the window once so that there is no initial flash of color // changing, in case the background color is not black @@ -1490,9 +1490,9 @@ create_os_window(PyObject UNUSED *self, PyObject *args, PyObject *kw) { if (ret == NULL) return NULL; Py_DECREF(ret); get_platform_dependent_config_values(glfw_window); - GLint encoding; - glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding); - if (encoding != GL_SRGB) log_error("The output buffer does not support sRGB color encoding, colors will be incorrect."); + if (!global_state.supports_framebuffer_srgb) { + log_error("The OpenGL drivers dont support GL_FRAMEBUFFER_SRGB this will cause a small rendering performance penalty"); + } is_first_window = false; } OSWindow *w = add_os_window(); diff --git a/kitty/state.h b/kitty/state.h index 716c9b114..969aa6451 100644 --- a/kitty/state.h +++ b/kitty/state.h @@ -349,6 +349,7 @@ typedef struct { bool redirect_mouse_handling; WindowLogoTable *all_window_logos; int gl_version; + bool supports_framebuffer_srgb; PyObject *options_object; } GlobalState;