diff --git a/kitty/gl.h b/kitty/gl.h index fcf964033..b10459d6c 100644 --- a/kitty/gl.h +++ b/kitty/gl.h @@ -607,10 +607,13 @@ static PyObject* replace_or_create_buffer(PyObject UNUSED *self, PyObject *args) { int usage, buftype; unsigned long size, prev_sz, target; + void *data = NULL; PyObject *address; if (!PyArg_ParseTuple(args, "kkkO!ii", &target, &size, &prev_sz, &PyLong_Type, &address, &usage, &buftype)) return NULL; - void *data = PyLong_AsVoidPtr(address); - if (data == NULL) { PyErr_SetString(PyExc_TypeError, "Not a valid data pointer"); return NULL; } + if (size) { + data = PyLong_AsVoidPtr(address); + if (data == NULL) { PyErr_SetString(PyExc_TypeError, "Not a valid data pointer"); return NULL; } + } glBindBuffer(buftype, target); if (prev_sz == 0 || prev_sz != size) glBufferData(buftype, size, data, usage); else glBufferSubData(buftype, 0, size, data); @@ -619,6 +622,23 @@ replace_or_create_buffer(PyObject UNUSED *self, PyObject *args) { Py_RETURN_NONE; } +static PyObject* +MapBuffer(PyObject UNUSED *self, PyObject *args) { + int target, access; + if (!PyArg_ParseTuple(args, "ii", &target, &access)) return NULL; + void *address = glMapBuffer(target, access); + if (address == NULL) { SET_GL_ERR; return NULL; } + return PyLong_FromVoidPtr(address); +} + +static PyObject* +UnmapBuffer(PyObject UNUSED *self, PyObject *args) { + int target; + if (!PyArg_ParseTuple(args, "i", &target)) return NULL; + if (!glUnmapBuffer(target)) { SET_GL_ERR; return NULL; } + Py_RETURN_NONE; +} + static PyObject* TexParameteri(PyObject UNUSED *self, PyObject *args) { int target, name, param; @@ -810,8 +830,9 @@ int add_module_gl_constants(PyObject *module) { GLC(GL_TEXTURE_WRAP_S); GLC(GL_TEXTURE_WRAP_T); GLC(GL_UNPACK_ALIGNMENT); GLC(GL_R8); GLC(GL_RED); GLC(GL_UNSIGNED_BYTE); GLC(GL_R32UI); GLC(GL_RGB32UI); GLC(GL_RGBA); - GLC(GL_TEXTURE_BUFFER); GLC(GL_STATIC_DRAW); GLC(GL_STREAM_DRAW); - GLC(GL_SRC_ALPHA); GLC(GL_ONE_MINUS_SRC_ALPHA); + GLC(GL_TEXTURE_BUFFER); GLC(GL_STATIC_DRAW); GLC(GL_STREAM_DRAW); GLC(GL_DYNAMIC_DRAW); + GLC(GL_SRC_ALPHA); GLC(GL_ONE_MINUS_SRC_ALPHA); + GLC(GL_WRITE_ONLY); GLC(GL_READ_ONLY); GLC(GL_READ_WRITE); GLC(GL_BLEND); GLC(GL_FLOAT); GLC(GL_UNSIGNED_INT); GLC(GL_ARRAY_BUFFER); GLC(GL_UNIFORM_BUFFER); return 1; } @@ -873,6 +894,8 @@ int add_module_gl_constants(PyObject *module) { METH(AttachShader, METH_VARARGS) \ METH(BindTexture, METH_VARARGS) \ METH(TexParameteri, METH_VARARGS) \ + METH(MapBuffer, METH_VARARGS) \ + METH(UnmapBuffer, METH_VARARGS) \ METH(PixelStorei, METH_VARARGS) \ METH(BindBuffer, METH_VARARGS) \ METH(BindBufferBase, METH_VARARGS) \ diff --git a/kitty/shaders.py b/kitty/shaders.py index bbbf54ddd..b476deaa8 100644 --- a/kitty/shaders.py +++ b/kitty/shaders.py @@ -6,7 +6,7 @@ import os import sys from collections import namedtuple from contextlib import contextmanager -from ctypes import addressof, sizeof +from ctypes import addressof, c_char, sizeof from functools import lru_cache from .fast_data_types import ( @@ -16,7 +16,7 @@ from .fast_data_types import ( GL_TEXTURE0, GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S, GL_TEXTURE_WRAP_T, GL_TRUE, GL_UNIFORM_BUFFER, GL_UNPACK_ALIGNMENT, GL_UNSIGNED_BYTE, GL_VERTEX_SHADER, - ITALIC, copy_image_sub_data, get_uniform_block_offsets, + GL_WRITE_ONLY, ITALIC, copy_image_sub_data, get_uniform_block_offsets, get_uniform_block_size, glActiveTexture, glAttachShader, glBindBuffer, glBindBufferBase, glBindTexture, glBindVertexArray, glCompileShader, glCopyImageSubData, glCreateProgram, glCreateShader, glDeleteBuffer, @@ -24,11 +24,12 @@ from .fast_data_types import ( glEnableVertexAttribArray, glGenBuffers, glGenTextures, glGenVertexArrays, glGetAttribLocation, glGetBufferSubData, glGetIntegerv, glGetProgramInfoLog, glGetProgramiv, glGetShaderInfoLog, glGetShaderiv, - glGetUniformBlockIndex, glGetUniformLocation, glLinkProgram, glPixelStorei, - glShaderSource, glTexParameteri, glTexStorage3D, glTexSubImage3D, - glUseProgram, glVertexAttribDivisor, glVertexAttribPointer, - render_dirty_sprites, replace_or_create_buffer, sprite_map_current_layout, - sprite_map_increment, sprite_map_set_layout, sprite_map_set_limits, sprite_map_free + glGetUniformBlockIndex, glGetUniformLocation, glLinkProgram, glMapBuffer, + glPixelStorei, glShaderSource, glTexParameteri, glTexStorage3D, + glTexSubImage3D, glUnmapBuffer, glUseProgram, glVertexAttribDivisor, + glVertexAttribPointer, render_dirty_sprites, replace_or_create_buffer, + sprite_map_current_layout, sprite_map_free, sprite_map_increment, + sprite_map_set_layout, sprite_map_set_limits ) from .fonts.render import render_cell from .utils import safe_print @@ -98,6 +99,19 @@ class BufferManager: # {{{ yield self.unbind(buf_id) + @contextmanager + def mapped_buffer(self, buf_sz, buf_id, usage=GL_STREAM_DRAW, access=GL_WRITE_ONLY): + prev_sz = self.sizes.get(buf_id, 0) + buf_type = self.types[buf_id] + if prev_sz != buf_sz: + replace_or_create_buffer(buf_id, buf_sz, 0, 0, usage, buf_type) + self.sizes[buf_id] = buf_sz + self.ctypes_types[buf_id] = c_char + with self.bound_buffer(buf_id): + address = glMapBuffer(buf_type, access) + yield address + glUnmapBuffer(buf_type) + buffer_manager = BufferManager() # }}}