Allow drawing images below cells w/background

This commit is contained in:
Fredrick Brennan
2020-01-11 13:29:41 +08:00
committed by Kovid Goyal
parent a15d3ff12d
commit 8020657d8c
7 changed files with 68 additions and 27 deletions

View File

@@ -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 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. 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 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 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 ``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 ``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 ``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** **Keys for deleting images**
----------------------------------------------------------- -----------------------------------------------------------
``d`` Single character. ``a`` What to delete. ``d`` Single character. ``a`` What to delete.

View File

@@ -2,7 +2,7 @@
#define WHICH_PROGRAM #define WHICH_PROGRAM
#define NOT_TRANSPARENT #define NOT_TRANSPARENT
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) #if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(DEFAULTBG)
#define NEEDS_BACKROUND #define NEEDS_BACKROUND
#endif #endif
@@ -12,6 +12,8 @@
#ifdef NEEDS_BACKROUND #ifdef NEEDS_BACKROUND
in vec3 background; in vec3 background;
in vec3 defaultbg;
in float bgfac;
#if defined(TRANSPARENT) || defined(SPECIAL) #if defined(TRANSPARENT) || defined(SPECIAL)
in float bg_alpha; in float bg_alpha;
#endif #endif
@@ -76,11 +78,13 @@ vec4 blend_onto_opaque_premul(vec3 over, float over_alpha, vec3 under) {
* *
* 2a) Opaque bg with images under text * 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): * 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 * 1) Draw only the default background
* 2) Draw the images that are supposed to be below text. This happens in the graphics shader * 2) Draw the images that are supposed to be below both the background and 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 * 3) Draw the background of cells that don't have the default background
* 4) Draw the foreground -- expected output is color with alpha which is blended using the opaque blend func 4) Draw the images that are supposed to be below text but not background, again in graphics shader.
* 5) Draw the images that are supposed to be above text again in the 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 * 2b) Transparent bg with images
* First everything is rendered into a framebuffer, and then the framebauffer is blended onto * First everything is rendered into a framebuffer, and then the framebauffer is blended onto
@@ -125,11 +129,15 @@ void main() {
#endif #endif
#endif #endif
#ifdef BACKGROUND #if (defined(DEFAULTBG) || defined(BACKGROUND))
#ifdef TRANSPARENT #if defined(TRANSPARENT)
final_color = vec4(background.rgb * bg_alpha, bg_alpha); final_color = vec4(bgfac * background.rgb * bg_alpha, bg_alpha * bgfac);
#else #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
#endif #endif

View File

@@ -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 #define NEEDS_BACKROUND
#endif #endif
@@ -45,6 +45,8 @@ const uvec2 cell_pos_map[] = uvec2[4](
#ifdef NEEDS_BACKROUND #ifdef NEEDS_BACKROUND
out vec3 background; out vec3 background;
out vec3 defaultbg;
out float bgfac;
#if defined(TRANSPARENT) || defined(SPECIAL) #if defined(TRANSPARENT) || defined(SPECIAL)
out float bg_alpha; out float bg_alpha;
#endif #endif
@@ -197,8 +199,13 @@ void main() {
// Background {{{ // Background {{{
#ifdef NEEDS_BACKROUND #ifdef NEEDS_BACKROUND
#if defined(BACKGROUND) #if defined(BACKGROUND) || defined(DEFAULTBG)
background = bg; background = bg;
defaultbg = to_color(colors[2], default_colors[bg_index]);
bgfac = 1-float(equal(background, defaultbg));
#if defined(DEFAULTBG)
bgfac += 1;
#endif
#endif #endif
#if defined(TRANSPARENT) #if defined(TRANSPARENT)

View File

@@ -544,7 +544,9 @@ grman_update_layers(GraphicsManager *self, unsigned int scrolled_by, float scree
if (!self->layers_dirty) return false; if (!self->layers_dirty) return false;
self->layers_dirty = false; self->layers_dirty = false;
size_t i, j; 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; Image *img; ImageRef *ref;
ImageRect r; ImageRect r;
float screen_width = dx * num_cols, screen_height = dy * num_rows; 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; 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; 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); ensure_space_for(self, render_data, ImageRenderData, self->count + 1, capacity, 64, true);
ImageRenderData *rd = self->render_data + self->count; ImageRenderData *rd = self->render_data + self->count;
zero_at_ptr(rd); zero_at_ptr(rd);

View File

@@ -72,7 +72,8 @@ typedef struct {
size_t count, capacity; size_t count, capacity;
ImageRenderData *render_data; ImageRenderData *render_data;
bool layers_dirty; 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; unsigned int last_scrolled_by;
size_t used_storage; size_t used_storage;
} GraphicsManager; } GraphicsManager;

View File

@@ -9,7 +9,7 @@
#include "gl.h" #include "gl.h"
#include <stddef.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 }; enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT };
// Sprites {{{ // Sprites {{{
@@ -390,12 +390,18 @@ draw_cells_simple(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
static void static void
draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) { 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); glEnable(GL_BLEND);
BLEND_ONTO_OPAQUE; 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); bind_program(CELL_SPECIAL_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); 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); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, offscreen_framebuffer);
glFramebufferTexture(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, os_window->offscreen_texture_id, 0); 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"); */ /* if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) fatal("Offscreen framebuffer not complete"); */
bind_program(CELL_DEFAULT_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);
BLEND_PREMULT; 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); bind_program(CELL_SPECIAL_PROGRAM);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); 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(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, 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_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 #undef S
cell_uniform_data.constants_set = true; 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); 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 draw_cells_simple(vao_idx, gvao_idx, screen);
} else { } 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); else draw_cells_simple(vao_idx, gvao_idx, screen);
} }
} }
@@ -691,7 +706,7 @@ static PyMethodDef module_methods[] = {
bool bool
init_shaders(PyObject *module) { init_shaders(PyObject *module) {
#define C(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return false; } #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(GLSL_VERSION);
C(GL_VERSION); C(GL_VERSION);
C(GL_VENDOR); C(GL_VENDOR);

View File

@@ -15,7 +15,7 @@ from .constants import (
ScreenGeometry, WindowGeometry, appname, get_boss, wakeup ScreenGeometry, WindowGeometry, appname, get_boss, wakeup
) )
from .fast_data_types import ( 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, CELL_SPECIAL_PROGRAM, CSI, DCS, DECORATION, DIM,
GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM, GRAPHICS_ALPHA_MASK_PROGRAM, GRAPHICS_PREMULT_PROGRAM, GRAPHICS_PROGRAM,
OSC, REVERSE, SCROLL_FULL, SCROLL_LINE, SCROLL_PAGE, STRIKETHROUGH, Screen, 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 { for which, p in {
'SIMPLE': CELL_PROGRAM, 'SIMPLE': CELL_PROGRAM,
'BACKGROUND': CELL_BG_PROGRAM, 'BACKGROUND': CELL_BG_PROGRAM,
'DEFAULTBG': CELL_DEFAULT_BG_PROGRAM,
'SPECIAL': CELL_SPECIAL_PROGRAM, 'SPECIAL': CELL_SPECIAL_PROGRAM,
'FOREGROUND': CELL_FG_PROGRAM, 'FOREGROUND': CELL_FG_PROGRAM,
}.items(): }.items():