More OpenGL bindings
This commit is contained in:
parent
5d77499cb1
commit
99f788ead5
126
kitty/gl.h
126
kitty/gl.h
@ -214,6 +214,13 @@ GetShaderInfoLog(PyObject UNUSED *self, PyObject *val) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
ActiveTexture(PyObject UNUSED *self, PyObject *val) {
|
||||
long tex_id = PyLong_AsLong(val);
|
||||
glActiveTexture(tex_id);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
DeleteProgram(PyObject UNUSED *self, PyObject *val) {
|
||||
@ -249,6 +256,43 @@ GenVertexArrays(PyObject UNUSED *self, PyObject *val) {
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
GenTextures(PyObject UNUSED *self, PyObject *val) {
|
||||
GLuint arrays[256] = {0};
|
||||
unsigned long n = PyLong_AsUnsignedLong(val);
|
||||
if (n > 256) { PyErr_SetString(PyExc_ValueError, "Generating more than 256 textures in a single call is not supported"); return NULL; }
|
||||
glGenTextures(n, arrays);
|
||||
CHECK_ERROR;
|
||||
if (n == 1) return PyLong_FromUnsignedLong((unsigned long)arrays[0]);
|
||||
PyObject *ans = PyTuple_New(n);
|
||||
if (ans == NULL) return PyErr_NoMemory();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
PyObject *t = PyLong_FromUnsignedLong((unsigned long)arrays[i]);
|
||||
if (t == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); }
|
||||
PyTuple_SET_ITEM(ans, i, t);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
GenBuffers(PyObject UNUSED *self, PyObject *val) {
|
||||
GLuint arrays[256] = {0};
|
||||
unsigned long n = PyLong_AsUnsignedLong(val);
|
||||
if (n > 256) { PyErr_SetString(PyExc_ValueError, "Generating more than 256 buffers in a single call is not supported"); return NULL; }
|
||||
glGenBuffers(n, arrays);
|
||||
CHECK_ERROR;
|
||||
if (n == 1) return PyLong_FromUnsignedLong((unsigned long)arrays[0]);
|
||||
PyObject *ans = PyTuple_New(n);
|
||||
if (ans == NULL) return PyErr_NoMemory();
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
PyObject *t = PyLong_FromUnsignedLong((unsigned long)arrays[i]);
|
||||
if (t == NULL) { Py_DECREF(ans); return PyErr_NoMemory(); }
|
||||
PyTuple_SET_ITEM(ans, i, t);
|
||||
}
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
CreateShader(PyObject UNUSED *self, PyObject *val) {
|
||||
long shader_type = PyLong_AsLong(val);
|
||||
@ -321,6 +365,68 @@ BindVertexArray(PyObject UNUSED *self, PyObject *val) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
GetIntegerv(PyObject UNUSED *self, PyObject *val) {
|
||||
unsigned long program_id = PyLong_AsUnsignedLong(val);
|
||||
GLint ans = 0;
|
||||
glGetIntegerv(program_id, &ans);
|
||||
CHECK_ERROR;
|
||||
return PyLong_FromLong((long)ans);
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
BindTexture(PyObject UNUSED *self, PyObject *args) {
|
||||
unsigned int tex_id; int target;
|
||||
if (!PyArg_ParseTuple(args, "iI", &target, &tex_id)) return NULL;
|
||||
glBindTexture(target, tex_id);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
TexParameteri(PyObject UNUSED *self, PyObject *args) {
|
||||
int target, name, param;
|
||||
if (!PyArg_ParseTuple(args, "iii", &target, &name, ¶m)) return NULL;
|
||||
glTexParameteri(target, name, param);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
PixelStorei(PyObject UNUSED *self, PyObject *args) {
|
||||
int name, param;
|
||||
if (!PyArg_ParseTuple(args, "ii", &name, ¶m)) return NULL;
|
||||
glPixelStorei(name, param);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
BindBuffer(PyObject UNUSED *self, PyObject *args) {
|
||||
int tgt; unsigned int buf_id;
|
||||
if (!PyArg_ParseTuple(args, "iI", &tgt, &buf_id)) return NULL;
|
||||
glBindBuffer(tgt, buf_id);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
TexBuffer(PyObject UNUSED *self, PyObject *args) {
|
||||
int tgt, fmt; unsigned int buf_id;
|
||||
if (!PyArg_ParseTuple(args, "iiI", &tgt, &fmt, &buf_id)) return NULL;
|
||||
glTexBuffer(tgt, fmt, buf_id);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
DeleteTexture(PyObject UNUSED *self, PyObject *val) {
|
||||
GLuint tex_id = (GLuint)PyLong_AsUnsignedLong(val);
|
||||
glDeleteTextures(1, &tex_id);
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
int add_module_gl_constants(PyObject *module) {
|
||||
#define GLC(x) if (PyModule_AddIntConstant(module, #x, x) != 0) { PyErr_NoMemory(); return 0; }
|
||||
GLC(GL_VERSION);
|
||||
@ -335,6 +441,16 @@ int add_module_gl_constants(PyObject *module) {
|
||||
GLC(GL_FALSE);
|
||||
GLC(GL_COMPILE_STATUS);
|
||||
GLC(GL_LINK_STATUS);
|
||||
GLC(GL_TEXTURE0); GLC(GL_TEXTURE1); GLC(GL_TEXTURE2); GLC(GL_TEXTURE3); GLC(GL_TEXTURE4); GLC(GL_TEXTURE5); GLC(GL_TEXTURE6); GLC(GL_TEXTURE7); GLC(GL_TEXTURE8);
|
||||
GLC(GL_MAX_ARRAY_TEXTURE_LAYERS);
|
||||
GLC(GL_MAX_TEXTURE_SIZE);
|
||||
GLC(GL_TEXTURE_2D_ARRAY);
|
||||
GLC(GL_LINEAR); GLC(GL_CLAMP_TO_EDGE);
|
||||
GLC(GL_TEXTURE_MIN_FILTER); GLC(GL_TEXTURE_MAG_FILTER);
|
||||
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_RGB32UI);
|
||||
GLC(GL_TEXTURE_BUFFER); GLC(GL_STATIC_DRAW);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -355,10 +471,14 @@ int add_module_gl_constants(PyObject *module) {
|
||||
METH(GetAttribLocation, METH_VARARGS) \
|
||||
METH(ShaderSource, METH_VARARGS) \
|
||||
METH(CompileShader, METH_O) \
|
||||
METH(DeleteTexture, METH_O) \
|
||||
METH(GetString, METH_O) \
|
||||
METH(GetIntegerv, METH_O) \
|
||||
METH(Clear, METH_O) \
|
||||
METH(CreateShader, METH_O) \
|
||||
METH(GenVertexArrays, METH_O) \
|
||||
METH(GenTextures, METH_O) \
|
||||
METH(GenBuffers, METH_O) \
|
||||
METH(LinkProgram, METH_O) \
|
||||
METH(UseProgram, METH_O) \
|
||||
METH(BindVertexArray, METH_O) \
|
||||
@ -366,7 +486,13 @@ int add_module_gl_constants(PyObject *module) {
|
||||
METH(DeleteShader, METH_O) \
|
||||
METH(GetProgramInfoLog, METH_O) \
|
||||
METH(GetShaderInfoLog, METH_O) \
|
||||
METH(ActiveTexture, METH_O) \
|
||||
METH(DrawArraysInstanced, METH_VARARGS) \
|
||||
METH(CreateProgram, METH_NOARGS) \
|
||||
METH(AttachShader, METH_VARARGS) \
|
||||
METH(BindTexture, METH_VARARGS) \
|
||||
METH(TexParameteri, METH_VARARGS) \
|
||||
METH(PixelStorei, METH_VARARGS) \
|
||||
METH(BindBuffer, METH_VARARGS) \
|
||||
METH(TexBuffer, METH_VARARGS) \
|
||||
|
||||
|
||||
@ -4,18 +4,27 @@
|
||||
|
||||
from functools import lru_cache
|
||||
|
||||
from OpenGL.arrays import ArrayDatatype
|
||||
import OpenGL.GL as gl
|
||||
from OpenGL.arrays import ArrayDatatype
|
||||
from OpenGL.GL.ARB.copy_image import glCopyImageSubData # only present in opengl core >= 4.3
|
||||
from OpenGL.GL.ARB.texture_storage import glTexStorage3D # only present in opengl core >= 4.2
|
||||
|
||||
from .fonts import render_cell
|
||||
from .data_types import ITALIC_MASK, BOLD_MASK
|
||||
from .fast_data_types import (
|
||||
glCreateProgram, glAttachShader, GL_FRAGMENT_SHADER, GL_VERTEX_SHADER, glLinkProgram,
|
||||
GL_TRUE, GL_LINK_STATUS, glGetProgramiv, glGetProgramInfoLog, glDeleteShader, glDeleteProgram,
|
||||
glGenVertexArrays, glCreateShader, glShaderSource, glCompileShader, glGetShaderiv, GL_COMPILE_STATUS,
|
||||
glGetShaderInfoLog, glGetUniformLocation, glGetAttribLocation, glUseProgram, glBindVertexArray,
|
||||
glCreateProgram, glAttachShader, GL_FRAGMENT_SHADER, GL_VERTEX_SHADER,
|
||||
glLinkProgram, GL_TRUE, GL_LINK_STATUS, glGetProgramiv,
|
||||
glGetProgramInfoLog, glDeleteShader, glDeleteProgram, glGenVertexArrays,
|
||||
glCreateShader, glShaderSource, glCompileShader, glGetShaderiv,
|
||||
GL_COMPILE_STATUS, glGetShaderInfoLog, glGetUniformLocation,
|
||||
glGetAttribLocation, glUseProgram, glBindVertexArray, GL_TEXTURE0,
|
||||
GL_TEXTURE1, glGetIntegerv, GL_MAX_ARRAY_TEXTURE_LAYERS,
|
||||
GL_MAX_TEXTURE_SIZE, glDeleteTexture, GL_TEXTURE_2D_ARRAY, glGenTextures,
|
||||
glBindTexture, glTexParameteri, GL_LINEAR, GL_CLAMP_TO_EDGE,
|
||||
GL_TEXTURE_MAG_FILTER, GL_TEXTURE_MIN_FILTER, GL_TEXTURE_WRAP_S,
|
||||
GL_TEXTURE_WRAP_T, glGenBuffers, GL_R8, GL_RED, GL_UNPACK_ALIGNMENT, GL_UNSIGNED_BYTE,
|
||||
GL_STATIC_DRAW, GL_TEXTURE_BUFFER, GL_RGB32UI, glBindBuffer, glPixelStorei,
|
||||
glTexBuffer, glActiveTexture
|
||||
)
|
||||
|
||||
GL_VERSION = (3, 3)
|
||||
@ -29,10 +38,10 @@ class Sprites:
|
||||
# TODO: Rewrite this class using the ARB_shader_image_load_store and ARB_shader_storage_buffer_object
|
||||
# extensions one they become available.
|
||||
|
||||
def __init__(self, texture_unit=0):
|
||||
def __init__(self):
|
||||
self.xnum = self.ynum = 1
|
||||
self.sampler_num = texture_unit
|
||||
self.buffer_sampler_num = texture_unit + 1
|
||||
self.sampler_num = 0
|
||||
self.buffer_sampler_num = 1
|
||||
self.first_cell_cache = {}
|
||||
self.second_cell_cache = {}
|
||||
self.x = self.y = self.z = 0
|
||||
@ -40,9 +49,9 @@ class Sprites:
|
||||
self.last_num_of_layers = 1
|
||||
|
||||
def initialize(self):
|
||||
self.texture_unit = getattr(gl, 'GL_TEXTURE%d' % self.sampler_num)
|
||||
self.max_array_len = gl.glGetIntegerv(gl.GL_MAX_ARRAY_TEXTURE_LAYERS)
|
||||
self.max_texture_size = gl.glGetIntegerv(gl.GL_MAX_TEXTURE_SIZE)
|
||||
self.texture_unit = GL_TEXTURE0
|
||||
self.max_array_len = glGetIntegerv(GL_MAX_ARRAY_TEXTURE_LAYERS)
|
||||
self.max_texture_size = glGetIntegerv(GL_MAX_TEXTURE_SIZE)
|
||||
self.do_layout(getattr(self, 'cell_width', 1), getattr(self, 'cell_height', 1))
|
||||
|
||||
def do_layout(self, cell_width=1, cell_height=1):
|
||||
@ -53,7 +62,7 @@ class Sprites:
|
||||
self.max_y = max(1, self.max_texture_size // self.cell_height)
|
||||
self.ynum = 1
|
||||
if self.texture_id is not None:
|
||||
gl.glDeleteTextures([self.texture_id])
|
||||
glDeleteTexture(self.texture_id)
|
||||
self.texture_id = None
|
||||
|
||||
@property
|
||||
@ -63,41 +72,41 @@ class Sprites:
|
||||
def realloc_texture(self):
|
||||
if self.texture_id is None:
|
||||
self.initialize()
|
||||
tgt = gl.GL_TEXTURE_2D_ARRAY
|
||||
tex = gl.glGenTextures(1)
|
||||
gl.glBindTexture(tgt, tex)
|
||||
gl.glTexParameteri(tgt, gl.GL_TEXTURE_MIN_FILTER, gl.GL_LINEAR)
|
||||
gl.glTexParameteri(tgt, gl.GL_TEXTURE_MAG_FILTER, gl.GL_LINEAR)
|
||||
gl.glTexParameteri(tgt, gl.GL_TEXTURE_WRAP_S, gl.GL_CLAMP_TO_EDGE)
|
||||
gl.glTexParameteri(tgt, gl.GL_TEXTURE_WRAP_T, gl.GL_CLAMP_TO_EDGE)
|
||||
tgt = GL_TEXTURE_2D_ARRAY
|
||||
tex = glGenTextures(1)
|
||||
glBindTexture(tgt, tex)
|
||||
glTexParameteri(tgt, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
|
||||
glTexParameteri(tgt, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
|
||||
glTexParameteri(tgt, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
|
||||
glTexParameteri(tgt, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
|
||||
znum = self.z + 1
|
||||
width, height = self.xnum * self.cell_width, self.ynum * self.cell_height
|
||||
glTexStorage3D(tgt, 1, gl.GL_R8, width, height, znum)
|
||||
glTexStorage3D(tgt, 1, GL_R8, width, height, znum)
|
||||
if self.texture_id is not None:
|
||||
ynum = self.ynum
|
||||
if self.z == 0:
|
||||
ynum -= 1 # Only copy the previous rows
|
||||
glCopyImageSubData(self.texture_id, tgt, 0, 0, 0, 0, tex, tgt, 0, 0, 0, 0,
|
||||
width, ynum * self.cell_height, self.last_num_of_layers)
|
||||
gl.glDeleteTextures([self.texture_id])
|
||||
glDeleteTexture(self.texture_id)
|
||||
self.last_num_of_layers = znum
|
||||
self.texture_id = tex
|
||||
gl.glBindTexture(tgt, 0)
|
||||
glBindTexture(tgt, 0)
|
||||
|
||||
def ensure_state(self):
|
||||
if self.texture_id is None:
|
||||
self.realloc_texture()
|
||||
self.buffer_id = gl.glGenBuffers(1)
|
||||
self.buffer_texture_id = gl.glGenTextures(1)
|
||||
self.buffer_texture_unit = getattr(gl, 'GL_TEXTURE%d' % self.buffer_sampler_num)
|
||||
self.buffer_id = glGenBuffers(1)
|
||||
self.buffer_texture_id = glGenTextures(1)
|
||||
self.buffer_texture_unit = GL_TEXTURE1
|
||||
|
||||
def add_sprite(self, buf):
|
||||
tgt = gl.GL_TEXTURE_2D_ARRAY
|
||||
gl.glBindTexture(tgt, self.texture_id)
|
||||
gl.glPixelStorei(gl.GL_UNPACK_ALIGNMENT, 1)
|
||||
tgt = GL_TEXTURE_2D_ARRAY
|
||||
glBindTexture(tgt, self.texture_id)
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
|
||||
x, y = self.x * self.cell_width, self.y * self.cell_height
|
||||
gl.glTexSubImage3D(tgt, 0, x, y, self.z, self.cell_width, self.cell_height, 1, gl.GL_RED, gl.GL_UNSIGNED_BYTE, buf)
|
||||
gl.glBindTexture(tgt, 0)
|
||||
gl.glTexSubImage3D(tgt, 0, x, y, self.z, self.cell_width, self.cell_height, 1, GL_RED, GL_UNSIGNED_BYTE, buf)
|
||||
glBindTexture(tgt, 0)
|
||||
|
||||
# co-ordinates for this sprite in the sprite sheet
|
||||
x, y, z = self.x, self.y, self.z
|
||||
@ -115,10 +124,10 @@ class Sprites:
|
||||
return x, y, z
|
||||
|
||||
def set_sprite_map(self, data):
|
||||
tgt = gl.GL_TEXTURE_BUFFER
|
||||
gl.glBindBuffer(tgt, self.buffer_id)
|
||||
gl.glBufferData(tgt, ArrayDatatype.arrayByteCount(data), data, gl.GL_STATIC_DRAW)
|
||||
gl.glBindBuffer(tgt, 0)
|
||||
tgt = GL_TEXTURE_BUFFER
|
||||
glBindBuffer(tgt, self.buffer_id)
|
||||
gl.glBufferData(tgt, ArrayDatatype.arrayByteCount(data), data, GL_STATIC_DRAW)
|
||||
glBindBuffer(tgt, 0)
|
||||
|
||||
def primary_sprite_position(self, key):
|
||||
' Return a 3-tuple (x, y, z) giving the position of this sprite on the sprite sheet '
|
||||
@ -145,16 +154,16 @@ class Sprites:
|
||||
|
||||
def __enter__(self):
|
||||
self.ensure_state()
|
||||
gl.glActiveTexture(self.texture_unit)
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D_ARRAY, self.texture_id)
|
||||
glActiveTexture(self.texture_unit)
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, self.texture_id)
|
||||
|
||||
gl.glActiveTexture(self.buffer_texture_unit)
|
||||
gl.glBindTexture(gl.GL_TEXTURE_BUFFER, self.buffer_texture_id)
|
||||
gl.glTexBuffer(gl.GL_TEXTURE_BUFFER, gl.GL_RGB32UI, self.buffer_id)
|
||||
glActiveTexture(self.buffer_texture_unit)
|
||||
glBindTexture(GL_TEXTURE_BUFFER, self.buffer_texture_id)
|
||||
glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32UI, self.buffer_id)
|
||||
|
||||
def __exit__(self, *a):
|
||||
gl.glBindTexture(gl.GL_TEXTURE_2D_ARRAY, 0)
|
||||
gl.glBindTexture(gl.GL_TEXTURE_BUFFER, 0)
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, 0)
|
||||
glBindTexture(GL_TEXTURE_BUFFER, 0)
|
||||
|
||||
|
||||
class ShaderProgram:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user