Only use an extra draw call for the background when drawing interleaved cells if it is actually required

This commit is contained in:
Kovid Goyal 2020-01-12 09:37:16 +05:30
parent 91673642b3
commit 714bee7f45
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
7 changed files with 44 additions and 29 deletions

View File

@ -335,7 +335,7 @@ 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. Negative z-index values below 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 INT32_MIN/2 (-1,073,741,824) will be drawn under cells with non-default background
colors. colors.
Deleting images Deleting images

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) || defined(DEFAULTBG) #if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
#define NEEDS_BACKROUND #define NEEDS_BACKROUND
#endif #endif
@ -12,7 +12,7 @@
#ifdef NEEDS_BACKROUND #ifdef NEEDS_BACKROUND
in vec3 background; in vec3 background;
in float bgfac; in float draw_bg;
#if defined(TRANSPARENT) || defined(SPECIAL) #if defined(TRANSPARENT) || defined(SPECIAL)
in float bg_alpha; in float bg_alpha;
#endif #endif
@ -128,15 +128,11 @@ void main() {
#endif #endif
#endif #endif
#if (defined(DEFAULTBG) || defined(BACKGROUND)) #ifdef BACKGROUND
#if defined(TRANSPARENT) #if defined(TRANSPARENT)
final_color = vec4(bgfac * background.rgb * bg_alpha, bg_alpha * bgfac); final_color = vec4(background.rgb * bg_alpha, bg_alpha * draw_bg);
#else #else
#if defined(DEFAULTBG) final_color = vec4(background.rgb, draw_bg);
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

@ -18,6 +18,9 @@ layout(std140) uniform CellRenderData {
uint color_table[256]; uint color_table[256];
}; };
#ifdef BACKGROUND
uniform float draw_default_bg;
#endif
// Have to use fixed locations here as all variants of the cell program share the same VAO // Have to use fixed locations here as all variants of the cell program share the same VAO
layout(location=0) in uvec3 colors; layout(location=0) in uvec3 colors;
@ -35,7 +38,7 @@ const uvec2 cell_pos_map[] = uvec2[4](
// }}} // }}}
#if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL) || defined(DEFAULTBG) #if defined(SIMPLE) || defined(BACKGROUND) || defined(SPECIAL)
#define NEEDS_BACKROUND #define NEEDS_BACKROUND
#endif #endif
@ -45,7 +48,7 @@ const uvec2 cell_pos_map[] = uvec2[4](
#ifdef NEEDS_BACKROUND #ifdef NEEDS_BACKROUND
out vec3 background; out vec3 background;
out float bgfac; out float draw_bg;
#if defined(TRANSPARENT) || defined(SPECIAL) #if defined(TRANSPARENT) || defined(SPECIAL)
out float bg_alpha; out float bg_alpha;
#endif #endif
@ -159,7 +162,8 @@ void main() {
float cell_has_cursor = is_cursor(c, r); float cell_has_cursor = is_cursor(c, r);
float is_block_cursor = step(float(cursor_fg_sprite_idx), 0.5); float is_block_cursor = step(float(cursor_fg_sprite_idx), 0.5);
float cell_has_block_cursor = cell_has_cursor * is_block_cursor; float cell_has_block_cursor = cell_has_cursor * is_block_cursor;
vec3 bg = to_color(colors[bg_index], default_colors[bg_index]); uint bg_as_uint = resolve_color(colors[bg_index], default_colors[bg_index]);
vec3 bg = color_to_vec(bg_as_uint);
// }}} // }}}
// Foreground {{{ // Foreground {{{
@ -198,13 +202,13 @@ void main() {
// Background {{{ // Background {{{
#ifdef NEEDS_BACKROUND #ifdef NEEDS_BACKROUND
#if defined(BACKGROUND) || defined(DEFAULTBG) #if defined(BACKGROUND)
background = bg; background = bg;
vec3 defaultbg = to_color(colors[2], default_colors[bg_index]); uint defaultbg = resolve_color(colors[2], default_colors[bg_index]);
bgfac = 1-float(equal(background, defaultbg)); float cell_has_non_default_bg = abs(defaultbg - bg_as_uint);
#if defined(DEFAULTBG) // draw background only if it is either non-default or the draw_default_bg
bgfac += 1; // uniform is set
#endif draw_bg = step(ONE, draw_default_bg + cell_has_non_default_bg);
#endif #endif
#if defined(TRANSPARENT) #if defined(TRANSPARENT)

View File

@ -126,6 +126,12 @@ init_uniforms(int program) {
} }
} }
GLint
get_uniform_location(int program, const char *name) {
Program *p = programs + program;
return glGetUniformLocation(p->id, name);
}
GLint GLint
get_uniform_information(int program, const char *name, GLenum information_type) { get_uniform_information(int program, const char *name, GLenum information_type) {
GLint q; GLuint t; GLint q; GLuint t;

View File

@ -41,6 +41,7 @@ GLuint program_id(int program);
Program* program_ptr(int program); Program* program_ptr(int program);
GLuint block_index(int program, const char *name); GLuint block_index(int program, const char *name);
GLint block_size(int program, GLuint block_index); GLint block_size(int program, GLuint block_index);
GLint get_uniform_location(int program, const char *name);
GLint get_uniform_information(int program, const char *name, GLenum information_type); GLint get_uniform_information(int program, const char *name, GLenum information_type);
GLint attrib_location(int program, const char *name); GLint attrib_location(int program, const char *name);
ssize_t create_vao(void); ssize_t create_vao(void);

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_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 { 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 { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT }; enum { SPRITE_MAP_UNIT, GRAPHICS_UNIT, BLIT_UNIT };
// Sprites {{{ // Sprites {{{
@ -150,6 +150,7 @@ send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei heigh
typedef struct { typedef struct {
UniformBlock render_data; UniformBlock render_data;
ArrayInformation color_table; ArrayInformation color_table;
GLint draw_default_bg_location;
} CellProgramLayout; } CellProgramLayout;
static CellProgramLayout cell_program_layouts[NUM_PROGRAMS]; static CellProgramLayout cell_program_layouts[NUM_PROGRAMS];
@ -165,6 +166,7 @@ init_cell_program(void) {
cell_program_layouts[i].color_table.offset = get_uniform_information(i, "color_table[0]", GL_UNIFORM_OFFSET); cell_program_layouts[i].color_table.offset = get_uniform_information(i, "color_table[0]", GL_UNIFORM_OFFSET);
cell_program_layouts[i].color_table.stride = get_uniform_information(i, "color_table[0]", GL_UNIFORM_ARRAY_STRIDE); cell_program_layouts[i].color_table.stride = get_uniform_information(i, "color_table[0]", GL_UNIFORM_ARRAY_STRIDE);
} }
cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location = get_uniform_location(CELL_BG_PROGRAM, "draw_default_bg");
// Sanity check to ensure the attribute location binding worked // Sanity check to ensure the attribute location binding worked
#define C(p, name, expected) { int aloc = attrib_location(p, #name); if (aloc != expected && aloc != -1) fatal("The attribute location for %s is %d != %d in program: %d", #name, aloc, expected, p); } #define C(p, name, expected) { int aloc = attrib_location(p, #name); if (aloc != expected && aloc != -1) fatal("The attribute location for %s is %d != %d in program: %d", #name, aloc, expected, p); }
for (int p = CELL_PROGRAM; p < BORDERS_PROGRAM; p++) { for (int p = CELL_PROGRAM; p < BORDERS_PROGRAM; p++) {
@ -393,14 +395,17 @@ draw_cells_interleaved(ssize_t vao_idx, ssize_t gvao_idx, Screen *screen) {
glEnable(GL_BLEND); glEnable(GL_BLEND);
BLEND_ONTO_OPAQUE; BLEND_ONTO_OPAQUE;
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); bind_program(CELL_BG_PROGRAM);
glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 1.f);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns); 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);
glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 0.f);
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); 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);
@ -429,13 +434,17 @@ 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);
glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 1.f);
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_below_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); 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);
glUniform1f(cell_program_layouts[CELL_BG_PROGRAM].draw_default_bg_location, 0.f);
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, screen->lines * screen->columns);
} }
bind_program(CELL_BG_PROGRAM); bind_program(CELL_BG_PROGRAM);
@ -706,7 +715,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_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(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(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_DEFAULT_BG_PROGRAM, CELL_FG_PROGRAM, CELL_PROGRAM, BLIT_PROGRAM, CELL_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,7 +63,6 @@ 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():