diff --git a/docs/graphics-protocol.rst b/docs/graphics-protocol.rst index 6aca6a5e7..751d518b7 100644 --- a/docs/graphics-protocol.rst +++ b/docs/graphics-protocol.rst @@ -335,7 +335,7 @@ placed in the same location with different z-index values will be blended if they are semi-transparent. You can specify z-index values using the ``z`` key. Negative z-index values mean that the images will be drawn under the text. This allows rendering of text on top of images. Negative z-index values below -INT32_MIN/2 (-1073741824) will be drawn under cells with non-default background +INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background colors. Deleting images diff --git a/kitty/cell_fragment.glsl b/kitty/cell_fragment.glsl index a1e005c5e..223421c9c 100644 --- a/kitty/cell_fragment.glsl +++ b/kitty/cell_fragment.glsl @@ -2,7 +2,7 @@ #define WHICH_PROGRAM #define NOT_TRANSPARENT -#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(DEFAULTBG) +#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) #define NEEDS_BACKROUND #endif @@ -12,7 +12,7 @@ #ifdef NEEDS_BACKROUND in vec3 background; -in float bgfac; +in float draw_bg; #if defined(TRANSPARENT) || defined(SPECIAL) in float bg_alpha; #endif @@ -128,15 +128,11 @@ void main() { #endif #endif -#if (defined(DEFAULTBG) || defined(BACKGROUND)) +#ifdef BACKGROUND #if defined(TRANSPARENT) - final_color = vec4(bgfac * background.rgb * bg_alpha, bg_alpha * bgfac); + final_color = vec4(background.rgb * bg_alpha, bg_alpha * draw_bg); #else -#if defined(DEFAULTBG) - final_color = vec4(bgfac * background.rgb, 1.0f); -#else - final_color = vec4(bgfac * background.rgb, 1.0f * bgfac); -#endif + final_color = vec4(background.rgb, draw_bg); #endif #endif diff --git a/kitty/cell_vertex.glsl b/kitty/cell_vertex.glsl index 5e070940c..0ca913cf4 100644 --- a/kitty/cell_vertex.glsl +++ b/kitty/cell_vertex.glsl @@ -18,6 +18,9 @@ layout(std140) uniform CellRenderData { uint color_table[256]; }; +#ifdef BACKGROUND +uniform float draw_default_bg; +#endif // Have to use fixed locations here as all variants of the cell program share the same VAO layout(location=0) in uvec3 colors; @@ -35,7 +38,7 @@ const uvec2 cell_pos_map[] = uvec2[4]( // }}} -#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(DEFAULTBG) +#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) #define NEEDS_BACKROUND #endif @@ -45,7 +48,7 @@ const uvec2 cell_pos_map[] = uvec2[4]( #ifdef NEEDS_BACKROUND out vec3 background; -out float bgfac; +out float draw_bg; #if defined(TRANSPARENT) || defined(SPECIAL) out float bg_alpha; #endif @@ -159,7 +162,8 @@ void main() { float cell_has_cursor = is_cursor(c, r); float is_block_cursor = step(float(cursor_fg_sprite_idx), 0.5); float cell_has_block_cursor = cell_has_cursor * is_block_cursor; - vec3 bg = to_color(colors[bg_index], default_colors[bg_index]); + uint bg_as_uint = resolve_color(colors[bg_index], default_colors[bg_index]); + vec3 bg = color_to_vec(bg_as_uint); // }}} // Foreground {{{ @@ -198,13 +202,13 @@ void main() { // Background {{{ #ifdef NEEDS_BACKROUND -#if defined(BACKGROUND) || defined(DEFAULTBG) +#if defined(BACKGROUND) background = bg; - vec3 defaultbg = to_color(colors[2], default_colors[bg_index]); - bgfac = 1-float(equal(background, defaultbg)); -#if defined(DEFAULTBG) - bgfac += 1; -#endif + uint defaultbg = resolve_color(colors[2], default_colors[bg_index]); + float cell_has_non_default_bg = abs(defaultbg - bg_as_uint); + // draw background only if it is either non-default or the draw_default_bg + // uniform is set + draw_bg = step(ONE, draw_default_bg + cell_has_non_default_bg); #endif #if defined(TRANSPARENT) diff --git a/kitty/gl.c b/kitty/gl.c index a6f6b961d..cd623c8eb 100644 --- a/kitty/gl.c +++ b/kitty/gl.c @@ -126,6 +126,12 @@ init_uniforms(int program) { } } +GLint +get_uniform_location(int program, const char *name) { + Program *p = programs + program; + return glGetUniformLocation(p->id, name); +} + GLint get_uniform_information(int program, const char *name, GLenum information_type) { GLint q; GLuint t; diff --git a/kitty/gl.h b/kitty/gl.h index 49a9447f4..2a6981cd0 100644 --- a/kitty/gl.h +++ b/kitty/gl.h @@ -41,6 +41,7 @@ GLuint program_id(int program); Program* program_ptr(int program); GLuint block_index(int program, const char *name); GLint block_size(int program, GLuint block_index); +GLint get_uniform_location(int program, const char *name); GLint get_uniform_information(int program, const char *name, GLenum information_type); GLint attrib_location(int program, const char *name); ssize_t create_vao(void); diff --git a/kitty/shaders.c b/kitty/shaders.c index 965d9276a..271b3b624 100644 --- a/kitty/shaders.c +++ b/kitty/shaders.c @@ -9,7 +9,7 @@ #include "gl.h" #include -enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_DEFAULT_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, NUM_PROGRAMS }; +enum { CELL_PROGRAM, CELL_BG_PROGRAM, CELL_SPECIAL_PROGRAM, CELL_FG_PROGRAM, BORDERS_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, BLIT_PROGRAM, NUM_PROGRAMS }; enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT }; // Sprites {{{ @@ -150,6 +150,7 @@ send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei heigh typedef struct { UniformBlock render_data; ArrayInformation color_table; + GLint draw_default_bg_location; } CellProgramLayout; static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; @@ -165,6 +166,7 @@ init_cell_program(void) { cell_program_layouts[i].color_table.offset = get_uniform_information(i, "color_table[0]", GL_UNIFORM_OFFSET); cell_program_layouts[i].color_table.stride = get_uniform_information(i, "color_table[0]", GL_UNIFORM_ARRAY_STRIDE); } + cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location = get_uniform_location(CELL_BG_PROGRAM, "draw_default_bg"); // Sanity check to ensure the attribute location binding worked #define C(p, name, expected) { int aloc = attrib_location(p, #name); if (aloc != expected && aloc != -1) fatal("The attribute location for %s is %d != %d in program: %d", #name, aloc, expected, p); } for (int p = CELL_PROGRAM; p < BORDERS_PROGRAM; p++) { @@ -393,14 +395,17 @@ draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) { glEnable(GL_BLEND); BLEND_ONTO_OPAQUE; - bind_program(CELL_DEFAULT_BG_PROGRAM); - glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); - - if (screen->grman->num_of_below_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs); - bind_program(CELL_BG_PROGRAM); + glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 1.f); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); + if (screen->grman->num_of_below_refs) { + draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs); + bind_program(CELL_BG_PROGRAM); + glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 0.f); + glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); + } + if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_below_refs, screen->grman->num_of_negative_refs); bind_program(CELL_SPECIAL_PROGRAM); @@ -429,13 +434,17 @@ draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen glBindFramebuffer(GL_DRAW_FRAMEBUFFER, offscreen_framebuffer); glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0); /* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("Offscreen framebuffer not complete"); */ - bind_program(CELL_DEFAULT_BG_PROGRAM); + bind_program(CELL_BG_PROGRAM); + glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 1.f); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); glEnable(GL_BLEND); BLEND_PREMULT; if (screen->grman->num_of_below_refs) { draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_below_refs); + bind_program(CELL_BG_PROGRAM); + glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 0.f); + glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); } bind_program(CELL_BG_PROGRAM); @@ -706,7 +715,7 @@ static PyMethodDef module_methods[] = { bool init_shaders(PyObject *module) { #define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; } - C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_DEFAULT_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM); + C(CELL_PROGRAM); C(CELL_BG_PROGRAM); C(CELL_SPECIAL_PROGRAM); C(CELL_FG_PROGRAM); C(BORDERS_PROGRAM); C(GRAPHICS_PROGRAM); C(GRAPHICS_PREMULT_PROGRAM); C(GRAPHICS_ALPHA_MASK_PROGRAM); C(BLIT_PROGRAM); C(GLSL_VERSION); C(GL_VERSION); C(GL_VENDOR); diff --git a/kitty/window.py b/kitty/window.py index e75ec64a8..bfaeaa70a 100644 --- a/kitty/window.py +++ b/kitty/window.py @@ -15,7 +15,7 @@ from .constants import ( ScreenGeometry, WindowGeometry, appname, get_boss, wakeup ) from .fast_data_types import ( - BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_DEFAULT_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM, + BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM, CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM, GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, Screen, @@ -63,7 +63,6 @@ def load_shader_programs(semi_transparent=False): for which, p in { 'SIMPLE': CELL_PROGRAM, 'BACKGROUND': CELL_BG_PROGRAM, - 'DEFAULTBG': CELL_DEFAULT_BG_PROGRAM, 'SPECIAL': CELL_SPECIAL_PROGRAM, 'FOREGROUND': CELL_FG_PROGRAM, }.items():