mirror of
https://github.com/kovidgoyal/kitty.git
synced 2026-06-26 02:41:54 +00:00
Infrastructure for loading shaders from multiple source files
Can eventually be used to share source code (functions) across many shaders
This commit is contained in:
parent
1ccfa8cda6
commit
444ec2484d
4 changed files with 66 additions and 37 deletions
|
|
@ -458,7 +458,7 @@ def add_window(os_window_id: int, tab_id: int, title: str) -> int:
|
|||
|
||||
|
||||
def compile_program(
|
||||
which: int, vertex_shader: str, fragment_shader: str, allow_recompile: bool = False
|
||||
which: int, vertex_shaders: Tuple[str, ...], fragment_shaders: Tuple[str, ...], allow_recompile: bool = False
|
||||
) -> int:
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -1070,12 +1070,25 @@ draw_borders(ssize_t vao_idx, unsigned int num_border_rects, BorderRect *rect_bu
|
|||
// }}}
|
||||
|
||||
// Python API {{{
|
||||
|
||||
static bool
|
||||
attach_shaders(PyObject *sources, GLuint program_id, GLenum shader_type) {
|
||||
for (Py_ssize_t i = 0; i < PyTuple_GET_SIZE(sources); i++) {
|
||||
PyObject *temp = PyTuple_GET_ITEM(sources, i);
|
||||
if (!PyUnicode_Check(temp)) { PyErr_SetString(PyExc_TypeError, "shaders must be strings"); return false; }
|
||||
const char *vertex_shader = PyUnicode_AsUTF8(temp);
|
||||
GLuint shader_id = compile_shader(shader_type, vertex_shader);
|
||||
glAttachShader(program_id, shader_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
compile_program(PyObject UNUSED *self, PyObject *args) {
|
||||
const char *vertex_shader, *fragment_shader;
|
||||
PyObject *vertex_shaders, *fragment_shaders;
|
||||
int which, allow_recompile = 0;
|
||||
GLuint vertex_shader_id = 0, fragment_shader_id = 0;
|
||||
if (!PyArg_ParseTuple(args, "iss|p", &which, &vertex_shader, &fragment_shader, &allow_recompile)) return NULL;
|
||||
if (!PyArg_ParseTuple(args, "iO!O!|p", &which, &PyTuple_Type, &vertex_shaders, &PyTuple_Type, &fragment_shaders, &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) {
|
||||
|
|
@ -1083,9 +1096,8 @@ compile_program(PyObject UNUSED *self, PyObject *args) {
|
|||
else { PyErr_SetString(PyExc_ValueError, "program already compiled"); return NULL; }
|
||||
}
|
||||
program->id = glCreateProgram();
|
||||
vertex_shader_id = compile_shader(GL_VERTEX_SHADER, vertex_shader);
|
||||
fragment_shader_id = compile_shader(GL_FRAGMENT_SHADER, fragment_shader);
|
||||
glAttachShader(program->id, vertex_shader_id);
|
||||
if (!attach_shaders(vertex_shaders, program->id, GL_VERTEX_SHADER)) return NULL;
|
||||
if (!attach_shaders(fragment_shaders, program->id, GL_FRAGMENT_SHADER)) return NULL;
|
||||
glAttachShader(program->id, fragment_shader_id);
|
||||
glLinkProgram(program->id);
|
||||
GLint ret = GL_FALSE;
|
||||
|
|
|
|||
|
|
@ -104,12 +104,25 @@ def platform_window_id(os_window_id: int) -> Optional[int]:
|
|||
return None
|
||||
|
||||
|
||||
def load_shaders(name: str, vertex_name: str = '', fragment_name: str = '') -> Tuple[str, str]:
|
||||
def load_shaders(name: str, vertex_name: str = '', fragment_name: str = '') -> Tuple[Tuple[str, ...], Tuple[str, ...]]:
|
||||
from .fast_data_types import GLSL_VERSION
|
||||
pat = re.compile(r'^#pragma kitty_include_shader <(.+?)>', re.MULTILINE)
|
||||
|
||||
def load(which: str, lname: str = '') -> str:
|
||||
def load_source(name: str) -> str:
|
||||
return read_kitty_resource(name).decode('utf-8').replace('GLSL_VERSION', str(GLSL_VERSION), 1)
|
||||
|
||||
def load_sources(name: str) -> Tuple[str, ...]:
|
||||
src = load_source(name)
|
||||
ans: Tuple[str, ...] = src,
|
||||
for m in pat.finditer(src):
|
||||
iname = m.group(1)
|
||||
ans += load_sources(iname)
|
||||
return ans
|
||||
|
||||
def load(which: str, lname: str = '') -> Tuple[str, ...]:
|
||||
lname = lname or name
|
||||
return read_kitty_resource(f'{lname}_{which}.glsl').decode('utf-8').replace('GLSL_VERSION', str(GLSL_VERSION), 1)
|
||||
main = f'{lname}_{which}.glsl'
|
||||
return load_sources(main)
|
||||
|
||||
return load('vertex', vertex_name), load('fragment', fragment_name)
|
||||
|
||||
|
|
|
|||
|
|
@ -393,7 +393,7 @@ class LoadShaderPrograms:
|
|||
self.text_old_gamma = opts.text_composition_strategy == 'legacy'
|
||||
self.text_fg_override_threshold = max(0, min(opts.text_fg_override_threshold, 100)) * 0.01
|
||||
compile_program(BLIT_PROGRAM, *load_shaders('blit'), allow_recompile)
|
||||
v, f = load_shaders('cell')
|
||||
vs, fs = load_shaders('cell')
|
||||
|
||||
for which, p in {
|
||||
'SIMPLE': CELL_PROGRAM,
|
||||
|
|
@ -401,41 +401,45 @@ class LoadShaderPrograms:
|
|||
'SPECIAL': CELL_SPECIAL_PROGRAM,
|
||||
'FOREGROUND': CELL_FG_PROGRAM,
|
||||
}.items():
|
||||
ff = f.replace('{WHICH_PROGRAM}', which)
|
||||
vv = multi_replace(
|
||||
v,
|
||||
WHICH_PROGRAM=which,
|
||||
REVERSE_SHIFT=REVERSE,
|
||||
STRIKE_SHIFT=STRIKETHROUGH,
|
||||
DIM_SHIFT=DIM,
|
||||
DECORATION_SHIFT=DECORATION,
|
||||
MARK_SHIFT=MARK,
|
||||
MARK_MASK=MARK_MASK,
|
||||
DECORATION_MASK=DECORATION_MASK,
|
||||
STRIKE_SPRITE_INDEX=NUM_UNDERLINE_STYLES + 1,
|
||||
)
|
||||
if self.text_fg_override_threshold != 0.:
|
||||
ff = ff.replace('#define NO_FG_OVERRIDE', f'#define FG_OVERRIDE {self.text_fg_override_threshold}')
|
||||
if self.text_old_gamma:
|
||||
ff = ff.replace('#define TEXT_NEW_GAMMA', '#define TEXT_OLD_GAMMA')
|
||||
if semi_transparent:
|
||||
vv = vv.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
||||
ff = ff.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
||||
compile_program(p, vv, ff, allow_recompile)
|
||||
vvs, ffs = [], []
|
||||
for v in vs:
|
||||
vv = multi_replace(
|
||||
v,
|
||||
WHICH_PROGRAM=which,
|
||||
REVERSE_SHIFT=REVERSE,
|
||||
STRIKE_SHIFT=STRIKETHROUGH,
|
||||
DIM_SHIFT=DIM,
|
||||
DECORATION_SHIFT=DECORATION,
|
||||
MARK_SHIFT=MARK,
|
||||
MARK_MASK=MARK_MASK,
|
||||
DECORATION_MASK=DECORATION_MASK,
|
||||
STRIKE_SPRITE_INDEX=NUM_UNDERLINE_STYLES + 1,
|
||||
)
|
||||
if semi_transparent:
|
||||
vv = vv.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
||||
vvs.append(vv)
|
||||
for f in fs:
|
||||
ff = f.replace('{WHICH_PROGRAM}', which)
|
||||
if self.text_fg_override_threshold != 0.:
|
||||
ff = ff.replace('#define NO_FG_OVERRIDE', f'#define FG_OVERRIDE {self.text_fg_override_threshold}')
|
||||
if self.text_old_gamma:
|
||||
ff = ff.replace('#define TEXT_NEW_GAMMA', '#define TEXT_OLD_GAMMA')
|
||||
if semi_transparent:
|
||||
ff = ff.replace('#define NOT_TRANSPARENT', '#define TRANSPARENT')
|
||||
ffs.append(ff)
|
||||
compile_program(p, tuple(vvs), tuple(ffs), allow_recompile)
|
||||
|
||||
v, f = load_shaders('graphics')
|
||||
vs, fs = load_shaders('graphics')
|
||||
for which, p in {
|
||||
'SIMPLE': GRAPHICS_PROGRAM,
|
||||
'PREMULT': GRAPHICS_PREMULT_PROGRAM,
|
||||
'ALPHA_MASK': GRAPHICS_ALPHA_MASK_PROGRAM,
|
||||
}.items():
|
||||
ff = f.replace('ALPHA_TYPE', which)
|
||||
compile_program(p, v, ff, allow_recompile)
|
||||
compile_program(p, vs, tuple(f.replace('ALPHA_TYPE', which) for f in fs), allow_recompile)
|
||||
|
||||
v, f = load_shaders('bgimage')
|
||||
compile_program(BGIMAGE_PROGRAM, v, f, allow_recompile)
|
||||
v, f = load_shaders('tint')
|
||||
compile_program(TINT_PROGRAM, v, f, allow_recompile)
|
||||
compile_program(BGIMAGE_PROGRAM, *load_shaders('bgimage'), allow_recompile)
|
||||
compile_program(TINT_PROGRAM, *load_shaders('tint'), allow_recompile)
|
||||
init_cell_program()
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue