Ensure GIL is not released when rendering sprites

This commit is contained in:
Kovid Goyal
2017-08-31 10:37:17 +05:30
parent 6127d2d122
commit f44d56b116
5 changed files with 20 additions and 20 deletions

View File

@@ -459,7 +459,7 @@ class Boss(Thread):
if isosx:
cocoa_update_title(self.glfw_window_title)
with self.sprites:
self.sprites.render_dirty_cells()
self.sprites.render_dirty_sprites()
tab.render()
render_data = {
window:

View File

@@ -153,8 +153,12 @@ class Sprites: # {{{
ans = second if is_second else first
return ans or render_cell()[0]
def render_dirty_cells(self):
render_dirty_sprites(self.render_cell, self.send_to_gpu)
def render_dirty_sprites(self):
ret = render_dirty_sprites()
if ret:
for text, bold, italic, is_second, x, y, z in ret:
cell = self.render_cell(text, bold, italic, is_second)
self.send_to_gpu(x, y, z, cell)
def send_to_gpu(self, x, y, z, buf):
xnum, ynum, znum = sprite_map_current_layout()

View File

@@ -182,34 +182,30 @@ update_cell_range_data(ScreenModes *modes, Line *line, unsigned int xstart, unsi
}
PyObject*
render_dirty_sprites(PyObject UNUSED *s_, PyObject *args) {
render_dirty_sprites(PyObject UNUSED *s_) {
#define render_dirty_cells_doc "Render all cells that are marked as dirty"
PyObject *render_cell, *send_to_gpu;
if (!PyArg_ParseTuple(args, "OO", &render_cell, &send_to_gpu)) return NULL;
if (!sprite_map.dirty) { Py_RETURN_NONE; }
PyObject *ans = PyList_New(0);
if (ans == NULL) return NULL;
for (size_t i = 0; i < sizeof(sprite_map.cache)/sizeof(sprite_map.cache[0]); i++) {
SpritePosition *sp = &(sprite_map.cache[i]);
while (sp) {
do {
if (sp->filled && !sp->rendered) {
PyObject *text = line_text_at(sp->ch & CHAR_MASK, sp->cc);
if (text == NULL) return NULL;
char_type attrs = sp->ch >> ATTRS_SHIFT;
bool bold = (attrs >> BOLD_SHIFT) & 1, italic = (attrs >> ITALIC_SHIFT) & 1;
PyObject *rcell = PyObject_CallFunctionObjArgs(render_cell, text, bold ? Py_True : Py_False, italic ? Py_True : Py_False, sp->is_second ? Py_True : Py_False, NULL);
PyObject *x = Py_BuildValue("OOOOHHH", text, bold ? Py_True : Py_False, italic ? Py_True : Py_False, sp->is_second ? Py_True : Py_False, sp->x, sp->y, sp->z);
Py_CLEAR(text);
if (rcell == NULL) return NULL;
PyObject *ret = PyObject_CallFunction(send_to_gpu, "IIIO", sp->x, sp->y, sp->z, rcell);
Py_CLEAR(rcell);
if (ret == NULL) return NULL;
Py_CLEAR(ret);
if (x == NULL) { Py_CLEAR(ans); return NULL; }
if (PyList_Append(ans, x) != 0) { Py_CLEAR(ans); return NULL; }
Py_CLEAR(x);
sp->rendered = true;
}
sp = sp->next;
}
} while(sp);
}
sprite_map.dirty = false;
Py_RETURN_NONE;
return ans;
}

View File

@@ -26,7 +26,7 @@ PyObject* sprite_map_increment();
SpritePosition* sprite_map_position_for(char_type ch, combining_type cc, bool is_second, int *error);
PyObject* sprite_position_for(PyObject UNUSED *self, PyObject *args);
bool update_cell_range_data(ScreenModes *modes, Line *line, unsigned int xstart, unsigned int xmax, unsigned int *data);
PyObject* render_dirty_sprites(PyObject UNUSED *self, PyObject *args);
PyObject* render_dirty_sprites(PyObject UNUSED *self);
#define SPRITE_FUNC_WRAPPERS \
{"sprite_map_set_limits", (PyCFunction)sprite_map_set_limits, METH_VARARGS, ""}, \
@@ -35,5 +35,5 @@ PyObject* render_dirty_sprites(PyObject UNUSED *self, PyObject *args);
{"sprite_map_free", (PyCFunction)sprite_map_free, METH_NOARGS, ""}, \
{"sprite_map_increment", (PyCFunction)sprite_map_increment, METH_NOARGS, ""}, \
{"sprite_position_for", (PyCFunction)sprite_position_for, METH_VARARGS, ""}, \
{"render_dirty_sprites", (PyCFunction)render_dirty_sprites, METH_VARARGS, ""}, \
{"render_dirty_sprites", (PyCFunction)render_dirty_sprites, METH_NOARGS, ""}, \

View File

@@ -302,7 +302,7 @@ class TabBar:
def render(self, cell_program, sprites):
' Must be called in the GUI thread '
if self.render_buf is not None:
sprites.render_dirty_cells()
sprites.render_dirty_sprites()
if self.vao_id is None:
self.vao_id = cell_program.create_sprite_map()
if self.dirty: