More OpenGL bindings

This commit is contained in:
Kovid Goyal 2016-11-03 15:14:59 +05:30
parent 5d77499cb1
commit 99f788ead5
2 changed files with 176 additions and 41 deletions

View File

@ -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, &param)) 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, &param)) 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) \

View File

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