Migrate the cursor program

This commit is contained in:
Kovid Goyal 2017-09-11 10:16:29 +05:30
parent d2b3052918
commit 778c3c075a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 73 additions and 31 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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 */
};