More robust detection of support for GL_FRAMEBUFFER_SRGB

When not supported fallback to layer based rendering
This commit is contained in:
Kovid Goyal
2025-08-11 09:13:49 +05:30
parent dea16c2ef7
commit 9f51779750
6 changed files with 32 additions and 11 deletions

View File

@@ -10,7 +10,8 @@ import subprocess
cmdline = ( cmdline = (
'glad --out-path {dest} --api gl:core=3.1 ' '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' 'c --header-only --debug'
) )

View File

@@ -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 #define TD os_window->tab_bar_render_data
bool needs_render = os_window->needs_render; bool needs_render = os_window->needs_render;
os_window->needs_render = false; os_window->needs_render = false;
os_window->needs_layers = os_window->is_semi_transparent || os_window->live_resize.in_progress || ( os_window->needs_layers = (
os_window->bgimage && os_window->bgimage->texture_id > 0); !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 (TD.screen && os_window->num_tabs >= OPT(tab_bar_min_tabs)) {
if (!os_window->tab_bar_data_updated) { if (!os_window->tab_bar_data_updated) {
call_boss(update_tab_bar_data, "K", os_window->id); call_boss(update_tab_bar_data, "K", os_window->id);

18
kitty/gl-wrapper.h generated
View File

@@ -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 * SPDX-License-Identifier: (WTFPL OR CC0-1.0) AND Apache-2.0
* *
* Generator: C/C++ * Generator: C/C++
* Specification: gl * Specification: gl
* Extensions: 6 * Extensions: 8
* *
* APIs: * APIs:
* - gl:core=3.1 * - gl:core=3.1
@@ -19,10 +19,10 @@
* - ON_DEMAND = False * - ON_DEMAND = False
* *
* Commandline: * 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: * 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_ #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_MULTISAMPLE 0x8D56
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC #define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER 0x8CDC
#define GL_FRAMEBUFFER_SRGB 0x8DB9 #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_UNDEFINED 0x8219
#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD #define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD
#define GL_FRONT 0x0404 #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; GLAD_API_CALL int GLAD_GL_VERSION_3_1;
#define GL_ARB_copy_image 1 #define GL_ARB_copy_image 1
GLAD_API_CALL int GLAD_GL_ARB_copy_image; 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 #define GL_ARB_instanced_arrays 1
GLAD_API_CALL int GLAD_GL_ARB_instanced_arrays; GLAD_API_CALL int GLAD_GL_ARB_instanced_arrays;
#define GL_ARB_multisample 1 #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; GLAD_API_CALL int GLAD_GL_ARB_robustness;
#define GL_ARB_texture_storage 1 #define GL_ARB_texture_storage 1
GLAD_API_CALL int GLAD_GL_ARB_texture_storage; 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 #define GL_KHR_debug 1
GLAD_API_CALL int GLAD_GL_KHR_debug; GLAD_API_CALL int GLAD_GL_KHR_debug;
typedef void (GLAD_API_PTR *PFNGLACCUMPROC)(GLenum op, GLfloat value); 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_0 = 0;
int GLAD_GL_VERSION_3_1 = 0; int GLAD_GL_VERSION_3_1 = 0;
int GLAD_GL_ARB_copy_image = 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_instanced_arrays = 0;
int GLAD_GL_ARB_multisample = 0; int GLAD_GL_ARB_multisample = 0;
int GLAD_GL_ARB_robustness = 0; int GLAD_GL_ARB_robustness = 0;
int GLAD_GL_ARB_texture_storage = 0; int GLAD_GL_ARB_texture_storage = 0;
int GLAD_GL_EXT_framebuffer_sRGB = 0;
int GLAD_GL_KHR_debug = 0; int GLAD_GL_KHR_debug = 0;
static void _pre_call_gl_callback_default(const char *name, GLADapiproc apiproc, int len_args, ...) { static void _pre_call_gl_callback_default(const char *name, GLADapiproc apiproc, int len_args, ...) {
GLAD_UNUSED(len_args); GLAD_UNUSED(len_args);
@@ -10077,10 +10085,12 @@ static int glad_gl_find_extensions_gl(void) {
char **exts_i = NULL; char **exts_i = NULL;
if (!glad_gl_get_extensions(&exts, &exts_i)) return 0; 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_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_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_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_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_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_KHR_debug = glad_gl_has_extension(exts, exts_i, "GL_KHR_debug");
glad_gl_free_extensions(exts_i); glad_gl_free_extensions(exts_i);
return 1; return 1;

View File

@@ -67,6 +67,13 @@ gl_init(void) {
} }
ARB_TEST(texture_storage); ARB_TEST(texture_storage);
#undef ARB_TEST #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; glad_loaded = true;
int gl_major = GLAD_VERSION_MAJOR(global_state.gl_version); int gl_major = GLAD_VERSION_MAJOR(global_state.gl_version);
int gl_minor = GLAD_VERSION_MINOR(global_state.gl_version); int gl_minor = GLAD_VERSION_MINOR(global_state.gl_version);

View File

@@ -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. // Also apparently mesa has introduced a bug with sRGB surfaces and Wayland.
// Sigh. Wayland is such a pile of steaming crap. // Sigh. Wayland is such a pile of steaming crap.
// See https://github.com/kovidgoyal/kitty/issues/7174#issuecomment-2000033873 // 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); if (!global_state.is_wayland) glfwWindowHint(GLFW_SRGB_CAPABLE, true);
#ifdef __APPLE__ #ifdef __APPLE__
cocoa_set_activation_policy(OPT(macos_hide_from_tasks) || lsc != NULL); 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 #undef glfw_failure
glfwMakeContextCurrent(glfw_window); glfwMakeContextCurrent(glfw_window);
if (is_first_window) gl_init(); 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); bool is_semi_transparent = glfwGetWindowAttrib(glfw_window, GLFW_TRANSPARENT_FRAMEBUFFER);
// blank the window once so that there is no initial flash of color // blank the window once so that there is no initial flash of color
// changing, in case the background color is not black // 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; if (ret == NULL) return NULL;
Py_DECREF(ret); Py_DECREF(ret);
get_platform_dependent_config_values(glfw_window); get_platform_dependent_config_values(glfw_window);
GLint encoding; if (!global_state.supports_framebuffer_srgb) {
glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_BACK_LEFT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, &encoding); log_error("The OpenGL drivers dont support GL_FRAMEBUFFER_SRGB this will cause a small rendering performance penalty");
if (encoding != GL_SRGB) log_error("The output buffer does not support sRGB color encoding, colors will be incorrect."); }
is_first_window = false; is_first_window = false;
} }
OSWindow *w = add_os_window(); OSWindow *w = add_os_window();

View File

@@ -349,6 +349,7 @@ typedef struct {
bool redirect_mouse_handling; bool redirect_mouse_handling;
WindowLogoTable *all_window_logos; WindowLogoTable *all_window_logos;
int gl_version; int gl_version;
bool supports_framebuffer_srgb;
PyObject *options_object; PyObject *options_object;
} GlobalState; } GlobalState;