File: headless.cpp

package info (click to toggle)
python-moderngl-glcontext 3.0.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 188 kB
  • sloc: cpp: 1,373; python: 212; makefile: 7
file content (107 lines) | stat: -rw-r--r-- 3,083 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
#include <Python.h>

#include <EGL/egl.h>
#include <EGL/eglext.h>

int num_devices;
EGLDeviceEXT devices[64];

EGLContext context;
EGLDisplay display;
EGLConfig config;

PyObject * meth_devices(PyObject * self) {
    PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT = (PFNEGLQUERYDEVICESEXTPROC)eglGetProcAddress("eglQueryDevicesEXT");
    PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT = (PFNEGLQUERYDEVICESTRINGEXTPROC)eglGetProcAddress("eglQueryDeviceStringEXT");

    if (!eglQueryDevicesEXT(0, NULL, &num_devices)) {
        return NULL;
    }

    if (!eglQueryDevicesEXT(num_devices, devices, &num_devices)) {
        return NULL;
    }

    PyObject * res = PyList_New(num_devices);
    for (int i = 0; i < num_devices; ++i) {
        const char * egl_extensions = eglQueryDeviceStringEXT(devices[i], EGL_EXTENSIONS);
        PyObject * temp = PyUnicode_FromString(egl_extensions ? egl_extensions : "");
        PyObject * extensions = PyObject_CallMethod(temp, "split", NULL);
        Py_DECREF(temp);
        PyList_SetItem(res, i, Py_BuildValue("{sisN}", "device", i, "extensions", extensions));
    }
    return res;
}

PyObject * meth_init(PyObject * self, PyObject * args, PyObject * kwargs) {
    const char * keywords[] = {"device", NULL};

    int device = 0;

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i", (char **)keywords, &device)) {
        return NULL;
    }

    if (device > num_devices) {
        return NULL;
    }

    display = eglGetPlatformDisplay(EGL_PLATFORM_DEVICE_EXT, devices[device], 0);
    if (display == EGL_NO_DISPLAY) {
        return NULL;
    }

    if (!eglInitialize(display, NULL, NULL)) {
        return NULL;
    }

    int config_attribs[] = {
        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
        EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
        EGL_NONE,
    };

    int num_configs = 0;
    if (!eglChooseConfig(display, config_attribs, &config, 1, &num_configs)) {
        return NULL;
    }

    if (!eglBindAPI(EGL_OPENGL_API)) {
        return NULL;
    }

    int context_attribs[] = {
        EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
        EGL_NONE,
    };

    context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attribs);
    if (!context) {
        return NULL;
    }

    eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, context);
    Py_RETURN_NONE;
}

PyObject * meth_load_opengl_function(PyObject * self, PyObject * arg) {
    if (!PyUnicode_CheckExact(arg)) {
        return NULL;
    }
    const char * name = PyUnicode_AsUTF8(arg);
    return PyLong_FromVoidPtr((void *)eglGetProcAddress(name));
}

PyMethodDef module_methods[] = {
    {"devices", (PyCFunction)meth_devices, METH_NOARGS},
    {"init", (PyCFunction)meth_init, METH_VARARGS | METH_KEYWORDS},
    {"load_opengl_function", (PyCFunction)meth_load_opengl_function, METH_O},
    {},
};

PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "headless", NULL, -1, module_methods};

extern "C" PyObject * PyInit_headless() {
    PyObject * module = PyModule_Create(&module_def);
    return module;
}