mirror of
https://github.com/kovidgoyal/kitty
synced 2026-07-06 16:05:05 +02:00
Allow drawing images below cells w/background
This commit is contained in:
committed by
Kovid Goyal
parent
a15d3ff12d
commit
8020657d8c
@@ -334,7 +334,9 @@ Finally, you can specify the image *z-index*, i.e. the vertical stacking order.
|
||||
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.
|
||||
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
|
||||
colors.
|
||||
|
||||
Deleting images
|
||||
---------------------
|
||||
@@ -417,7 +419,7 @@ Key Value Default Description
|
||||
``Y`` Positive integer ``0`` The y-offset within the first cell at which to start displaying the image
|
||||
``c`` Positive integer ``0`` The number of columns to display the image over
|
||||
``r`` Positive integer ``0`` The number of rows to display the image over
|
||||
``z`` Integer ``0`` The *z-index* vertical stacking order of the image
|
||||
``z`` 32-bit integer ``0`` The *z-index* vertical stacking order of the image
|
||||
**Keys for deleting images**
|
||||
-----------------------------------------------------------
|
||||
``d`` Single character. ``a`` What to delete.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#define WHICH_PROGRAM
|
||||
#define NOT_TRANSPARENT
|
||||
|
||||
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
|
||||
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(DEFAULTBG)
|
||||
#define NEEDS_BACKROUND
|
||||
#endif
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
|
||||
#ifdef NEEDS_BACKROUND
|
||||
in vec3 background;
|
||||
in vec3 defaultbg;
|
||||
in float bgfac;
|
||||
#if defined(TRANSPARENT) || defined(SPECIAL)
|
||||
in float bg_alpha;
|
||||
#endif
|
||||
@@ -76,11 +78,13 @@ vec4 blend_onto_opaque_premul(vec3 over, float over_alpha, vec3 under) {
|
||||
*
|
||||
* 2a) Opaque bg with images under text
|
||||
* There are multiple passes, each pass is blended onto the previous using the opaque blend func (alpha, 1- alpha):
|
||||
* 1) Draw only the background -- expected output is color with alpha 1
|
||||
* 2) Draw the images that are supposed to be below text. This happens in the graphics shader
|
||||
* 3) Draw the special cells (selection/cursor). Output is same as from step 1, with bg_alpha 1 for special cells and 0 otherwise
|
||||
* 4) Draw the foreground -- expected output is color with alpha which is blended using the opaque blend func
|
||||
* 5) Draw the images that are supposed to be above text again in the graphics shader
|
||||
* 1) Draw only the default background
|
||||
* 2) Draw the images that are supposed to be below both the background and text. This happens in the graphics shader
|
||||
* 3) Draw the background of cells that don't have the default background
|
||||
4) Draw the images that are supposed to be below text but not background, again in graphics shader.
|
||||
* 5) Draw the special cells (selection/cursor). Output is same as from step 1, with bg_alpha 1 for special cells and 0 otherwise
|
||||
* 6) Draw the foreground -- expected output is color with alpha which is blended using the opaque blend func
|
||||
* 7) Draw the images that are supposed to be above text again in the graphics shader
|
||||
*
|
||||
* 2b) Transparent bg with images
|
||||
* First everything is rendered into a framebuffer, and then the framebauffer is blended onto
|
||||
@@ -125,11 +129,15 @@ void main() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef BACKGROUND
|
||||
#ifdef TRANSPARENT
|
||||
final_color = vec4(background.rgb * bg_alpha, bg_alpha);
|
||||
#if (defined(DEFAULTBG) || defined(BACKGROUND))
|
||||
#if defined(TRANSPARENT)
|
||||
final_color = vec4(bgfac * background.rgb * bg_alpha, bg_alpha * bgfac);
|
||||
#else
|
||||
final_color = vec4(background.rgb, 1.0f);
|
||||
#if defined(DEFAULTBG)
|
||||
final_color = vec4(bgfac * background.rgb, 1.0f);
|
||||
#else
|
||||
final_color = vec4(bgfac * background.rgb, 1.0f * bgfac);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ const uvec2 cell_pos_map[] = uvec2[4](
|
||||
// }}}
|
||||
|
||||
|
||||
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
|
||||
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(DEFAULTBG)
|
||||
#define NEEDS_BACKROUND
|
||||
#endif
|
||||
|
||||
@@ -45,6 +45,8 @@ const uvec2 cell_pos_map[] = uvec2[4](
|
||||
|
||||
#ifdef NEEDS_BACKROUND
|
||||
out vec3 background;
|
||||
out vec3 defaultbg;
|
||||
out float bgfac;
|
||||
#if defined(TRANSPARENT) || defined(SPECIAL)
|
||||
out float bg_alpha;
|
||||
#endif
|
||||
@@ -197,8 +199,13 @@ void main() {
|
||||
// Background {{{
|
||||
#ifdef NEEDS_BACKROUND
|
||||
|
||||
#if defined(BACKGROUND)
|
||||
#if defined(BACKGROUND) || defined(DEFAULTBG)
|
||||
background = bg;
|
||||
defaultbg = to_color(colors[2], default_colors[bg_index]);
|
||||
bgfac = 1-float(equal(background, defaultbg));
|
||||
#if defined(DEFAULTBG)
|
||||
bgfac += 1;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(TRANSPARENT)
|
||||
|
||||
@@ -544,7 +544,9 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
|
||||
if (!self->layers_dirty) return false;
|
||||
self->layers_dirty = false;
|
||||
size_t i, j;
|
||||
self->num_of_negative_refs = 0; self->num_of_positive_refs = 0;
|
||||
self->num_of_below_refs = 0;
|
||||
self->num_of_negative_refs = 0;
|
||||
self->num_of_positive_refs = 0;
|
||||
Image *img; ImageRef *ref;
|
||||
ImageRect r;
|
||||
float screen_width = dx * num_cols, screen_height = dy * num_rows;
|
||||
@@ -565,7 +567,12 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
|
||||
if (ref->num_cols > 0) r.right = screen_left + (ref->start_column + (int32_t)ref->num_cols) * dx;
|
||||
else r.right = r.left + screen_width * (float)ref->src_width / screen_width_px;
|
||||
|
||||
if (ref->z_index < 0) self->num_of_negative_refs++; else self->num_of_positive_refs++;
|
||||
if (ref->z_index < ((int32_t)INT32_MIN/2))
|
||||
self->num_of_below_refs++;
|
||||
else if (ref->z_index < 0)
|
||||
self->num_of_negative_refs++;
|
||||
else
|
||||
self->num_of_positive_refs++;
|
||||
ensure_space_for(self, render_data, ImageRenderData, self->count + 1, capacity, 64, true);
|
||||
ImageRenderData *rd = self->render_data + self->count;
|
||||
zero_at_ptr(rd);
|
||||
|
||||
@@ -72,7 +72,8 @@ typedef struct {
|
||||
size_t count, capacity;
|
||||
ImageRenderData *render_data;
|
||||
bool layers_dirty;
|
||||
size_t num_of_negative_refs, num_of_positive_refs;
|
||||
// The number of images below MIN_ZINDEX / 2, then the number of refs between MIN_ZINDEX / 2 and -1 inclusive, then the number of refs above 0 inclusive.
|
||||
size_t num_of_below_refs, num_of_negative_refs, num_of_positive_refs;
|
||||
unsigned int last_scrolled_by;
|
||||
size_t used_storage;
|
||||
} GraphicsManager;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "gl.h"
|
||||
#include <stddef.h>
|
||||
|
||||
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 { 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 { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT };
|
||||
|
||||
// Sprites {{{
|
||||
@@ -390,12 +390,18 @@ draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
|
||||
|
||||
static void
|
||||
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_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);
|
||||
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);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||
@@ -423,13 +429,21 @@ 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_BG_PROGRAM);
|
||||
bind_program(CELL_DEFAULT_BG_PROGRAM);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||
glEnable(GL_BLEND);
|
||||
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_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);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||
|
||||
if (screen->grman->num_of_negative_refs) {
|
||||
draw_graphics(GRAPHICS_PREMULT_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);
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
|
||||
@@ -469,6 +483,7 @@ set_cell_uniforms(float current_inactive_text_alpha, bool force) {
|
||||
S(GRAPHICS_PREMULT_PROGRAM, image, GRAPHICS_UNIT, 1i);
|
||||
S(CELL_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i); S(CELL_FG_PROGRAM, sprites, SPRITE_MAP_UNIT, 1i);
|
||||
S(CELL_PROGRAM, dim_opacity, OPT(dim_opacity), 1f); S(CELL_FG_PROGRAM, dim_opacity, OPT(dim_opacity), 1f);
|
||||
S(CELL_BG_PROGRAM, defaultbg, OPT(background), 1f);
|
||||
#undef S
|
||||
cell_uniform_data.constants_set = true;
|
||||
}
|
||||
@@ -530,7 +545,7 @@ draw_cells(ssize_t vao_idx, ssize_t gvao_idx, GLfloat xstart, GLfloat ystart, GL
|
||||
if (screen->grman->count) draw_cells_interleaved_premult(vao_idx, gvao_idx, screen, os_window);
|
||||
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);
|
||||
if (screen->grman->num_of_negative_refs || screen->grman->num_of_below_refs) draw_cells_interleaved(vao_idx, gvao_idx, screen);
|
||||
else draw_cells_simple(vao_idx, gvao_idx, screen);
|
||||
}
|
||||
}
|
||||
@@ -691,7 +706,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_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_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(GLSL_VERSION);
|
||||
C(GL_VERSION);
|
||||
C(GL_VENDOR);
|
||||
|
||||
@@ -15,7 +15,7 @@ from .constants import (
|
||||
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
|
||||
)
|
||||
from .fast_data_types import (
|
||||
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM,
|
||||
BLIT_PROGRAM, CELL_BG_PROGRAM, CELL_DEFAULT_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,6 +63,7 @@ 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():
|
||||
|
||||
Reference in New Issue
Block a user