Fallback implementation for glCopyImageSubData
OS X is missing this function so we fallback to a very slow, GPU->CPU->GPU roundtrip. Fortunately this is needed only rarely so it should not have a noticeable performance imapct. Le bubbling sigh!
This commit is contained in:
parent
6b01b9613a
commit
063ec7dc02
47
kitty/gl.h
47
kitty/gl.h
@ -127,10 +127,6 @@ _glewInit(PyObject UNUSED *self) {
|
||||
PyErr_Format(PyExc_RuntimeError, "GLEW init failed: %s", glewGetErrorString(err));
|
||||
return NULL;
|
||||
}
|
||||
if(!GLEW_ARB_copy_image) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "OpenGL is missing the required ARB_copy_image extension");
|
||||
return NULL;
|
||||
}
|
||||
if(!GLEW_ARB_texture_storage) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "OpenGL is missing the required ARB_texture_storage extension");
|
||||
return NULL;
|
||||
@ -439,6 +435,10 @@ static PyObject*
|
||||
CopyImageSubData(PyObject UNUSED *self, PyObject *args) {
|
||||
int src_target, src_level, srcX, srcY, srcZ, dest_target, dest_level, destX, destY, destZ;
|
||||
unsigned int src, dest, width, height, depth;
|
||||
if(!GLEW_ARB_copy_image) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "OpenGL is missing the required ARB_copy_image extension");
|
||||
return NULL;
|
||||
}
|
||||
if (!PyArg_ParseTuple(args, "IiiiiiIiiiiiIII",
|
||||
&src, &src_target, &src_level, &srcX, &srcY, &srcZ,
|
||||
&dest, &dest_target, &dest_level, &destX, &destY, &destZ,
|
||||
@ -451,6 +451,26 @@ CopyImageSubData(PyObject UNUSED *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
copy_image_sub_data(PyObject UNUSED *self, PyObject *args) {
|
||||
int src_target, dest_target;
|
||||
unsigned int width, height, num_levels;
|
||||
if (!PyArg_ParseTuple(args, "iiIII", &src_target, &dest_target, &width, &height, &num_levels)) return NULL;
|
||||
uint8_t *src = (uint8_t*)PyMem_Malloc(5 * width * height * num_levels);
|
||||
if (src == NULL) return PyErr_NoMemory();
|
||||
uint8_t *dest = src + (4 * width * height * num_levels);
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, src_target);
|
||||
glGetTexImage(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA, GL_UNSIGNED_BYTE, src);
|
||||
glBindTexture(GL_TEXTURE_2D_ARRAY, dest_target);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
for(unsigned int i = 0; i < width * height * num_levels; i++) dest[i] = src[4*i];
|
||||
glTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, width, height, num_levels, GL_RED, GL_UNSIGNED_BYTE, dest);
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyMem_Free(src);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
TexSubImage3D(PyObject UNUSED *self, PyObject *args) {
|
||||
int target, level, x, y, z, fmt, type;
|
||||
@ -466,6 +486,21 @@ TexSubImage3D(PyObject UNUSED *self, PyObject *args) {
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
|
||||
static PyObject*
|
||||
GetTexImage(PyObject UNUSED *self, PyObject *args) {
|
||||
int target, level, fmt, type;
|
||||
PyObject *pixels;
|
||||
if (!PyArg_ParseTuple(args, "iiiiO!", &target, &level, &fmt, &type, &PyLong_Type, &pixels)) return NULL;
|
||||
void *data = PyLong_AsVoidPtr(pixels);
|
||||
if (data == NULL) { PyErr_SetString(PyExc_TypeError, "Not a valid data pointer"); return NULL; }
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
glGetTexImage(target, level, fmt, type, data);
|
||||
Py_END_ALLOW_THREADS;
|
||||
CHECK_ERROR;
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
static PyObject*
|
||||
NamedBufferData(PyObject UNUSED *self, PyObject *args) {
|
||||
int usage;
|
||||
@ -609,7 +644,7 @@ int add_module_gl_constants(PyObject *module) {
|
||||
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_R8); GLC(GL_RED); GLC(GL_UNSIGNED_BYTE); 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_BLEND); GLC(GL_FLOAT); GLC(GL_ARRAY_BUFFER);
|
||||
@ -619,6 +654,7 @@ int add_module_gl_constants(PyObject *module) {
|
||||
|
||||
#define GL_METHODS \
|
||||
{"enable_automatic_opengl_error_checking", (PyCFunction)enable_automatic_error_checking, METH_O, NULL}, \
|
||||
{"copy_image_sub_data", (PyCFunction)copy_image_sub_data, METH_VARARGS, NULL}, \
|
||||
{"glewInit", (PyCFunction)_glewInit, METH_NOARGS, NULL}, \
|
||||
METH(Viewport, METH_VARARGS) \
|
||||
METH(CheckError, METH_NOARGS) \
|
||||
@ -668,6 +704,7 @@ int add_module_gl_constants(PyObject *module) {
|
||||
METH(TexStorage3D, METH_VARARGS) \
|
||||
METH(CopyImageSubData, METH_VARARGS) \
|
||||
METH(TexSubImage3D, METH_VARARGS) \
|
||||
METH(GetTexImage, METH_VARARGS) \
|
||||
METH(NamedBufferData, METH_VARARGS) \
|
||||
METH(BlendFunc, METH_VARARGS) \
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
|
||||
import sys
|
||||
from ctypes import addressof, sizeof
|
||||
from functools import lru_cache
|
||||
from threading import Lock
|
||||
@ -23,8 +24,9 @@ from .fast_data_types import (
|
||||
GL_TEXTURE_BUFFER, GL_RGB32UI, GL_FLOAT, GL_ARRAY_BUFFER, glBindBuffer,
|
||||
glPixelStorei, glTexBuffer, glActiveTexture, glTexStorage3D,
|
||||
glCopyImageSubData, glTexSubImage3D, ITALIC, BOLD, SpriteMap,
|
||||
glEnableVertexAttribArray, glVertexAttribPointer
|
||||
glEnableVertexAttribArray, glVertexAttribPointer, copy_image_sub_data
|
||||
)
|
||||
from .utils import safe_print
|
||||
|
||||
GL_VERSION = (3, 3)
|
||||
VERSION = GL_VERSION[0] * 100 + GL_VERSION[1] * 10
|
||||
@ -120,8 +122,18 @@ class Sprites:
|
||||
ynum = self.backend.ynum
|
||||
if self.backend.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)
|
||||
try:
|
||||
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)
|
||||
except RuntimeError:
|
||||
# OpenGL does not have ARB_copy_image
|
||||
if not hasattr(self, 'realloc_warned'):
|
||||
safe_print(
|
||||
'WARNING: Your system\'s OpenGL implementation does not have glCopyImageSubData, falling back to a slower implementation',
|
||||
file=sys.stderr)
|
||||
self.realloc_warned = True
|
||||
copy_image_sub_data(self.texture_id, tex, width, ynum * self.cell_height, self.last_num_of_layers)
|
||||
glBindTexture(tgt, tex)
|
||||
glDeleteTexture(self.texture_id)
|
||||
self.last_num_of_layers = znum
|
||||
self.last_ynum = self.backend.ynum
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user