Migrate the cursor program
This commit is contained in:
parent
d2b3052918
commit
778c3c075a
@ -120,7 +120,7 @@ class Boss:
|
||||
self.tab_manager.init(startup_session)
|
||||
self.sprites = Sprites()
|
||||
self.sprites.do_layout(cell_size.width, cell_size.height)
|
||||
self.cell_program, self.cursor_program = load_shader_programs()
|
||||
self.cell_program = load_shader_programs()
|
||||
self.borders_program = BordersProgram()
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
|
||||
self.glfw_window.set_click_cursor(False)
|
||||
@ -395,10 +395,7 @@ class Boss:
|
||||
self.ui_timers.add_if_before(
|
||||
((n + 1) * d / 1000) - now, None)
|
||||
if draw_cursor:
|
||||
with self.cursor_program:
|
||||
active.char_grid.render_cursor(
|
||||
self.cursor_program,
|
||||
self.window_is_focused)
|
||||
active.char_grid.render_cursor(self.window_is_focused)
|
||||
|
||||
def gui_close_window(self, window):
|
||||
window.char_grid.destroy(self.cell_program)
|
||||
|
||||
@ -13,15 +13,15 @@ from .constants import (
|
||||
)
|
||||
from .fast_data_types import (
|
||||
CELL, CELL_PROGRAM, CURSOR_BEAM, CURSOR_BLOCK, CURSOR_PROGRAM,
|
||||
CURSOR_UNDERLINE, GL_BLEND, GL_FLOAT, GL_LINE_LOOP, GL_STATIC_DRAW,
|
||||
GL_TRIANGLE_FAN, GL_UNSIGNED_INT, GL_UNSIGNED_SHORT, glDisable,
|
||||
glDrawArrays, glDrawArraysInstanced, glEnable, glUniform1i, glUniform2f,
|
||||
glUniform2i, glUniform2ui, glUniform4f, glUniform4ui
|
||||
CURSOR_UNDERLINE, GL_FLOAT, GL_STATIC_DRAW, GL_TRIANGLE_FAN,
|
||||
GL_UNSIGNED_INT, GL_UNSIGNED_SHORT, compile_program, draw_cursor,
|
||||
glDrawArraysInstanced, glUniform1i, glUniform2f, glUniform2i, glUniform2ui,
|
||||
glUniform4f, glUniform4ui, init_cursor_program
|
||||
)
|
||||
from .rgb import to_color
|
||||
from .shaders import ShaderProgram, load_shaders
|
||||
from .utils import (
|
||||
color_as_int, color_from_int, get_logical_dpi, open_url,
|
||||
color_as_int, get_logical_dpi, open_url,
|
||||
set_primary_selection
|
||||
)
|
||||
|
||||
@ -56,10 +56,9 @@ class CellProgram(ShaderProgram): # {{{
|
||||
|
||||
def load_shader_programs():
|
||||
cell = CellProgram(CELL_PROGRAM, *load_shaders('cell'))
|
||||
cursor = ShaderProgram(CURSOR_PROGRAM, *load_shaders('cursor'))
|
||||
with cursor.array_object_creator() as add_attribute:
|
||||
cursor.vao_id = add_attribute.vao_id
|
||||
return cell, cursor
|
||||
compile_program(CURSOR_PROGRAM, *load_shaders('cursor'))
|
||||
init_cursor_program()
|
||||
return cell
|
||||
# }}}
|
||||
|
||||
|
||||
@ -243,7 +242,7 @@ class CharGrid:
|
||||
self.screen.color_profile, invert_colors=invert_colors,
|
||||
screen_reversed=self.screen_reversed)
|
||||
|
||||
def render_cursor(self, cursor_program, is_focused):
|
||||
def render_cursor(self, is_focused):
|
||||
cursor = self.current_cursor
|
||||
if not self.screen.cursor_visible or self.screen.scrolled_by:
|
||||
return
|
||||
@ -255,22 +254,15 @@ class CharGrid:
|
||||
return w * factor
|
||||
|
||||
sg = self.screen_geometry
|
||||
ul = cursor_program.uniform_location
|
||||
left = sg.xstart + cursor.x * sg.dx
|
||||
top = sg.ystart - cursor.y * sg.dy
|
||||
col = color_from_int(self.screen.color_profile.cursor_color)
|
||||
col = self.screen.color_profile.cursor_color
|
||||
shape = cursor.shape or self.default_cursor.shape
|
||||
alpha = self.opts.cursor_opacity
|
||||
if alpha < 1.0 and shape == CURSOR_BLOCK:
|
||||
glEnable(GL_BLEND)
|
||||
mult = self.screen.current_char_width()
|
||||
right = left + (width(1.5) if shape == CURSOR_BEAM else sg.dx * mult)
|
||||
bottom = top - sg.dy
|
||||
if shape == CURSOR_UNDERLINE:
|
||||
top = bottom + width(vert=False)
|
||||
glUniform4f(ul('color'), col[0] / 255.0, col[1] / 255.0, col[2] / 255.0, alpha)
|
||||
glUniform2f(ul('xpos'), left, right)
|
||||
glUniform2f(ul('ypos'), top, bottom)
|
||||
with cursor_program.bound_vertex_array(cursor_program.vao_id):
|
||||
glDrawArrays(GL_TRIANGLE_FAN if is_focused else GL_LINE_LOOP, 0, 4)
|
||||
glDisable(GL_BLEND)
|
||||
semi_transparent = alpha < 1.0 and shape == CURSOR_BLOCK
|
||||
draw_cursor(semi_transparent, is_focused, col, alpha, left, right, top, bottom)
|
||||
|
||||
@ -12,6 +12,7 @@
|
||||
#else
|
||||
#include <GL/glew.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
|
||||
static char glbuf[4096];
|
||||
|
||||
@ -109,7 +110,7 @@ enum ProgramNames { CELL_PROGRAM, CURSOR_PROGRAM, BORDERS_PROGRAM, NUM_PROGRAMS
|
||||
|
||||
typedef struct {
|
||||
char name[256];
|
||||
GLint size;
|
||||
GLint size, id;
|
||||
GLenum type;
|
||||
} Uniform;
|
||||
|
||||
@ -152,17 +153,19 @@ init_uniforms(int program) {
|
||||
Uniform *u = p->uniforms + i;
|
||||
glGetActiveUniform(p->id, (GLuint)i, sizeof(u->name)/sizeof(u->name[0]), NULL, &(u->size), &(u->type), u->name);
|
||||
if (set_error_from_gl()) return false;
|
||||
u->id = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static inline GLint
|
||||
uniform_location(int program, const char *name) {
|
||||
static inline Uniform*
|
||||
uniform(int program, const char *name) {
|
||||
for (GLint i = 0; i < programs[program].num_of_uniforms; i++) {
|
||||
if (strncmp(programs[program].uniforms[i].name, name, sizeof(programs[program].uniforms[i].name)) == 0) return i;
|
||||
Uniform *u = programs[program].uniforms + i;
|
||||
if (strncmp(u->name, name, sizeof(u->name)/sizeof(u->name[0])) == 0) return u;
|
||||
}
|
||||
return -1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline GLint
|
||||
@ -330,6 +333,41 @@ unbind_vertex_array() {
|
||||
}
|
||||
// }}}
|
||||
|
||||
// Cursor {{{
|
||||
enum CursorUniforms { CURSOR_color, CURSOR_xpos, CURSOR_ypos, NUM_CURSOR_UNIFORMS };
|
||||
static GLint cursor_uniform_locations[NUM_CURSOR_UNIFORMS] = {0};
|
||||
static ssize_t cursor_vertex_array;
|
||||
|
||||
static bool
|
||||
init_cursor_program() {
|
||||
Program *p = programs + CURSOR_PROGRAM;
|
||||
int left = NUM_CURSOR_UNIFORMS;
|
||||
cursor_vertex_array = create_vao();
|
||||
if (set_error_from_gl()) return false;
|
||||
for (int i = 0; i < p->num_of_uniforms; i++, left--) {
|
||||
#define SET_LOC(which) if (strcmp(p->uniforms[i].name, #which) == 0) cursor_uniform_locations[CURSOR_##which] = p->uniforms[i].id
|
||||
SET_LOC(color);
|
||||
else SET_LOC(xpos);
|
||||
else SET_LOC(ypos);
|
||||
else { set_local_error("Unknown uniform in cursor program"); return false; }
|
||||
}
|
||||
if (left) { set_local_error("Left over uniforms in cursor program"); return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
draw_cursor(bool semi_transparent, bool is_focused, color_type color, float alpha, float left, float right, float top, float bottom) {
|
||||
if (semi_transparent) glEnable(GL_BLEND);
|
||||
bind_program(CURSOR_PROGRAM); bind_vertex_array(cursor_vertex_array);
|
||||
glUniform4f(cursor_uniform_locations[CURSOR_color], ((color >> 16) & 0xff) / 255.0, ((color >> 8) & 0xff) / 255.0, (color & 0xff) / 255.0, alpha);
|
||||
glUniform2f(cursor_uniform_locations[CURSOR_xpos], left, right);
|
||||
glUniform2f(cursor_uniform_locations[CURSOR_ypos], top, bottom);
|
||||
glDrawArrays(is_focused ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
|
||||
unbind_vertex_array(); unbind_program();
|
||||
if (semi_transparent) glDisable(GL_BLEND);
|
||||
}
|
||||
// }}}
|
||||
|
||||
// Python API {{{
|
||||
static PyObject*
|
||||
enable_automatic_opengl_error_checking(PyObject UNUSED *self, PyObject *val) {
|
||||
@ -383,13 +421,15 @@ end:
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#define CHECK_ERROR if (_enable_error_checking) { translate_error(); if (PyErr_Occurred()) return NULL; }
|
||||
#define CHECK_ERROR_ALWAYS { translate_error(); if (PyErr_Occurred()) return NULL; }
|
||||
#define CHECK_ERROR if (_enable_error_checking) CHECK_ERROR_ALWAYS
|
||||
#define PYWRAP0(name) static PyObject* py##name(PyObject UNUSED *self)
|
||||
#define PYWRAP1(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args)
|
||||
#define PYWRAP2(name) static PyObject* py##name(PyObject UNUSED *self, PyObject *args, PyObject *kw)
|
||||
#define PA(fmt, ...) if(!PyArg_ParseTuple(args, fmt, __VA_ARGS__)) return NULL;
|
||||
#define ONE_INT(name) PYWRAP1(name) { name(PyLong_AsSsize_t(args)); CHECK_ERROR; Py_RETURN_NONE; }
|
||||
#define NO_ARG(name) PYWRAP0(name) { name(); CHECK_ERROR; Py_RETURN_NONE; }
|
||||
#define NO_ARG_CHECK(name) PYWRAP0(name) { name(); CHECK_ERROR_ALWAYS; Py_RETURN_NONE; }
|
||||
|
||||
ONE_INT(bind_program)
|
||||
NO_ARG(unbind_program)
|
||||
@ -422,6 +462,17 @@ PYWRAP2(add_attribute_to_vao) {
|
||||
|
||||
ONE_INT(bind_vertex_array)
|
||||
NO_ARG(unbind_vertex_array)
|
||||
NO_ARG_CHECK(init_cursor_program)
|
||||
|
||||
PYWRAP1(draw_cursor) {
|
||||
int semi_transparent, is_focused;
|
||||
unsigned int color;
|
||||
float alpha, left, right, top, bottom;
|
||||
PA("ppIfffff", &semi_transparent, &is_focused, &color, &alpha, &left, &right, &top, &bottom);
|
||||
draw_cursor(semi_transparent, is_focused, color, alpha, left, right, top, bottom);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
#define M(name, arg_type) {#name, (PyCFunction)name, arg_type, NULL}
|
||||
#define MW(name, arg_type) {#name, (PyCFunction)py##name, arg_type, NULL}
|
||||
@ -437,6 +488,8 @@ static PyMethodDef module_methods[] = {
|
||||
MW(unbind_vertex_array, METH_NOARGS),
|
||||
MW(bind_program, METH_O),
|
||||
MW(unbind_program, METH_NOARGS),
|
||||
MW(init_cursor_program, METH_NOARGS),
|
||||
MW(draw_cursor, METH_VARARGS),
|
||||
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user