Fix rendering broken on ancient GPU drivers that dont support rendering to 16 bit textures

Fixes #9068
This commit is contained in:
Kovid Goyal
2025-10-06 08:54:53 +05:30
parent fdf2c0725c
commit e46a75ca57
4 changed files with 24 additions and 9 deletions

View File

@@ -145,6 +145,8 @@ Detailed list of changes
- Fix a regression in the previous release that broke ``goto_session -1``
- Fix rendering broken on ancient GPU drivers that dont support rendering to 16 bit textures (:iss:`9068`)
0.43.1 [2025-10-01]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@@ -84,7 +84,7 @@ gl_init(void) {
}
}
static const char*
const char*
check_framebuffer_status(void) {
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
switch (status) {
@@ -100,12 +100,6 @@ check_framebuffer_status(void) {
}
}
void
check_framebuffer_status_or_die(void) {
const char *err = check_framebuffer_status();
if (err != NULL) fatal("Framebuffer not complete with error: %s", err);
}
void
free_texture(GLuint *tex_id) {
glDeleteTextures(1, tex_id);

View File

@@ -63,7 +63,7 @@ void unbind_program(void);
GLuint compile_shaders(GLenum shader_type, GLsizei count, const GLchar * const * string);
void save_viewport_using_top_left_origin(GLsizei x, GLsizei y, GLsizei width, GLsizei height, GLsizei full_framebuffer_height);
void save_viewport_using_bottom_left_origin(GLsizei x, GLsizei y, GLsizei width, GLsizei height);
void check_framebuffer_status_or_die(void);
const char* check_framebuffer_status(void);
void restore_viewport(void);
void bind_framebuffer_for_output(unsigned fbid);
void set_framebuffer_to_use_for_output(unsigned fbid);

View File

@@ -656,9 +656,28 @@ setup_texture_as_render_target(unsigned width, unsigned height, GLuint *texture_
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// We use GL_RGBA16 to avoid incorrect colors due to quantization loss when
// blending, see https://github.com/kovidgoyal/kitty/issues/8953
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
static struct { bool ok; int fmt; } status = { false, GL_RGBA16};
glTexImage2D(GL_TEXTURE_2D, 0, status.fmt, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
bind_framebuffer_for_output(*framebuffer_id);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *texture_id, 0);
if (!status.ok) {
if (check_framebuffer_status() == NULL) {
status.ok = true;
} else {
if (status.fmt == GL_RGBA16) {
// Driver does not support 16 bit FBO so let it choose the
// format. It will probably end up choosing 8 bit but
// inaccurate colors are better than completely broken rendering.
// See https://github.com/kovidgoyal/kitty/issues/9068
status.fmt = GL_RGBA;
free_framebuffer(framebuffer_id);
free_texture(texture_id);
setup_texture_as_render_target(width, height, texture_id, framebuffer_id);
} else {
fatal("Your GPU driver does not support indirect rendering to a GL_RGBA texture via a framebuffer");
}
}
}
}
static void