Avoid a malloc when updating cell data

This commit is contained in:
Kovid Goyal
2016-11-21 15:12:06 +05:30
parent 96d8d29154
commit b1dba240ca

View File

@@ -3,8 +3,7 @@
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
from collections import namedtuple from collections import namedtuple
from copy import copy from ctypes import c_uint, addressof, memmove, sizeof
from ctypes import c_uint, addressof
from queue import Queue, Empty from queue import Queue, Empty
from threading import Lock from threading import Lock
@@ -122,10 +121,10 @@ def calculate_screen_geometry(cell_width, cell_height, screen_width, screen_heig
class RenderData: class RenderData:
__slots__ = 'viewport clear_color cell_data screen_geometry sprite_layout cursor'.split() __slots__ = 'viewport clear_color cell_data_changed screen_geometry sprite_layout cursor'.split()
def __init__(self, viewport=None, clear_color=None, cell_data=None, screen_geometry=None, sprite_layout=None, cursor=None): def __init__(self, viewport=None, clear_color=None, cell_data_changed=False, screen_geometry=None, sprite_layout=None, cursor=None):
self.viewport, self.clear_color, self.cell_data = viewport, clear_color, cell_data self.viewport, self.clear_color, self.cell_data_changed = viewport, clear_color, cell_data_changed
self.screen_geometry = screen_geometry self.screen_geometry = screen_geometry
self.sprite_layout = sprite_layout self.sprite_layout = sprite_layout
self.cursor = cursor self.cursor = cursor
@@ -144,7 +143,7 @@ def color_as_int(val):
class CharGrid: class CharGrid:
def __init__(self, screen, opts, window_width, window_height): def __init__(self, screen, opts, window_width, window_height):
self.lock = Lock() self.sprites_lock, self.buffer_lock = Lock(), Lock()
self.scrolled_by = 0 self.scrolled_by = 0
self.dpix, self.dpiy = get_logical_dpi() self.dpix, self.dpiy = get_logical_dpi()
self.width, self.height = window_width, window_height self.width, self.height = window_width, window_height
@@ -196,8 +195,10 @@ class CharGrid:
self.width, self.height = w, h self.width, self.height = w, h
self.screen_geometry = sg = calculate_screen_geometry(self.cell_width, self.cell_height, self.width, self.height) self.screen_geometry = sg = calculate_screen_geometry(self.cell_width, self.cell_height, self.width, self.height)
self.screen.resize(sg.ynum, sg.xnum) self.screen.resize(sg.ynum, sg.xnum)
self.main_sprite_map = (c_uint * (sg.ynum * sg.xnum * 9))() self.sprite_map_type = (c_uint * (sg.ynum * sg.xnum * 9))
self.scroll_sprite_map = (c_uint * (sg.ynum * sg.xnum * 9))() self.main_sprite_map = self.sprite_map_type()
self.scroll_sprite_map = self.sprite_map_type()
self.render_buf = self.sprite_map_type()
self.update_cell_data(add_viewport_data=True) self.update_cell_data(add_viewport_data=True)
self.clear_count = 4 self.clear_count = 4
@@ -222,7 +223,7 @@ class CharGrid:
if add_viewport_data: if add_viewport_data:
rd.viewport = Size(self.width, self.height) rd.viewport = Size(self.width, self.height)
rd.screen_geometry = self.screen_geometry rd.screen_geometry = self.screen_geometry
with self.lock: with self.sprites_lock:
cursor_changed = self.screen.update_cell_data( cursor_changed = self.screen.update_cell_data(
self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg, add_viewport_data) self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg, add_viewport_data)
if self.scrolled_by: if self.scrolled_by:
@@ -230,7 +231,10 @@ class CharGrid:
self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg, self.sprites.backend, self.color_profile, addressof(self.main_sprite_map), self.default_fg, self.default_bg,
self.scrolled_by, addressof(self.scroll_sprite_map)) self.scrolled_by, addressof(self.scroll_sprite_map))
rd.cell_data = copy(self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map) data = self.scroll_sprite_map if self.scrolled_by else self.main_sprite_map
with self.buffer_lock:
memmove(self.render_buf, data, sizeof(type(data)))
rd.cell_data_changed = True
if cursor_changed: if cursor_changed:
c = self.screen.cursor c = self.screen.cursor
rd.cursor = Cursor(c.x, c.y, c.hidden, c.shape, c.color, c.blink) rd.cursor = Cursor(c.x, c.y, c.hidden, c.shape, c.color, c.blink)
@@ -243,10 +247,11 @@ class CharGrid:
self.clear_count -= 1 self.clear_count -= 1
cell_data_changed = self.get_all_render_changes() cell_data_changed = self.get_all_render_changes()
with self.sprites: with self.sprites:
with self.lock: with self.sprites_lock:
self.sprites.render_dirty_cells() self.sprites.render_dirty_cells()
if cell_data_changed: if cell_data_changed:
self.sprites.set_sprite_map(self.last_render_data.cell_data) with self.buffer_lock:
self.sprites.set_sprite_map(self.render_buf)
data = self.last_render_data data = self.last_render_data
if data.screen_geometry is None: if data.screen_geometry is None:
@@ -264,7 +269,7 @@ class CharGrid:
rd = self.render_queue.get_nowait() rd = self.render_queue.get_nowait()
except Empty: except Empty:
break break
cell_data_changed |= rd.cell_data is not None cell_data_changed |= rd.cell_data_changed
if rd.clear_color is not None: if rd.clear_color is not None:
bg = rd.clear_color bg = rd.clear_color
glClearColor((bg >> 16) / 255, ((bg >> 8) & 0xff) / 255, (bg & 0xff) / 255, 1) glClearColor((bg >> 16) / 255, ((bg >> 8) & 0xff) / 255, (bg & 0xff) / 255, 1)