Dont use FBO's unless absolutely necessary

Negative z-index images dont need FBO based rendering when the
background is opaque. Finishes up support for background_opacity.

Fixes #31
This commit is contained in:
Kovid Goyal
2017-11-24 17:53:20 +05:30
parent b86e0ef669
commit b51100195a
3 changed files with 60 additions and 11 deletions

View File

@@ -6,9 +6,14 @@ kitty is a feature full, cross-platform, *fast*, GPU based terminal emulator.
version 0.6.0 [future] version 0.6.0 [future]
------------------------ ------------------------
- Support background transparency via the background_opacity option. Provided
that your OS/window manager supports transparency, you can now have kitty
render pixels that have only the default background color as
semi-transparent.
- Support multiple top level (OS) windows. These windows all share the sprite - Support multiple top level (OS) windows. These windows all share the sprite
texture cache on the GPU, further reducing overall resource usage. Use texture cache on the GPU, further reducing overall resource usage. Use
the shortcut `ctrl+shift+n` to open anew top-level window. the shortcut `ctrl+shift+n` to open a new top-level window.
- Add support for a *daemon* mode using the `--single-instance` command line - Add support for a *daemon* mode using the `--single-instance` command line
option. With this option you can have only a single kitty instance running. option. With this option you can have only a single kitty instance running.

View File

@@ -62,19 +62,36 @@ vec4 calculate_foreground() {
#endif #endif
void main() { void main() {
#if defined(BACKGROUND) || defined(SPECIAL) #ifdef BACKGROUND
#if defined(TRANSPARENT) || defined(SPECIAL) #ifdef TRANSPARENT
final_color = vec4(background.rgb * bg_alpha, bg_alpha); final_color = vec4(background.rgb * bg_alpha, bg_alpha);
#else #else
final_color = vec4(background.rgb, 1.0f); final_color = vec4(background.rgb, 1.0f);
#endif #endif
#endif
#ifdef SPECIAL
#ifdef TRANSPARENT
final_color = vec4(background.rgb * bg_alpha, bg_alpha);
#else #else
final_color = vec4(background.rgb, bg_alpha);
#endif
#endif
#if defined(FOREGROUND) || defined(SIMPLE)
// FOREGROUND or SIMPLE
vec4 fg = calculate_foreground(); // pre-multiplied foreground vec4 fg = calculate_foreground(); // pre-multiplied foreground
#ifdef FOREGROUND #ifdef FOREGROUND
// FOREGROUND
#ifdef TRANSPARENT
final_color = fg; final_color = fg;
#else #else
final_color = vec4(fg.rgb / fg.a, fg.a);
#endif
#else
// SIMPLE
#ifdef TRANSPARENT #ifdef TRANSPARENT
final_color = alpha_blend_premul(fg.rgb, fg.a, background * bg_alpha, bg_alpha); final_color = alpha_blend_premul(fg.rgb, fg.a, background * bg_alpha, bg_alpha);
final_color = vec4(final_color.rgb / final_color.a, final_color.a); final_color = vec4(final_color.rgb / final_color.a, final_color.a);

View File

@@ -303,20 +303,43 @@ draw_graphics(int program, ssize_t vao_idx, ssize_t gvao_idx, ImageRenderData *d
bind_vertex_array(vao_idx); bind_vertex_array(vao_idx);
} }
#define BLEND_ONTO_OPAQUE glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // blending onto opaque colors
#define BLEND_PREMULT glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // blending of pre-multiplied colors
static void static void
draw_all_cells(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) { draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
bind_program(CELL_PROGRAM); bind_program(CELL_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
if (screen->grman->count) { if (screen->grman->count) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // blending onto opaque colors BLEND_ONTO_OPAQUE;
draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->count); draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->count);
glDisable(GL_BLEND); glDisable(GL_BLEND);
} }
} }
static void static void
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *os_window) { draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
bind_program(CELL_BG_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
glEnable(GL_BLEND);
BLEND_ONTO_OPAQUE;
if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
bind_program(CELL_SPECIAL_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
bind_program(CELL_FG_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
if (screen->grman->num_of_positive_refs) draw_graphics(GRAPHICS_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, screen->grman->num_of_negative_refs, screen->grman->num_of_positive_refs);
glDisable(GL_BLEND);
}
static void
draw_cells_interleaved_premult(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWindow *os_window) {
if (!os_window->offscreen_texture_id) { if (!os_window->offscreen_texture_id) {
glGenTextures(1, &os_window->offscreen_texture_id); glGenTextures(1, &os_window->offscreen_texture_id);
glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id); glBindTexture(GL_TEXTURE_2D, os_window->offscreen_texture_id);
@@ -334,7 +357,7 @@ draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen, OSWind
bind_program(CELL_BG_PROGRAM); bind_program(CELL_BG_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); // blending of pre-multiplied colors BLEND_PREMULT;
if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs); if (screen->grman->num_of_negative_refs) draw_graphics(GRAPHICS_PREMULT_PROGRAM, vao_idx, gvao_idx, screen->grman->render_data, 0, screen->grman->num_of_negative_refs);
@@ -390,9 +413,13 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
glUniform1i(glGetUniformLocation(program_id(CELL_FG_PROGRAM), "sprites"), SPRITE_MAP_UNIT); glUniform1i(glGetUniformLocation(program_id(CELL_FG_PROGRAM), "sprites"), SPRITE_MAP_UNIT);
cell_constants_set = true; cell_constants_set = true;
} }
bool needs_complex_rendering = screen->grman->num_of_negative_refs || (screen->grman->num_of_positive_refs && os_window->is_semi_transparent); if (os_window->is_semi_transparent) {
if (needs_complex_rendering) draw_cells_interleaved(vao_idx, gvao_idx, screen, os_window); if (screen->grman->count) draw_cells_interleaved_premult(vao_idx, gvao_idx, screen, os_window);
else draw_all_cells(vao_idx, gvao_idx, screen); else draw_cells_simple(vao_idx, gvao_idx, screen);
} else {
if (screen->grman->num_of_negative_refs) draw_cells_interleaved(vao_idx, gvao_idx, screen);
else draw_cells_simple(vao_idx, gvao_idx, screen);
}
} }
// }}} // }}}