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
|
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.
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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():
|
||||||
|
|||||||
Reference in New Issue
Block a user