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
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.

View File

@@ -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

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
#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)

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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():