Start work on OpenGL bindings

This commit is contained in:
Kovid Goyal 2016-11-02 21:27:20 +05:30
parent 8636ddf3cd
commit 3ecf3751ef
5 changed files with 80 additions and 12 deletions

View File

@ -1,5 +1 @@
import OpenGL
# PyOpenGL error checking is extremely slow, so disable it, since by default it
# runs for every call into the OpenGL API
OpenGL.ERROR_CHECKING = False

View File

@ -9,24 +9,26 @@
extern int init_LineBuf(PyObject *);
extern int init_Cursor(PyObject *);
extern int init_Line(PyObject *);
#include "gl.h"
static PyMethodDef module_methods[] = {
GL_METHODS
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef module = {
PyModuleDef_HEAD_INIT,
"fast_data_types", /* name of module */
NULL,
-1,
module_methods
.m_base = PyModuleDef_HEAD_INIT,
.m_name = "fast_data_types", /* name of module */
.m_doc = NULL,
.m_size = -1,
.m_methods = module_methods
};
PyMODINIT_FUNC
PyInit_fast_data_types(void) {
PyObject *m;
m = PyModule_Create(&module);
if (m == NULL) return NULL;

View File

@ -9,6 +9,7 @@ import sys
from kitty.shaders import ShaderProgram, GL_VERSION, Sprites, check_for_required_extensions
from kitty.fonts import set_font_family, cell_size
from kitty.char_grid import calculate_vertices, cell_shader
from kitty.fast_data_types import glViewport, enable_automatic_opengl_error_checking
def rectangle_uv(left=0, top=0, right=1, bottom=1):
@ -37,7 +38,7 @@ class Renderer:
self.do_layout()
def on_resize(self, window, w, h):
gl.glViewport(0, 0, w, h)
glViewport(0, 0, w, h)
self.w, self.h = w, h
self.do_layout()
@ -137,6 +138,7 @@ def main():
glfw.glfwSetErrorCallback(on_error)
if not glfw.glfwInit():
raise SystemExit('GLFW initialization failed')
enable_automatic_opengl_error_checking(True)
set_font_family('monospace', 144)
try:
_main()

63
kitty/gl.h Normal file
View File

@ -0,0 +1,63 @@
/*
* gl.c
* Copyright (C) 2016 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include "data-types.h"
#include <GL/glew.h>
#define STRINGIFY(x) #x
#define METH(name, argtype) {STRINGIFY(gl##name), (PyCFunction)name, argtype, NULL},
static int _enable_error_checking = 1;
#define SET_GL_ERR \
switch(glGetError()) { \
case GL_NO_ERROR: break; \
case GL_INVALID_ENUM: \
PyErr_SetString(PyExc_ValueError, "An enum value is invalid (GL_INVALID_ENUM)"); break; \
case GL_INVALID_VALUE: \
PyErr_SetString(PyExc_ValueError, "An numeric value is invalid (GL_INVALID_VALUE)"); break; \
case GL_INVALID_OPERATION: \
PyErr_SetString(PyExc_ValueError, "This operation is not allowed in the current state (GL_INVALID_OPERATION)"); break; \
case GL_INVALID_FRAMEBUFFER_OPERATION: \
PyErr_SetString(PyExc_ValueError, "The framebuffer object is not complete (GL_INVALID_FRAMEBUFFER_OPERATION)"); break; \
case GL_OUT_OF_MEMORY: \
PyErr_SetString(PyExc_MemoryError, "There is not enough memory left to execute the command. (GL_OUT_OF_MEMORY)"); break; \
case GL_STACK_UNDERFLOW: \
PyErr_SetString(PyExc_OverflowError, "An attempt has been made to perform an operation that would cause an internal stack to underflow. (GL_STACK_UNDERFLOW)"); break; \
case GL_STACK_OVERFLOW: \
PyErr_SetString(PyExc_OverflowError, "An attempt has been made to perform an operation that would cause an internal stack to underflow. (GL_STACK_UNDERFLOW)"); break; \
default: \
PyErr_SetString(PyExc_RuntimeError, "An unknown OpenGL error occurred."); break; \
}
#define CHECK_ERROR if (_enable_error_checking) { SET_GL_ERR; if (PyErr_Occurred()) return NULL; }
static PyObject*
enable_automatic_error_checking(PyObject UNUSED *self, PyObject *val) {
_enable_error_checking = PyObject_IsTrue(val) ? 1 : 0;
Py_RETURN_NONE;
}
static PyObject*
Viewport(PyObject UNUSED *self, PyObject *args) {
unsigned int x, y, w, h;
if (!PyArg_ParseTuple(args, "IIII", &x, &y, &w, &h)) return NULL;
glViewport(x, y, w, h);
CHECK_ERROR;
Py_RETURN_NONE;
}
static PyObject*
CheckError(PyObject UNUSED *self) {
CHECK_ERROR; Py_RETURN_NONE;
}
#define GL_METHODS \
{"enable_automatic_opengl_error_checking", (PyCFunction)enable_automatic_error_checking, METH_O, NULL}, \
METH(Viewport, METH_VARARGS) \
METH(CheckError, METH_NOARGS) \

View File

@ -21,6 +21,10 @@ version = tuple(map(int, re.search(r"^version = \((\d+), (\d+), (\d+)\)", consta
cflags = ldflags = cc = ldpaths = None
def pkg_config(pkg, *args):
return shlex.split(subprocess.check_output(['pkg-config', pkg] + list(args)).decode('utf-8'))
def init_env():
global cflags, ldflags, cc, ldpaths
cc = os.environ.get('CC', 'gcc')
@ -34,11 +38,12 @@ def init_env():
ldflags += shlex.split(os.environ.get('LDFLAGS', ''))
cflags.append('-pthread')
cflags.extend(pkg_config('glew', '--cflags-only-I'))
ldflags.append('-pthread')
ldflags.append('-shared')
cflags.append('-I' + sysconfig.get_config_var('CONFINCLUDEPY'))
lib = sysconfig.get_config_var('LDLIBRARY')[3:-3]
ldpaths = ['-L' + sysconfig.get_config_var('LIBDIR'), '-l' + lib]
ldpaths = ['-L' + sysconfig.get_config_var('LIBDIR'), '-l' + lib] + pkg_config('glew', '--libs')
try:
os.mkdir(build_dir)