mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-07-11 18:23:20 +00:00
Load GLSL binding information at runtime rather than writing it to a generated C header
This commit is contained in:
parent
91d39eba6c
commit
86bc2c952a
7 changed files with 233 additions and 360 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
|
@ -11,7 +11,6 @@ kitty/rgb.py linguist-generated=true
|
|||
kitty/srgb_gamma.* linguist-generated=true
|
||||
kitty/gl-wrapper.* linguist-generated=true
|
||||
kitty/glfw-wrapper.* linguist-generated=true
|
||||
kitty/glsl-uniforms.h linguist-generated=true
|
||||
kitty/color-names.h linguist-generated=true
|
||||
kitty/parse-graphics-command.h linguist-generated=true
|
||||
kitty/parse-multicell-command.h linguist-generated=true
|
||||
|
|
|
|||
|
|
@ -551,7 +551,7 @@ def add_window(os_window_id: int, tab_id: int, title: str) -> int:
|
|||
|
||||
|
||||
def compile_program(
|
||||
which: int, vertex_shaders: Tuple[str, ...], fragment_shaders: Tuple[str, ...], allow_recompile: bool = False
|
||||
which: int, vertex_shaders: Tuple[str, ...], fragment_shaders: Tuple[str, ...], metadata: Dict[str, Any], allow_recompile: bool = False
|
||||
) -> int:
|
||||
pass
|
||||
|
||||
|
|
|
|||
104
kitty/gl.c
104
kitty/gl.c
|
|
@ -337,6 +337,110 @@ block_size(int program, GLuint block_index) {
|
|||
return ans;
|
||||
}
|
||||
|
||||
// Program metadata (uniform/attribute locations and UBO/array info, looked up by name) {{{
|
||||
#define NAME program_metadata_map
|
||||
#define KEY_TY const char*
|
||||
#define VAL_TY ProgramMetadataEntry
|
||||
#include "kitty-verstable.h"
|
||||
|
||||
static program_metadata_map program_layouts[arraysz(programs)];
|
||||
static bool program_layouts_initialized[arraysz(programs)] = {0};
|
||||
|
||||
static void
|
||||
clear_program_layout(int program) {
|
||||
if (!program_layouts_initialized[program]) return;
|
||||
program_metadata_map *m = program_layouts + program;
|
||||
vt_create_for_loop(program_metadata_map_itr, itr, m) free((void*)itr.data->key);
|
||||
vt_cleanup(m);
|
||||
program_layouts_initialized[program] = false;
|
||||
}
|
||||
|
||||
void
|
||||
free_program_layouts(void) {
|
||||
for (size_t i = 0; i < arraysz(program_layouts); i++) clear_program_layout((int)i);
|
||||
}
|
||||
|
||||
static void
|
||||
insert_program_metadata(int program, const char *name, ProgramMetadataEntry entry) {
|
||||
program_metadata_map_itr itr = vt_insert(program_layouts + program, strdup(name), entry);
|
||||
if (vt_is_end(itr)) fatal("Out of memory adding program metadata entry: %s", name);
|
||||
}
|
||||
|
||||
static ProgramMetadataEntry*
|
||||
program_metadata_entry(int program, const char *name, ProgramMetadataKind expected) {
|
||||
program_metadata_map_itr itr = vt_get(program_layouts + program, name);
|
||||
if (vt_is_end(itr)) fatal("No metadata entry named: %s for program: %d", name, program);
|
||||
if (itr.data->val.kind != expected) fatal("The metadata entry named: %s for program: %d is not of the expected kind", name, program);
|
||||
return &itr.data->val;
|
||||
}
|
||||
|
||||
void
|
||||
set_program_layout(int program, PyObject *metadata) {
|
||||
clear_program_layout(program);
|
||||
vt_init(program_layouts + program);
|
||||
program_layouts_initialized[program] = true;
|
||||
|
||||
PyObject *key, *val; Py_ssize_t pos;
|
||||
|
||||
PyObject *loose_uniforms = PyDict_GetItemString(metadata, "loose_uniforms");
|
||||
pos = 0;
|
||||
while (PyDict_Next(loose_uniforms, &pos, &key, &val)) {
|
||||
const char *actual_name = PyUnicode_AsUTF8(val);
|
||||
ProgramMetadataEntry e = {.kind=PROGRAM_UNIFORM, .location=get_uniform_location(program, actual_name)};
|
||||
insert_program_metadata(program, PyUnicode_AsUTF8(key), e);
|
||||
}
|
||||
|
||||
PyObject *input_locations = PyDict_GetItemString(metadata, "input_locations");
|
||||
pos = 0;
|
||||
while (PyDict_Next(input_locations, &pos, &key, &val)) {
|
||||
ProgramMetadataEntry e = {.kind=PROGRAM_ATTRIBUTE, .location=(GLint)PyLong_AsLong(val)};
|
||||
insert_program_metadata(program, PyUnicode_AsUTF8(key), e);
|
||||
}
|
||||
|
||||
PyObject *uniform_structs = PyDict_GetItemString(metadata, "uniform_structs");
|
||||
PyObject *uniform_struct_names = PyDict_GetItemString(metadata, "uniform_struct_names");
|
||||
pos = 0;
|
||||
while (PyDict_Next(uniform_structs, &pos, &key, &val)) {
|
||||
const char *glsl_block_name = PyUnicode_AsUTF8(PyDict_GetItem(uniform_struct_names, key));
|
||||
GLuint index = block_index(program, glsl_block_name);
|
||||
ProgramMetadataEntry be = {.kind=PROGRAM_BLOCK, .block={.size=block_size(program, index), .index=(GLint)index}};
|
||||
insert_program_metadata(program, PyUnicode_AsUTF8(key), be);
|
||||
|
||||
PyObject *mkey, *mval; Py_ssize_t mpos = 0;
|
||||
while (PyDict_Next(val, &mpos, &mkey, &mval)) {
|
||||
const char *decl = PyUnicode_AsUTF8(mval);
|
||||
const char *bracket = strchr(decl, '[');
|
||||
if (!bracket) continue; // scalar block members are hand-mirrored in C structs, not queried here
|
||||
char actual_name[256];
|
||||
size_t n = MIN(sizeof(actual_name) - 1, (size_t)(bracket - decl));
|
||||
memcpy(actual_name, decl, n); actual_name[n] = 0;
|
||||
ProgramMetadataEntry ae = {.kind=PROGRAM_ARRAY, .array=get_uniform_array_information(program, actual_name)};
|
||||
insert_program_metadata(program, PyUnicode_AsUTF8(mkey), ae);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GLint
|
||||
program_uniform_location(int program, const char *name) {
|
||||
return program_metadata_entry(program, name, PROGRAM_UNIFORM)->location;
|
||||
}
|
||||
|
||||
GLint
|
||||
program_attribute_location(int program, const char *name) {
|
||||
return program_metadata_entry(program, name, PROGRAM_ATTRIBUTE)->location;
|
||||
}
|
||||
|
||||
UniformBlock
|
||||
program_uniform_block(int program, const char *name) {
|
||||
return program_metadata_entry(program, name, PROGRAM_BLOCK)->block;
|
||||
}
|
||||
|
||||
ArrayInformation
|
||||
program_uniform_array(int program, const char *name) {
|
||||
return program_metadata_entry(program, name, PROGRAM_ARRAY)->array;
|
||||
}
|
||||
// }}}
|
||||
|
||||
void
|
||||
bind_program(int program) {
|
||||
glUseProgram(programs[program].id);
|
||||
|
|
|
|||
12
kitty/gl.h
12
kitty/gl.h
|
|
@ -33,6 +33,12 @@ typedef struct {
|
|||
|
||||
typedef struct Viewport { unsigned left, top, width, height; } Viewport;
|
||||
|
||||
typedef enum { PROGRAM_UNIFORM, PROGRAM_ATTRIBUTE, PROGRAM_BLOCK, PROGRAM_ARRAY } ProgramMetadataKind;
|
||||
typedef struct ProgramMetadataEntry {
|
||||
ProgramMetadataKind kind;
|
||||
union { GLint location; UniformBlock block; ArrayInformation array; };
|
||||
} ProgramMetadataEntry;
|
||||
|
||||
void gl_init(void);
|
||||
const char* gl_version_string(void);
|
||||
void set_gpu_viewport(unsigned w, unsigned h);
|
||||
|
|
@ -51,6 +57,12 @@ GLint get_uniform_location(int program, const char *name);
|
|||
GLint get_uniform_information(int program, const char *name, GLenum information_type);
|
||||
ArrayInformation get_uniform_array_information(int program, const char *name);
|
||||
GLint attrib_location(int program, const char *name);
|
||||
void set_program_layout(int program, PyObject *metadata);
|
||||
void free_program_layouts(void);
|
||||
GLint program_uniform_location(int program, const char *name);
|
||||
GLint program_attribute_location(int program, const char *name);
|
||||
UniformBlock program_uniform_block(int program, const char *name);
|
||||
ArrayInformation program_uniform_array(int program, const char *name);
|
||||
ssize_t create_vao(void);
|
||||
size_t add_buffer_to_vao(ssize_t vao_idx, GLenum usage);
|
||||
void add_attribute_to_vao(ssize_t vao_idx, int location, GLint size, GLenum data_type, GLsizei stride, void *offset, GLuint divisor);
|
||||
|
|
|
|||
|
|
@ -1,166 +0,0 @@
|
|||
// generated by slang.py DO NOT EDIT
|
||||
#include "gl.h"
|
||||
|
||||
|
||||
typedef struct BgimageUniforms {
|
||||
int background;
|
||||
int image;
|
||||
int positions;
|
||||
int sizes;
|
||||
int tiled;
|
||||
} BgimageUniforms;
|
||||
|
||||
static inline void get_uniform_locations_bgimage(int program, BgimageUniforms *ans) {
|
||||
ans->background = get_uniform_location(program, "background_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->positions = get_uniform_location(program, "positions_0");
|
||||
ans->sizes = get_uniform_location(program, "sizes_0");
|
||||
ans->tiled = get_uniform_location(program, "tiled_0");
|
||||
}
|
||||
|
||||
typedef struct BlitUniforms {
|
||||
int dest_rect;
|
||||
int image;
|
||||
int src_rect;
|
||||
} BlitUniforms;
|
||||
|
||||
static inline void get_uniform_locations_blit(int program, BlitUniforms *ans) {
|
||||
ans->dest_rect = get_uniform_location(program, "dest_rect_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->src_rect = get_uniform_location(program, "src_rect_0");
|
||||
}
|
||||
|
||||
typedef struct BorderUniforms {
|
||||
int background_opacity;
|
||||
// Vertex Input locations
|
||||
int rect;
|
||||
int rect_color;
|
||||
// Uniform block locations
|
||||
UniformBlock Colors;
|
||||
ArrayInformation colors;
|
||||
UniformBlock GammaLUT;
|
||||
ArrayInformation gamma_lut;
|
||||
} BorderUniforms;
|
||||
|
||||
static inline void get_uniform_locations_border(int program, BorderUniforms *ans) {
|
||||
ans->background_opacity = get_uniform_location(program, "background_opacity_0");
|
||||
ans->rect = 0;
|
||||
ans->rect_color = 1;
|
||||
ans->Colors.index = block_index(program, "block_Colors_0");
|
||||
ans->Colors.size = block_size(program, ans->Colors.index);
|
||||
ans->colors = get_uniform_array_information(program, "colors_0");
|
||||
ans->GammaLUT.index = block_index(program, "block_GammaLUT_0");
|
||||
ans->GammaLUT.size = block_size(program, ans->GammaLUT.index);
|
||||
ans->gamma_lut = get_uniform_array_information(program, "gamma_lut_0");
|
||||
}
|
||||
|
||||
typedef struct CellUniforms {
|
||||
int draw_bg_bitfield;
|
||||
int sprite_decorations_map;
|
||||
int sprites;
|
||||
int text_contrast;
|
||||
int text_gamma_adjustment;
|
||||
// Vertex Input locations
|
||||
int colors;
|
||||
int is_selected;
|
||||
int sprite_idx;
|
||||
// Uniform block locations
|
||||
UniformBlock CellRenderData;
|
||||
UniformBlock ColorTable;
|
||||
ArrayInformation color_table;
|
||||
UniformBlock GammaLUT;
|
||||
ArrayInformation gamma_lut;
|
||||
} CellUniforms;
|
||||
|
||||
static inline void get_uniform_locations_cell(int program, CellUniforms *ans) {
|
||||
ans->draw_bg_bitfield = get_uniform_location(program, "draw_bg_bitfield_0");
|
||||
ans->sprite_decorations_map = get_uniform_location(program, "sprite_decorations_map_0");
|
||||
ans->sprites = get_uniform_location(program, "sprites_0");
|
||||
ans->text_contrast = get_uniform_location(program, "text_contrast_0");
|
||||
ans->text_gamma_adjustment = get_uniform_location(program, "text_gamma_adjustment_0");
|
||||
ans->colors = 0;
|
||||
ans->is_selected = 2;
|
||||
ans->sprite_idx = 1;
|
||||
ans->CellRenderData.index = block_index(program, "block_CellRenderData_0");
|
||||
ans->CellRenderData.size = block_size(program, ans->CellRenderData.index);
|
||||
ans->ColorTable.index = block_index(program, "block_ColorTable_0");
|
||||
ans->ColorTable.size = block_size(program, ans->ColorTable.index);
|
||||
ans->color_table = get_uniform_array_information(program, "color_table_0");
|
||||
ans->GammaLUT.index = block_index(program, "block_GammaLUT_0");
|
||||
ans->GammaLUT.size = block_size(program, ans->GammaLUT.index);
|
||||
ans->gamma_lut = get_uniform_array_information(program, "gamma_lut_0");
|
||||
}
|
||||
|
||||
typedef struct GraphicsUniforms {
|
||||
int amask_bg_premult;
|
||||
int amask_fg;
|
||||
int dest_rect;
|
||||
int extra_alpha;
|
||||
int image;
|
||||
int src_rect;
|
||||
} GraphicsUniforms;
|
||||
|
||||
static inline void get_uniform_locations_graphics(int program, GraphicsUniforms *ans) {
|
||||
ans->amask_bg_premult = get_uniform_location(program, "amask_bg_premult_0");
|
||||
ans->amask_fg = get_uniform_location(program, "amask_fg_0");
|
||||
ans->dest_rect = get_uniform_location(program, "dest_rect_0");
|
||||
ans->extra_alpha = get_uniform_location(program, "extra_alpha_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->src_rect = get_uniform_location(program, "src_rect_0");
|
||||
}
|
||||
|
||||
typedef struct Rounded_rectUniforms {
|
||||
int background_color;
|
||||
int color;
|
||||
int params;
|
||||
int rect;
|
||||
} Rounded_rectUniforms;
|
||||
|
||||
static inline void get_uniform_locations_rounded_rect(int program, Rounded_rectUniforms *ans) {
|
||||
ans->background_color = get_uniform_location(program, "background_color_0");
|
||||
ans->color = get_uniform_location(program, "color_0");
|
||||
ans->params = get_uniform_location(program, "params_0");
|
||||
ans->rect = get_uniform_location(program, "rect_0");
|
||||
}
|
||||
|
||||
typedef struct ScreenshotUniforms {
|
||||
int dest_rect;
|
||||
int image;
|
||||
int src_rect;
|
||||
int src_size;
|
||||
} ScreenshotUniforms;
|
||||
|
||||
static inline void get_uniform_locations_screenshot(int program, ScreenshotUniforms *ans) {
|
||||
ans->dest_rect = get_uniform_location(program, "dest_rect_0");
|
||||
ans->image = get_uniform_location(program, "image_0");
|
||||
ans->src_rect = get_uniform_location(program, "src_rect_0");
|
||||
ans->src_size = get_uniform_location(program, "src_size_0");
|
||||
}
|
||||
|
||||
typedef struct TintUniforms {
|
||||
int edges;
|
||||
int tint_color;
|
||||
} TintUniforms;
|
||||
|
||||
static inline void get_uniform_locations_tint(int program, TintUniforms *ans) {
|
||||
ans->edges = get_uniform_location(program, "edges_0");
|
||||
ans->tint_color = get_uniform_location(program, "tint_color_0");
|
||||
}
|
||||
|
||||
typedef struct TrailUniforms {
|
||||
int cursor_edge_x;
|
||||
int cursor_edge_y;
|
||||
int trail_color;
|
||||
int trail_opacity;
|
||||
int x_coords;
|
||||
int y_coords;
|
||||
} TrailUniforms;
|
||||
|
||||
static inline void get_uniform_locations_trail(int program, TrailUniforms *ans) {
|
||||
ans->cursor_edge_x = get_uniform_location(program, "cursor_edge_x_0");
|
||||
ans->cursor_edge_y = get_uniform_location(program, "cursor_edge_y_0");
|
||||
ans->trail_color = get_uniform_location(program, "trail_color_0");
|
||||
ans->trail_opacity = get_uniform_location(program, "trail_opacity_0");
|
||||
ans->x_coords = get_uniform_location(program, "x_coords_0");
|
||||
ans->y_coords = get_uniform_location(program, "y_coords_0");
|
||||
}
|
||||
242
kitty/shaders.c
242
kitty/shaders.c
|
|
@ -14,7 +14,6 @@
|
|||
#include "text-cache.h"
|
||||
#include "window_logo.h"
|
||||
#include "srgb_gamma.h"
|
||||
#include "glsl-uniforms.h"
|
||||
#include "state.h"
|
||||
|
||||
enum {
|
||||
|
|
@ -296,11 +295,6 @@ send_image_to_gpu(GLuint *tex_id, const void* data, GLsizei width, GLsizei heigh
|
|||
// }}}
|
||||
|
||||
// Rounded rect {{{
|
||||
typedef struct {
|
||||
Rounded_rectUniforms uniforms;
|
||||
} RoundedRectProgramLayout;
|
||||
static RoundedRectProgramLayout rounded_rect_program_layout;
|
||||
|
||||
static double
|
||||
thickness_as_float(const OSWindow *os_window, unsigned level) {
|
||||
level = MIN(level, arraysz(OPT(box_drawing_scale)));
|
||||
|
|
@ -318,12 +312,12 @@ draw_rounded_rect(
|
|||
) {
|
||||
float thickness = (float)thickness_as_float(os_window, thickness_level);
|
||||
bind_program(ROUNDED_RECT_PROGRAM);
|
||||
color_vec4(rounded_rect_program_layout.uniforms.color, srgb_color, 1.f);
|
||||
color_vec4(rounded_rect_program_layout.uniforms.background_color, srgb_background, bg_alpha);
|
||||
color_vec4(program_uniform_location(ROUNDED_RECT_PROGRAM, "color"), srgb_color, 1.f);
|
||||
color_vec4(program_uniform_location(ROUNDED_RECT_PROGRAM, "background_color"), srgb_background, bg_alpha);
|
||||
// y co-ord has to be changed to co-ord system with origin at bottom left
|
||||
float y = (float)framebuffer_height - (float)(rect.top + rect.height);
|
||||
glUniform4f(rounded_rect_program_layout.uniforms.rect, rect.left, y, rect.width, rect.height);
|
||||
glUniform2f(rounded_rect_program_layout.uniforms.params, thickness, corner_radius_px);
|
||||
glUniform4f(program_uniform_location(ROUNDED_RECT_PROGRAM, "rect"), rect.left, y, rect.width, rect.height);
|
||||
glUniform2f(program_uniform_location(ROUNDED_RECT_PROGRAM, "params"), thickness, corner_radius_px);
|
||||
save_viewport_using_top_left_origin(rect.left, rect.top, rect.width, rect.height, framebuffer_height);
|
||||
draw_quad(true, 0);
|
||||
restore_viewport();
|
||||
|
|
@ -338,46 +332,6 @@ enum { GAMMA_LUT_GLOBAL_BUFFER, BORDER_COLORS_GLOBAL_BUFFER };
|
|||
// its vertex attribute/array facilities are unused.
|
||||
static ssize_t shader_globals_vao_idx = -1;
|
||||
|
||||
typedef struct {
|
||||
CellUniforms uniforms;
|
||||
} CellProgramLayout;
|
||||
static CellProgramLayout cell_program_layouts[NUM_PROGRAMS];
|
||||
|
||||
typedef struct {
|
||||
GraphicsUniforms uniforms;
|
||||
} GraphicsProgramLayout;
|
||||
static GraphicsProgramLayout graphics_program_layouts[NUM_PROGRAMS];
|
||||
|
||||
typedef struct {
|
||||
BgimageUniforms uniforms;
|
||||
} BGImageProgramLayout;
|
||||
static BGImageProgramLayout bgimage_program_layout;
|
||||
|
||||
typedef struct {
|
||||
TintUniforms uniforms;
|
||||
} TintProgramLayout;
|
||||
static TintProgramLayout tint_program_layout;
|
||||
|
||||
typedef struct {
|
||||
TrailUniforms uniforms;
|
||||
} TrailProgramLayout;
|
||||
static TrailProgramLayout trail_program_layout;
|
||||
|
||||
typedef struct {
|
||||
BlitUniforms uniforms;
|
||||
} BlitProgramLayout;
|
||||
static BlitProgramLayout blit_program_layout;
|
||||
|
||||
typedef struct {
|
||||
ScreenshotUniforms uniforms;
|
||||
} ScreenshotProgramLayout;
|
||||
static ScreenshotProgramLayout screenshot_program_layout;
|
||||
|
||||
typedef struct BorderProgramLayout {
|
||||
BorderUniforms uniforms;
|
||||
} BorderProgramLayout;
|
||||
static BorderProgramLayout border_program_layout;
|
||||
|
||||
static void
|
||||
write_float_array_to_ubo(void *dest, const GLfloat *src, size_t count, const ArrayInformation *ai) {
|
||||
GLint stride = MAX((GLint)sizeof(GLfloat), ai->stride);
|
||||
|
|
@ -396,11 +350,13 @@ static void
|
|||
init_cell_program(void) {
|
||||
GLint gamma_lut_buf_size = 0;
|
||||
for (int i = CELL_PROGRAM; i < CELL_PROGRAM_SENTINEL; i++) {
|
||||
get_uniform_locations_cell(i, &cell_program_layouts[i].uniforms);
|
||||
glUniformBlockBinding(program_id(i), cell_program_layouts[i].uniforms.CellRenderData.index, CELL_RENDER_DATA_BINDING_POINT);
|
||||
glUniformBlockBinding(program_id(i), cell_program_layouts[i].uniforms.ColorTable.index, COLOR_TABLE_BINDING_POINT);
|
||||
glUniformBlockBinding(program_id(i), cell_program_layouts[i].uniforms.GammaLUT.index, GAMMA_LUT_BINDING_POINT);
|
||||
gamma_lut_buf_size = MAX(gamma_lut_buf_size, cell_program_layouts[i].uniforms.GammaLUT.size);
|
||||
UniformBlock crd = program_uniform_block(i, "CellRenderData");
|
||||
glUniformBlockBinding(program_id(i), crd.index, CELL_RENDER_DATA_BINDING_POINT);
|
||||
UniformBlock ct = program_uniform_block(i, "ColorTable");
|
||||
glUniformBlockBinding(program_id(i), ct.index, COLOR_TABLE_BINDING_POINT);
|
||||
UniformBlock glut = program_uniform_block(i, "GammaLUT");
|
||||
glUniformBlockBinding(program_id(i), glut.index, GAMMA_LUT_BINDING_POINT);
|
||||
gamma_lut_buf_size = MAX(gamma_lut_buf_size, glut.size);
|
||||
}
|
||||
|
||||
// Sanity check to ensure the attribute location binding worked
|
||||
|
|
@ -409,31 +365,23 @@ init_cell_program(void) {
|
|||
C(p, colors, 0); C(p, sprite_idx, 1); C(p, is_selected, 2); C(p, decorations_sprite_map, 3);
|
||||
}
|
||||
#undef C
|
||||
for (int i = GRAPHICS_PROGRAM; i <= GRAPHICS_ALPHA_MASK_PROGRAM; i++) {
|
||||
get_uniform_locations_graphics(i, &graphics_program_layouts[i].uniforms);
|
||||
}
|
||||
get_uniform_locations_bgimage(BGIMAGE_PROGRAM, &bgimage_program_layout.uniforms);
|
||||
get_uniform_locations_tint(TINT_PROGRAM, &tint_program_layout.uniforms);
|
||||
get_uniform_locations_trail(TRAIL_PROGRAM, &trail_program_layout.uniforms);
|
||||
get_uniform_locations_blit(BLIT_PROGRAM, &blit_program_layout.uniforms);
|
||||
get_uniform_locations_screenshot(SCREENSHOT_PROGRAM, &screenshot_program_layout.uniforms);
|
||||
get_uniform_locations_rounded_rect(ROUNDED_RECT_PROGRAM, &rounded_rect_program_layout.uniforms);
|
||||
get_uniform_locations_border(BORDERS_PROGRAM, &border_program_layout.uniforms);
|
||||
glUniformBlockBinding(program_id(BORDERS_PROGRAM), border_program_layout.uniforms.Colors.index, BORDER_COLORS_BINDING_POINT);
|
||||
glUniformBlockBinding(program_id(BORDERS_PROGRAM), border_program_layout.uniforms.GammaLUT.index, GAMMA_LUT_BINDING_POINT);
|
||||
UniformBlock border_colors = program_uniform_block(BORDERS_PROGRAM, "Colors");
|
||||
glUniformBlockBinding(program_id(BORDERS_PROGRAM), border_colors.index, BORDER_COLORS_BINDING_POINT);
|
||||
UniformBlock border_glut = program_uniform_block(BORDERS_PROGRAM, "GammaLUT");
|
||||
glUniformBlockBinding(program_id(BORDERS_PROGRAM), border_glut.index, GAMMA_LUT_BINDING_POINT);
|
||||
|
||||
// The gamma LUT is a constant, shared amongst all the programs that use it via a single UBO.
|
||||
if (shader_globals_vao_idx == -1) {
|
||||
shader_globals_vao_idx = create_vao();
|
||||
add_buffer_to_vao(shader_globals_vao_idx, GL_UNIFORM_BUFFER);
|
||||
add_buffer_to_vao(shader_globals_vao_idx, GL_UNIFORM_BUFFER);
|
||||
gamma_lut_buf_size = MAX(gamma_lut_buf_size, border_program_layout.uniforms.GammaLUT.size);
|
||||
gamma_lut_buf_size = MAX(gamma_lut_buf_size, border_glut.size);
|
||||
void *gamma_lut_buf = alloc_and_map_vao_buffer(shader_globals_vao_idx, gamma_lut_buf_size, GAMMA_LUT_GLOBAL_BUFFER, false);
|
||||
const ArrayInformation *a = &cell_program_layouts[CELL_PROGRAM].uniforms.gamma_lut;
|
||||
write_float_array_to_ubo(gamma_lut_buf, srgb_lut, arraysz(srgb_lut), a);
|
||||
const ArrayInformation a = program_uniform_array(CELL_PROGRAM, "gamma_lut");
|
||||
write_float_array_to_ubo(gamma_lut_buf, srgb_lut, arraysz(srgb_lut), &a);
|
||||
unmap_vao_buffer(shader_globals_vao_idx, GAMMA_LUT_GLOBAL_BUFFER);
|
||||
// The border colors change on every draw, but are shared amongst all border VAOs (only one is ever drawn at a time)
|
||||
alloc_vao_buffer(shader_globals_vao_idx, border_program_layout.uniforms.Colors.size, BORDER_COLORS_GLOBAL_BUFFER, GL_STREAM_DRAW);
|
||||
alloc_vao_buffer(shader_globals_vao_idx, border_colors.size, BORDER_COLORS_GLOBAL_BUFFER, GL_STREAM_DRAW);
|
||||
bind_vao_uniform_buffer(shader_globals_vao_idx, GAMMA_LUT_GLOBAL_BUFFER, GAMMA_LUT_BINDING_POINT);
|
||||
bind_vao_uniform_buffer(shader_globals_vao_idx, BORDER_COLORS_GLOBAL_BUFFER, BORDER_COLORS_BINDING_POINT);
|
||||
}
|
||||
|
|
@ -444,24 +392,23 @@ init_cell_program(void) {
|
|||
ssize_t
|
||||
create_cell_vao(void) {
|
||||
ssize_t vao_idx = create_vao();
|
||||
const struct CellUniforms *u = &cell_program_layouts[CELL_PROGRAM].uniforms;
|
||||
#define A(name, size, dtype, offset, stride) \
|
||||
add_attribute_to_vao(vao_idx, u->name, \
|
||||
add_attribute_to_vao(vao_idx, program_attribute_location(CELL_PROGRAM, name), \
|
||||
/*size=*/size, /*dtype=*/dtype, /*stride=*/stride, /*offset=*/offset, /*divisor=*/1);
|
||||
#define A1(name, size, dtype, offset) A(name, size, dtype, (void*)(offsetof(GPUCell, offset)), sizeof(GPUCell))
|
||||
|
||||
add_buffer_to_vao(vao_idx, GL_ARRAY_BUFFER);
|
||||
A1(sprite_idx, 2, GL_UNSIGNED_INT, sprite_idx);
|
||||
A1(colors, 3, GL_UNSIGNED_INT, fg);
|
||||
A1("sprite_idx", 2, GL_UNSIGNED_INT, sprite_idx);
|
||||
A1("colors", 3, GL_UNSIGNED_INT, fg);
|
||||
|
||||
add_buffer_to_vao(vao_idx, GL_ARRAY_BUFFER);
|
||||
A(is_selected, 1, GL_UNSIGNED_BYTE, NULL, 0);
|
||||
A("is_selected", 1, GL_UNSIGNED_BYTE, NULL, 0);
|
||||
|
||||
size_t bufnum = add_buffer_to_vao(vao_idx, GL_UNIFORM_BUFFER);
|
||||
alloc_vao_buffer(vao_idx, cell_program_layouts[CELL_PROGRAM].uniforms.CellRenderData.size, bufnum, GL_STREAM_DRAW);
|
||||
alloc_vao_buffer(vao_idx, program_uniform_block(CELL_PROGRAM, "CellRenderData").size, bufnum, GL_STREAM_DRAW);
|
||||
|
||||
size_t ctbufnum = add_buffer_to_vao(vao_idx, GL_UNIFORM_BUFFER);
|
||||
alloc_vao_buffer(vao_idx, cell_program_layouts[CELL_PROGRAM].uniforms.ColorTable.size, ctbufnum, GL_STATIC_DRAW);
|
||||
alloc_vao_buffer(vao_idx, program_uniform_block(CELL_PROGRAM, "ColorTable").size, ctbufnum, GL_STATIC_DRAW);
|
||||
|
||||
return vao_idx;
|
||||
#undef A
|
||||
|
|
@ -506,13 +453,13 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, i
|
|||
// Send the uniform data
|
||||
ColorProfile *cp = screen->paused_rendering.expires_at ? &screen->paused_rendering.color_profile : screen->color_profile;
|
||||
if (cp->dirty || screen->reload_all_gpu_data) {
|
||||
const ArrayInformation *ai = &cell_program_layouts[CELL_PROGRAM].uniforms.color_table;
|
||||
uint8_t *base = (uint8_t*)map_vao_buffer_for_write_only(vao_idx, color_table_buf, 0, cell_program_layouts[CELL_PROGRAM].uniforms.ColorTable.size);
|
||||
GLuint *ct_buf = (GLuint*)(base + ai->offset);
|
||||
copy_color_table_to_buffer(cp, ct_buf, 0, ai->stride / sizeof(GLuint));
|
||||
const ArrayInformation ai = program_uniform_array(CELL_PROGRAM, "color_table");
|
||||
uint8_t *base = (uint8_t*)map_vao_buffer_for_write_only(vao_idx, color_table_buf, 0, program_uniform_block(CELL_PROGRAM, "ColorTable").size);
|
||||
GLuint *ct_buf = (GLuint*)(base + ai.offset);
|
||||
copy_color_table_to_buffer(cp, ct_buf, 0, ai.stride / sizeof(GLuint));
|
||||
unmap_vao_buffer(vao_idx, color_table_buf);
|
||||
}
|
||||
struct GPUCellRenderData *rd = (struct GPUCellRenderData*)map_vao_buffer_for_write_only(vao_idx, uniform_buffer, 0, cell_program_layouts[CELL_PROGRAM].uniforms.CellRenderData.size);
|
||||
struct GPUCellRenderData *rd = (struct GPUCellRenderData*)map_vao_buffer_for_write_only(vao_idx, uniform_buffer, 0, program_uniform_block(CELL_PROGRAM, "CellRenderData").size);
|
||||
#define COLOR(name) colorprofile_to_color(cp, cp->overridden.name, cp->configured.name).rgb
|
||||
rd->default_fg = COLOR(default_fg);
|
||||
rd->highlight_fg = COLOR(highlight_fg); rd->highlight_bg = COLOR(highlight_bg);
|
||||
|
|
@ -682,17 +629,18 @@ cell_prepare_to_render(ssize_t vao_idx, Screen *screen, FONTS_DATA_HANDLE fonts_
|
|||
static void
|
||||
draw_graphics(int program, ImageRenderData *data, GLuint start, GLuint count, float extra_alpha) {
|
||||
bind_program(program);
|
||||
if (program != GRAPHICS_ALPHA_MASK_PROGRAM) glUniform1f(graphics_program_layouts[program].uniforms.extra_alpha, extra_alpha);
|
||||
if (program != GRAPHICS_ALPHA_MASK_PROGRAM) glUniform1f(program_uniform_location(program, "extra_alpha"), extra_alpha);
|
||||
glActiveTexture(GL_TEXTURE0 + GRAPHICS_UNIT);
|
||||
GraphicsUniforms *u = &graphics_program_layouts[program].uniforms;
|
||||
GLint src_rect_loc = program_uniform_location(program, "src_rect");
|
||||
GLint dest_rect_loc = program_uniform_location(program, "dest_rect");
|
||||
for (GLuint i=0; i < count;) {
|
||||
ImageRenderData *group = data + start + i;
|
||||
glBindTexture(GL_TEXTURE_2D, group->texture_id);
|
||||
if (group->group_count == 0) { i++; continue; }
|
||||
for (GLuint k=0; k < group->group_count; k++, i++) {
|
||||
ImageRenderData *rd = data + start + i;
|
||||
glUniform4f(u->src_rect, rd->src_rect.left, rd->src_rect.top, rd->src_rect.right, rd->src_rect.bottom);
|
||||
glUniform4f(u->dest_rect, rd->dest_rect.left, rd->dest_rect.top, rd->dest_rect.right, rd->dest_rect.bottom);
|
||||
glUniform4f(src_rect_loc, rd->src_rect.left, rd->src_rect.top, rd->src_rect.right, rd->src_rect.bottom);
|
||||
glUniform4f(dest_rect_loc, rd->dest_rect.left, rd->dest_rect.top, rd->dest_rect.right, rd->dest_rect.bottom);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -754,17 +702,17 @@ set_cell_uniforms(bool force) {
|
|||
float text_contrast = 1.0f + OPT(text_contrast) * 0.01f;
|
||||
float text_gamma_adjustment = OPT(text_gamma_adjustment) < 0.01f ? 1.0f : 1.0f / OPT(text_gamma_adjustment);
|
||||
for (int i = GRAPHICS_PROGRAM; i <= GRAPHICS_ALPHA_MASK_PROGRAM; i++) {
|
||||
bind_program(i); glUniform1i(graphics_program_layouts[i].uniforms.image, GRAPHICS_UNIT);
|
||||
bind_program(i); glUniform1i(program_uniform_location(i, "image"), GRAPHICS_UNIT);
|
||||
}
|
||||
for (int i = CELL_PROGRAM; i < CELL_PROGRAM_SENTINEL; i++) {
|
||||
bind_program(i); const CellUniforms *cu = &cell_program_layouts[i].uniforms;
|
||||
glUniform1i(cu->sprites, SPRITE_MAP_UNIT);
|
||||
glUniform1i(cu->sprite_decorations_map, SPRITE_DECORATIONS_MAP_UNIT);
|
||||
glUniform1f(cu->text_contrast, text_contrast);
|
||||
glUniform1f(cu->text_gamma_adjustment, text_gamma_adjustment);
|
||||
bind_program(i);
|
||||
glUniform1i(program_uniform_location(i, "sprites"), SPRITE_MAP_UNIT);
|
||||
glUniform1i(program_uniform_location(i, "sprite_decorations_map"), SPRITE_DECORATIONS_MAP_UNIT);
|
||||
glUniform1f(program_uniform_location(i, "text_contrast"), text_contrast);
|
||||
glUniform1f(program_uniform_location(i, "text_gamma_adjustment"), text_gamma_adjustment);
|
||||
}
|
||||
bind_program(BLIT_PROGRAM); glUniform1i(blit_program_layout.uniforms.image, GRAPHICS_UNIT);
|
||||
bind_program(SCREENSHOT_PROGRAM); glUniform1i(screenshot_program_layout.uniforms.image, GRAPHICS_UNIT);
|
||||
bind_program(BLIT_PROGRAM); glUniform1i(program_uniform_location(BLIT_PROGRAM, "image"), GRAPHICS_UNIT);
|
||||
bind_program(SCREENSHOT_PROGRAM); glUniform1i(program_uniform_location(SCREENSHOT_PROGRAM, "image"), GRAPHICS_UNIT);
|
||||
constants_set = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -803,9 +751,9 @@ draw_visual_bell_flash(GLfloat intensity, const color_type flash) {
|
|||
#undef C
|
||||
#define C(x) (x * intensity * attenuation)
|
||||
if (max_channel > 0.45) attenuation = 0.6f; // light color
|
||||
glUniform4f(tint_program_layout.uniforms.tint_color, C(r), C(g), C(b), C(1));
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "tint_color"), C(r), C(g), C(b), C(1));
|
||||
#undef C
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1, 1, 1, -1);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), -1, 1, 1, -1);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
|
||||
|
|
@ -846,9 +794,9 @@ draw_drag_preview_overlay(const UIRenderData *ui) {
|
|||
float a = intensity * 0.25f;
|
||||
color_type hint = get_flash_color(screen);
|
||||
#define C(shift) (srgb_color((hint >> shift) & 0xFF) * a)
|
||||
glUniform4f(tint_program_layout.uniforms.tint_color, C(16), C(8), C(0), a);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "tint_color"), C(16), C(8), C(0), a);
|
||||
#undef C
|
||||
glUniform4f(tint_program_layout.uniforms.edges, left, top, right, bottom);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), left, top, right, bottom);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
|
||||
|
|
@ -992,10 +940,10 @@ draw_window_number(const UIRenderData *ui) {
|
|||
bind_program(GRAPHICS_ALPHA_MASK_PROGRAM);
|
||||
ImageRenderData *ird = load_alpha_mask_texture(lr.width_px, lr.height_px, lr.canvas);
|
||||
gpu_data_for_image(ird, -1, 1, 1, -1);
|
||||
glUniform1i(graphics_program_layouts[GRAPHICS_ALPHA_MASK_PROGRAM].uniforms.image, GRAPHICS_UNIT);
|
||||
glUniform1i(program_uniform_location(GRAPHICS_ALPHA_MASK_PROGRAM, "image"), GRAPHICS_UNIT);
|
||||
color_type digit_color = colorprofile_to_color_with_fallback(ui->screen->color_profile, ui->screen->color_profile->overridden.highlight_bg, ui->screen->color_profile->configured.highlight_bg, ui->screen->color_profile->overridden.default_fg, ui->screen->color_profile->configured.default_fg);
|
||||
color_vec3(graphics_program_layouts[GRAPHICS_ALPHA_MASK_PROGRAM].uniforms.amask_fg, digit_color);
|
||||
glUniform4f(graphics_program_layouts[GRAPHICS_ALPHA_MASK_PROGRAM].uniforms.amask_bg_premult, 0.f, 0.f, 0.f, 0.f);
|
||||
color_vec3(program_uniform_location(GRAPHICS_ALPHA_MASK_PROGRAM, "amask_fg"), digit_color);
|
||||
glUniform4f(program_uniform_location(GRAPHICS_ALPHA_MASK_PROGRAM, "amask_bg_premult"), 0.f, 0.f, 0.f, 0.f);
|
||||
save_viewport_using_top_left_origin(
|
||||
ui->screen_left + letter_x, ui->screen_top + letter_y, lr.width_px, lr.height_px, ui->full_framebuffer_height);
|
||||
draw_graphics(GRAPHICS_ALPHA_MASK_PROGRAM, ird, 0, 1, 1.f);
|
||||
|
|
@ -1009,7 +957,7 @@ set_color_uniform_with_opacity(color_type color, float opacity) {
|
|||
float r = srgb_color((color >> 16) & 0xFF) * opacity;
|
||||
float g = srgb_color((color >> 8) & 0xFF) * opacity;
|
||||
float b = srgb_color(color & 0xFF) * opacity;
|
||||
glUniform4f(tint_program_layout.uniforms.tint_color, r, g, b, opacity);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "tint_color"), r, g, b, opacity);
|
||||
}
|
||||
|
||||
static color_type
|
||||
|
|
@ -1080,7 +1028,7 @@ draw_scrollbar(const UIRenderData *ui) {
|
|||
if (track_opacity > 0) {
|
||||
bind_program(TINT_PROGRAM);
|
||||
set_color_uniform_with_opacity(track_color, track_opacity);
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1.f, 1.f, 1.f, -1.f);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), -1.f, 1.f, 1.f, -1.f);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1093,16 +1041,16 @@ draw_scrollbar(const UIRenderData *ui) {
|
|||
restore_viewport();
|
||||
|
||||
bind_program(ROUNDED_RECT_PROGRAM);
|
||||
color_vec4(rounded_rect_program_layout.uniforms.color, bar_color, opacity);
|
||||
color_vec4(rounded_rect_program_layout.uniforms.background_color, 0, 0.0f);
|
||||
color_vec4(program_uniform_location(ROUNDED_RECT_PROGRAM, "color"), bar_color, opacity);
|
||||
color_vec4(program_uniform_location(ROUNDED_RECT_PROGRAM, "background_color"), 0, 0.0f);
|
||||
|
||||
float y = (float)ui->full_framebuffer_height - (float)(thumb_top_px + thumb_height_px);
|
||||
glUniform4f(rounded_rect_program_layout.uniforms.rect,
|
||||
glUniform4f(program_uniform_location(ROUNDED_RECT_PROGRAM, "rect"),
|
||||
(float)scrollbar_left, y,
|
||||
(float)scrollbar_width_px, (float)thumb_height_px);
|
||||
|
||||
float thickness = (float)MAX(scrollbar_width_px, thumb_height_px);
|
||||
glUniform2f(rounded_rect_program_layout.uniforms.params, thickness, (float)scrollbar_radius);
|
||||
glUniform2f(program_uniform_location(ROUNDED_RECT_PROGRAM, "params"), thickness, (float)scrollbar_radius);
|
||||
|
||||
save_viewport_using_top_left_origin(scrollbar_left, thumb_top_px,
|
||||
scrollbar_width_px, thumb_height_px,
|
||||
|
|
@ -1111,7 +1059,7 @@ draw_scrollbar(const UIRenderData *ui) {
|
|||
restore_viewport();
|
||||
} else {
|
||||
set_color_uniform_with_opacity(bar_color, opacity);
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1.f, thumb_top_gl, 1.f, thumb_bottom_gl);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), -1.f, thumb_top_gl, 1.f, thumb_bottom_gl);
|
||||
draw_quad(true, 0);
|
||||
restore_viewport();
|
||||
}
|
||||
|
|
@ -1154,16 +1102,16 @@ draw_progress_handle(const UIRenderData *ui, color_type bar_color, float opacity
|
|||
|
||||
if (bar_radius > 0) {
|
||||
bind_program(ROUNDED_RECT_PROGRAM);
|
||||
color_vec4(rounded_rect_program_layout.uniforms.color, bar_color, opacity);
|
||||
color_vec4(rounded_rect_program_layout.uniforms.background_color, 0, 0.0f);
|
||||
color_vec4(program_uniform_location(ROUNDED_RECT_PROGRAM, "color"), bar_color, opacity);
|
||||
color_vec4(program_uniform_location(ROUNDED_RECT_PROGRAM, "background_color"), 0, 0.0f);
|
||||
|
||||
float y = (float)ui->full_framebuffer_height - (float)(handle_top + handle_h);
|
||||
glUniform4f(rounded_rect_program_layout.uniforms.rect,
|
||||
glUniform4f(program_uniform_location(ROUNDED_RECT_PROGRAM, "rect"),
|
||||
(float)handle_left, y,
|
||||
(float)handle_w, (float)handle_h);
|
||||
|
||||
float thickness = (float)(is_horizontal ? handle_h : handle_w);
|
||||
glUniform2f(rounded_rect_program_layout.uniforms.params, thickness, (float)bar_radius);
|
||||
glUniform2f(program_uniform_location(ROUNDED_RECT_PROGRAM, "params"), thickness, (float)bar_radius);
|
||||
|
||||
save_viewport_using_top_left_origin(handle_left, handle_top, handle_w, handle_h, ui->full_framebuffer_height);
|
||||
draw_quad(true, 0);
|
||||
|
|
@ -1180,11 +1128,11 @@ draw_progress_handle(const UIRenderData *ui, color_type bar_color, float opacity
|
|||
if (is_horizontal) {
|
||||
// edges: left, top, right, bottom
|
||||
save_viewport_using_top_left_origin(track_left, track_top, track_width, track_height, ui->full_framebuffer_height);
|
||||
glUniform4f(tint_program_layout.uniforms.edges, start_gl, 1.f, end_gl, -1.f);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), start_gl, 1.f, end_gl, -1.f);
|
||||
} else {
|
||||
save_viewport_using_top_left_origin(track_left, track_top, track_width, track_height, ui->full_framebuffer_height);
|
||||
// For vertical: start_gl is top in GL coords (inverted y), so bottom_gl = -end_gl, top_gl = -start_gl
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1.f, -start_gl, 1.f, -end_gl);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), -1.f, -start_gl, 1.f, -end_gl);
|
||||
}
|
||||
draw_quad(true, 0);
|
||||
restore_viewport();
|
||||
|
|
@ -1269,7 +1217,7 @@ draw_progress_bar(const UIRenderData *ui) {
|
|||
if (track_opacity > 0) {
|
||||
bind_program(TINT_PROGRAM);
|
||||
set_color_uniform_with_opacity(track_color, track_opacity);
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1.f, 1.f, 1.f, -1.f);
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), -1.f, 1.f, 1.f, -1.f);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
restore_viewport();
|
||||
|
|
@ -1366,7 +1314,7 @@ call_cell_program(int program, const UIRenderData *ui, ssize_t vao_idx, bool for
|
|||
CELL_BUFFERS;
|
||||
bind_vao_uniform_buffer(vao_idx, uniform_buffer, CELL_RENDER_DATA_BINDING_POINT);
|
||||
bind_vao_uniform_buffer(vao_idx, color_table_buffer, COLOR_TABLE_BINDING_POINT);
|
||||
glUniform1ui(cell_program_layouts[program].uniforms.draw_bg_bitfield, draw_bg_bitfield);
|
||||
glUniform1ui(program_uniform_location(program, "draw_bg_bitfield"), draw_bg_bitfield);
|
||||
if (for_final_output) glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
draw_quad(!for_final_output, render_lines_for_screen(ui->screen) * ui->screen->columns);
|
||||
if (for_final_output) glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
|
@ -1380,8 +1328,8 @@ draw_cells_without_layers(const UIRenderData *ui, ssize_t vao_idx) {
|
|||
static void
|
||||
draw_tint(const UIRenderData *ui) {
|
||||
bind_program(TINT_PROGRAM);
|
||||
color_vec4_premult(tint_program_layout.uniforms.tint_color, ui->background_color, OPT(background_tint));
|
||||
glUniform4f(tint_program_layout.uniforms.edges, -1, 1, 1, -1);
|
||||
color_vec4_premult(program_uniform_location(TINT_PROGRAM, "tint_color"), ui->background_color, OPT(background_tint));
|
||||
glUniform4f(program_uniform_location(TINT_PROGRAM, "edges"), -1, 1, 1, -1);
|
||||
draw_quad(true, 0);
|
||||
}
|
||||
|
||||
|
|
@ -1489,10 +1437,9 @@ create_border_vao(void) {
|
|||
ssize_t vao_idx = create_vao();
|
||||
|
||||
add_buffer_to_vao(vao_idx, GL_ARRAY_BUFFER);
|
||||
const BorderUniforms *u = &border_program_layout.uniforms;
|
||||
add_attribute_to_vao(vao_idx, u->rect,
|
||||
add_attribute_to_vao(vao_idx, program_attribute_location(BORDERS_PROGRAM, "rect"),
|
||||
/*size=*/4, /*dtype=*/GL_FLOAT, /*stride=*/sizeof(BorderRect), /*offset=*/(void*)offsetof(BorderRect, left), /*divisor=*/1);
|
||||
add_attribute_to_vao(vao_idx, u->rect_color,
|
||||
add_attribute_to_vao(vao_idx, program_attribute_location(BORDERS_PROGRAM, "rect_color"),
|
||||
/*size=*/1, /*dtype=*/GL_UNSIGNED_INT, /*stride=*/sizeof(BorderRect), /*offset=*/(void*)(offsetof(BorderRect, color)), /*divisor=*/1);
|
||||
|
||||
return vao_idx;
|
||||
|
|
@ -1517,10 +1464,11 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu
|
|||
OPT(bell_border_color), OPT(tab_bar_background), OPT(tab_bar_margin_color),
|
||||
w->tab_bar_edge_color.left, w->tab_bar_edge_color.right
|
||||
};
|
||||
void *colors_buf = map_vao_buffer_for_write_only(shader_globals_vao_idx, BORDER_COLORS_GLOBAL_BUFFER, 0, border_program_layout.uniforms.Colors.size);
|
||||
write_uint_array_to_ubo(colors_buf, colors, arraysz(colors), &border_program_layout.uniforms.colors);
|
||||
void *colors_buf = map_vao_buffer_for_write_only(shader_globals_vao_idx, BORDER_COLORS_GLOBAL_BUFFER, 0, program_uniform_block(BORDERS_PROGRAM, "Colors").size);
|
||||
const ArrayInformation border_colors_array = program_uniform_array(BORDERS_PROGRAM, "colors");
|
||||
write_uint_array_to_ubo(colors_buf, colors, arraysz(colors), &border_colors_array);
|
||||
unmap_vao_buffer(shader_globals_vao_idx, BORDER_COLORS_GLOBAL_BUFFER);
|
||||
glUniform1f(border_program_layout.uniforms.background_opacity, background_opacity);
|
||||
glUniform1f(program_uniform_location(BORDERS_PROGRAM, "background_opacity"), background_opacity);
|
||||
if (!w->needs_layers) glEnable(GL_FRAMEBUFFER_SRGB);
|
||||
draw_quad(has_background_image, num_border_rects);
|
||||
if (!w->needs_layers) glDisable(GL_FRAMEBUFFER_SRGB);
|
||||
|
|
@ -1534,19 +1482,19 @@ void
|
|||
draw_cursor_trail(CursorTrail *trail, Window *active_window) {
|
||||
bind_program(TRAIL_PROGRAM);
|
||||
|
||||
glUniform4fv(trail_program_layout.uniforms.x_coords, 1, trail->corner_x);
|
||||
glUniform4fv(trail_program_layout.uniforms.y_coords, 1, trail->corner_y);
|
||||
glUniform4fv(program_uniform_location(TRAIL_PROGRAM, "x_coords"), 1, trail->corner_x);
|
||||
glUniform4fv(program_uniform_location(TRAIL_PROGRAM, "y_coords"), 1, trail->corner_y);
|
||||
|
||||
glUniform2fv(trail_program_layout.uniforms.cursor_edge_x, 1, trail->cursor_edge_x);
|
||||
glUniform2fv(trail_program_layout.uniforms.cursor_edge_y, 1, trail->cursor_edge_y);
|
||||
glUniform2fv(program_uniform_location(TRAIL_PROGRAM, "cursor_edge_x"), 1, trail->cursor_edge_x);
|
||||
glUniform2fv(program_uniform_location(TRAIL_PROGRAM, "cursor_edge_y"), 1, trail->cursor_edge_y);
|
||||
|
||||
color_type trail_color = OPT(cursor_trail_color);
|
||||
if (trail_color == 0) { // 0 means "none" was specified
|
||||
trail_color = active_window ? active_window->render_data.screen->last_rendered.cursor_bg : OPT(foreground);
|
||||
}
|
||||
color_vec3(trail_program_layout.uniforms.trail_color, trail_color);
|
||||
color_vec3(program_uniform_location(TRAIL_PROGRAM, "trail_color"), trail_color);
|
||||
|
||||
glUniform1f(trail_program_layout.uniforms.trail_opacity, trail->opacity);
|
||||
glUniform1f(program_uniform_location(TRAIL_PROGRAM, "trail_opacity"), trail->opacity);
|
||||
|
||||
draw_quad(true, 0);
|
||||
unbind_program();
|
||||
|
|
@ -1597,11 +1545,11 @@ draw_bg_image(OSWindow *os_window, Tab *tab) {
|
|||
bind_program(BGIMAGE_PROGRAM);
|
||||
// altough we dont use this VO we need to ensure *some* VAO is bound at this point.
|
||||
bind_vertex_array(tab->border_rects.vao_idx);
|
||||
glUniform4f(bgimage_program_layout.uniforms.sizes, vwidth, vheight, iwidth, iheight);
|
||||
glUniform1f(bgimage_program_layout.uniforms.tiled, tiled);
|
||||
glUniform4f(bgimage_program_layout.uniforms.positions, left, top, right, bottom);
|
||||
glUniform1i(bgimage_program_layout.uniforms.image, GRAPHICS_UNIT);
|
||||
color_vec4(bgimage_program_layout.uniforms.background, s.bgcolor, s.opacity);
|
||||
glUniform4f(program_uniform_location(BGIMAGE_PROGRAM, "sizes"), vwidth, vheight, iwidth, iheight);
|
||||
glUniform1f(program_uniform_location(BGIMAGE_PROGRAM, "tiled"), tiled);
|
||||
glUniform4f(program_uniform_location(BGIMAGE_PROGRAM, "positions"), left, top, right, bottom);
|
||||
glUniform1i(program_uniform_location(BGIMAGE_PROGRAM, "image"), GRAPHICS_UNIT);
|
||||
color_vec4(program_uniform_location(BGIMAGE_PROGRAM, "background"), s.bgcolor, s.opacity);
|
||||
glActiveTexture(GL_TEXTURE0 + GRAPHICS_UNIT);
|
||||
glBindTexture(GL_TEXTURE_2D, bg->texture_id);
|
||||
draw_quad(false, 0);
|
||||
|
|
@ -1621,9 +1569,9 @@ draw_centered_alpha_mask(size_t screen_width, size_t screen_height, size_t width
|
|||
ImageRenderData *data = load_alpha_mask_texture(width, height, canvas);
|
||||
gpu_data_for_centered_image(data, screen_width, screen_height, width, height);
|
||||
bind_program(GRAPHICS_ALPHA_MASK_PROGRAM);
|
||||
glUniform1i(graphics_program_layouts[GRAPHICS_ALPHA_MASK_PROGRAM].uniforms.image, GRAPHICS_UNIT);
|
||||
color_vec3(graphics_program_layouts[GRAPHICS_ALPHA_MASK_PROGRAM].uniforms.amask_fg, OPT(foreground));
|
||||
color_vec4_premult(graphics_program_layouts[GRAPHICS_ALPHA_MASK_PROGRAM].uniforms.amask_bg_premult, OPT(background), background_opacity);
|
||||
glUniform1i(program_uniform_location(GRAPHICS_ALPHA_MASK_PROGRAM, "image"), GRAPHICS_UNIT);
|
||||
color_vec3(program_uniform_location(GRAPHICS_ALPHA_MASK_PROGRAM, "amask_fg"), OPT(foreground));
|
||||
color_vec4_premult(program_uniform_location(GRAPHICS_ALPHA_MASK_PROGRAM, "amask_bg_premult"), OPT(background), background_opacity);
|
||||
draw_graphics(GRAPHICS_ALPHA_MASK_PROGRAM, data, 0, 1, 1.0);
|
||||
}
|
||||
|
||||
|
|
@ -1700,8 +1648,8 @@ stop_os_window_rendering(OSWindow *os_window, Tab *tab, Window *active_window) {
|
|||
glBindTexture(GL_TEXTURE_2D, global_state.layers_render_texture.texture_id);
|
||||
float sx = global_state.layers_render_texture.width > 0 ? (float)os_window->viewport_width / (float)global_state.layers_render_texture.width : 1.f;
|
||||
float sy = global_state.layers_render_texture.height > 0 ? (float)os_window->viewport_height / (float)global_state.layers_render_texture.height : 1.f;
|
||||
glUniform4f(blit_program_layout.uniforms.src_rect, 0, sy, sx, 0);
|
||||
glUniform4f(blit_program_layout.uniforms.dest_rect, -1, 1, 1, -1);
|
||||
glUniform4f(program_uniform_location(BLIT_PROGRAM, "src_rect"), 0, sy, sx, 0);
|
||||
glUniform4f(program_uniform_location(BLIT_PROGRAM, "dest_rect"), -1, 1, 1, -1);
|
||||
restore_viewport();
|
||||
if (os_window->live_resize.in_progress) save_viewport_using_top_left_origin(
|
||||
0, 0, os_window->viewport_width, os_window->viewport_height, os_window->live_resize.height);
|
||||
|
|
@ -1776,13 +1724,13 @@ take_screenshot_of_rectangular_region(OSWindow *os_window, Region region, unsign
|
|||
float src_right_norm = (float)region.right / (float)vw;
|
||||
float src_bottom_norm = (float)(vh - region.bottom) / (float)vh;
|
||||
float src_top_norm = (float)(vh - region.top) / (float)vh;
|
||||
glUniform4f(screenshot_program_layout.uniforms.src_rect, src_left_norm, src_top_norm, src_right_norm, src_bottom_norm);
|
||||
glUniform4f(program_uniform_location(SCREENSHOT_PROGRAM, "src_rect"), src_left_norm, src_top_norm, src_right_norm, src_bottom_norm);
|
||||
|
||||
// Set destination rectangle (NDC coordinates: -1 to 1)
|
||||
glUniform4f(screenshot_program_layout.uniforms.dest_rect, -1.0f, -1.0f, 1.0f, 1.0f);
|
||||
glUniform4f(program_uniform_location(SCREENSHOT_PROGRAM, "dest_rect"), -1.0f, -1.0f, 1.0f, 1.0f);
|
||||
|
||||
// Set the source texture size for proper downscaling
|
||||
glUniform2f(screenshot_program_layout.uniforms.src_size, (float)vw, (float)vh);
|
||||
glUniform2f(program_uniform_location(SCREENSHOT_PROGRAM, "src_size"), (float)vw, (float)vh);
|
||||
|
||||
// Bind the source texture
|
||||
glActiveTexture(GL_TEXTURE0 + GRAPHICS_UNIT);
|
||||
|
|
@ -1831,9 +1779,9 @@ attach_shaders(PyObject *sources, GLuint program_id, GLenum shader_type) {
|
|||
|
||||
static PyObject*
|
||||
compile_program(PyObject UNUSED *self, PyObject *args) {
|
||||
PyObject *vertex_shaders, *fragment_shaders;
|
||||
PyObject *vertex_shaders, *fragment_shaders, *metadata;
|
||||
int which, allow_recompile = 0;
|
||||
if (!PyArg_ParseTuple(args, "iO!O!|p", &which, &PyTuple_Type, &vertex_shaders, &PyTuple_Type, &fragment_shaders, &allow_recompile)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "iO!O!O!|p", &which, &PyTuple_Type, &vertex_shaders, &PyTuple_Type, &fragment_shaders, &PyDict_Type, &metadata, &allow_recompile)) return NULL;
|
||||
if (which < 0 || which >= NUM_PROGRAMS) { PyErr_Format(PyExc_ValueError, "Unknown program: %d", which); return NULL; }
|
||||
Program *program = program_ptr(which);
|
||||
if (program->id != 0) {
|
||||
|
|
@ -1856,6 +1804,7 @@ compile_program(PyObject UNUSED *self, PyObject *args) {
|
|||
}
|
||||
#undef fail_compile
|
||||
init_uniforms(which);
|
||||
set_program_layout(which, metadata);
|
||||
return Py_BuildValue("I", program->id);
|
||||
}
|
||||
|
||||
|
|
@ -1911,6 +1860,7 @@ static PyMethodDef module_methods[] = {
|
|||
static void
|
||||
finalize(void) {
|
||||
default_visual_bell_animation = free_animation(default_visual_bell_animation);
|
||||
free_program_layouts();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
|||
|
|
@ -191,17 +191,18 @@ class LoadShaderPrograms:
|
|||
opts = self.get_options()
|
||||
self.text_old_gamma = opts.text_composition_strategy == 'legacy'
|
||||
self.text_fg_override_threshold = opts.text_fg_override_threshold
|
||||
metadata = load_glsl_metadata()
|
||||
def cell(prog: int) -> None:
|
||||
v = cell_variant(opts, program=prog)
|
||||
vert, frag = glsl_shaders('cell', variant_name(v, default_cell_variant))
|
||||
compile_program(prog, (vert,), (frag,), allow_recompile)
|
||||
compile_program(prog, (vert,), (frag,), metadata['cell'], allow_recompile)
|
||||
cell(CELL_PROGRAM), cell(CELL_BG_PROGRAM), cell(CELL_FG_PROGRAM)
|
||||
for prog, vname in {
|
||||
GRAPHICS_PROGRAM: '', GRAPHICS_ALPHA_MASK_PROGRAM: 'alpha_mask',
|
||||
GRAPHICS_PREMULT_PROGRAM: 'premult',
|
||||
}.items():
|
||||
vert, frag = glsl_shaders('graphics', vname)
|
||||
compile_program(prog, (vert,), (frag,), allow_recompile)
|
||||
compile_program(prog, (vert,), (frag,), metadata['graphics'], allow_recompile)
|
||||
for name, prog in {
|
||||
'bgimage': BGIMAGE_PROGRAM,
|
||||
'tint': TINT_PROGRAM,
|
||||
|
|
@ -212,7 +213,7 @@ class LoadShaderPrograms:
|
|||
'border': BORDERS_PROGRAM,
|
||||
}.items():
|
||||
vert, frag = glsl_shaders(name)
|
||||
compile_program(prog, (vert,), (frag,), allow_recompile)
|
||||
compile_program(prog, (vert,), (frag,), metadata[name], allow_recompile)
|
||||
init_cell_program()
|
||||
|
||||
|
||||
|
|
@ -719,55 +720,28 @@ def write_if_changed(dest: str, text: str) -> None:
|
|||
f.write(text)
|
||||
|
||||
|
||||
def write_glsl_header(dest_dir: str, dest: str = 'kitty/glsl-uniforms.h') -> None:
|
||||
def write_glsl_metadata(dest_dir: str, dest: str = 'glsl-uniforms.json') -> None:
|
||||
metadata_map = {}
|
||||
for x in glob.glob(os.path.join(dest_dir, '*.glsl.json')):
|
||||
shader_name = shader_name_from_path(x)
|
||||
if '.' in shader_name:
|
||||
continue
|
||||
with open(x) as f:
|
||||
d = json.load(f)
|
||||
metadata_map[shader_name] = GLSLMetadata.fromdict(d)
|
||||
m = GLSLMetadata.fromdict(d)
|
||||
metadata_map[shader_name] = {
|
||||
'loose_uniforms': m.loose_uniforms,
|
||||
'uniform_structs': m.uniform_structs,
|
||||
'input_locations': m.input_locations,
|
||||
'uniform_struct_names': m.uniform_struct_names,
|
||||
}
|
||||
write_if_changed(os.path.join(dest_dir, dest), json.dumps(metadata_map, indent=2, sort_keys=True))
|
||||
|
||||
lines = ['// generated by slang.py DO NOT EDIT', '#include "gl.h"', '']
|
||||
a = lines.append
|
||||
for name in sorted(metadata_map):
|
||||
if '.' in name:
|
||||
continue
|
||||
m = metadata_map[name]
|
||||
struct_name = name.capitalize() + 'Uniforms'
|
||||
a('')
|
||||
a(f'typedef struct {struct_name} {{') # }}
|
||||
for u in sorted(m.loose_uniforms):
|
||||
a(f' int {u};')
|
||||
if m.input_locations:
|
||||
a(' // Vertex Input locations')
|
||||
for u in sorted(m.input_locations):
|
||||
a(f' int {u};')
|
||||
if m.uniform_structs:
|
||||
a(' // Uniform block locations')
|
||||
for u in sorted(m.uniform_structs):
|
||||
a(f' UniformBlock {u};')
|
||||
for v in sorted(m.uniform_structs[u]):
|
||||
vv = m.uniform_structs[u][v]
|
||||
if ']' in vv:
|
||||
a(f' ArrayInformation {v};')
|
||||
|
||||
a(f'}} {struct_name};')
|
||||
a('')
|
||||
a(f'static inline void get_uniform_locations_{name}(int program, {struct_name} *ans) {{') # }}
|
||||
for u in sorted(m.loose_uniforms):
|
||||
a(f' ans->{u} = get_uniform_location(program, "{m.loose_uniforms[u]}");')
|
||||
for u in sorted(m.input_locations):
|
||||
a(f' ans->{u} = {m.input_locations[u]};')
|
||||
for u in sorted(m.uniform_structs):
|
||||
a(f' ans->{u}.index = block_index(program, "{m.uniform_struct_names[u]}");')
|
||||
a(f' ans->{u}.size = block_size(program, ans->{u}.index);')
|
||||
for v in sorted(m.uniform_structs[u]):
|
||||
vv = m.uniform_structs[u][v]
|
||||
if ']' in vv:
|
||||
vv = vv.partition('[')[0] # ]
|
||||
a(f' ans->{v} = get_uniform_array_information(program, "{vv}");')
|
||||
a('}')
|
||||
write_if_changed(dest, '\n'.join(lines))
|
||||
@lru_cache(maxsize=1)
|
||||
def load_glsl_metadata() -> dict[str, dict[str, Any]]:
|
||||
with open(os.path.join(shaders_dir, 'glsl-uniforms.json')) as f:
|
||||
return dict(json.load(f))
|
||||
# }}}
|
||||
|
||||
|
||||
|
|
@ -844,7 +818,7 @@ def compile_builtin_shaders(build_dir: str, dest_dir: str, parallel_run: Paralle
|
|||
if shutil.which('glslangValidator'):
|
||||
from kitty.shaders.validate_shaders import validation_command_for_file
|
||||
parallel_run((True, f'Validating |{os.path.basename(x)}| ...', validation_command_for_file(x)) for x in built_glsl_files)
|
||||
write_glsl_header(dest_dir)
|
||||
write_glsl_metadata(dest_dir)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue