pax_global_header 0000666 0000000 0000000 00000000064 14512447336 0014523 g ustar 00root root 0000000 0000000 52 comment=1573e57e5423b313599155c7e4bc9c5253065f40
moderngl-glcontext-1573e57/ 0000775 0000000 0000000 00000000000 14512447336 0015621 5 ustar 00root root 0000000 0000000 moderngl-glcontext-1573e57/.github/ 0000775 0000000 0000000 00000000000 14512447336 0017161 5 ustar 00root root 0000000 0000000 moderngl-glcontext-1573e57/.github/icon.svg 0000664 0000000 0000000 00000010012 14512447336 0020624 0 ustar 00root root 0000000 0000000
moderngl-glcontext-1573e57/.github/workflows/ 0000775 0000000 0000000 00000000000 14512447336 0021216 5 ustar 00root root 0000000 0000000 moderngl-glcontext-1573e57/.github/workflows/build.yml 0000664 0000000 0000000 00000002603 14512447336 0023041 0 ustar 00root root 0000000 0000000 name: build
on:
push:
branches: [master]
pull_request:
branches: [master]
workflow_dispatch:
jobs:
build:
name: build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
architecture: ['x64']
steps:
- uses: actions/checkout@v3
- name: setup
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
architecture: ${{ matrix.architecture }}
- name: deps
run: python -m pip install -U pip wheel setuptools
- name: wheel
run: python setup.py bdist_wheel
build-aarch64:
strategy:
fail-fast: false
runs-on: ubuntu-latest
env:
py: /opt/python/cp39-cp39/bin/python
img: quay.io/pypa/manylinux2014_aarch64
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up QEMU
id: qemu
uses: docker/setup-qemu-action@v1
- name: Install dependencies
run: |
docker run --rm -v ${{ github.workspace }}:/ws:rw --workdir=/ws \
${{ env.img }} \
bash -exc '${{ env.py }} -m venv .env && \
source .env/bin/activate && \
python -m pip install -U pip wheel setuptools && \
python setup.py bdist_wheel && \
deactivate'
moderngl-glcontext-1573e57/.github/workflows/publish.yml 0000664 0000000 0000000 00000004356 14512447336 0023417 0 ustar 00root root 0000000 0000000 name: Publish
on:
# push:
release:
types: [created]
workflow_dispatch:
jobs:
build_wheels:
name: Build Wheels on ${{ matrix.os }}-${{ matrix.cibw_archs }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-18.04, windows-2019, macos-10.15]
cibw_archs: ["auto64"]
include:
- os: ubuntu-18.04
cibw_archs: "aarch64"
- os: ubuntu-18.04
cibw_archs: "auto32"
- os: windows-2019
cibw_archs: "auto32"
steps:
- uses: actions/checkout@v3
- name: Set up QEMU
if: matrix.cibw_archs == 'aarch64'
uses: docker/setup-qemu-action@v1
with:
platforms: arm64
- name: Build wheels
uses: pypa/cibuildwheel@v2.16.2
with:
output-dir: dist/
env:
CIBW_ARCHS_MACOS: "x86_64 universal2"
CIBW_BUILD: cp38-* cp39-* cp310-* cp311-* cp312-* pp*
CIBW_ARCHS: ${{ matrix.cibw_archs }}
CIBW_SKIP: "*-musllinux*"
- uses: actions/upload-artifact@v2
with:
path: ./dist/*.whl
name: wheels-${{ runner.os }}-${{ matrix.cibw_archs }}
# Build the source distribution under Linux
build_sdist:
name: Source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build source distribution
run: pipx run build --sdist
- name: Store artifacts
uses: actions/upload-artifact@v2
with:
path: dist/*.tar.gz
publish:
name: publish
needs:
- build_sdist
- build_wheels
runs-on: ubuntu-latest
# if: ${{ github.event_name == 'release' && github.event.action == 'created' }}
steps:
- name: download
uses: actions/download-artifact@v2
with:
path: temp-dist/
# Only copy the wheels and source dist files. Additional lingering
# files will cause issues
- name: Copy Files to dist
shell: bash
run: |
mkdir dist
cp temp-dist/*/*.whl dist/
cp temp-dist/*/*.tar.gz dist/
- uses: pypa/gh-action-pypi-publish@v1.4.2
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
moderngl-glcontext-1573e57/.github/workflows/release.yml 0000664 0000000 0000000 00000001532 14512447336 0023362 0 ustar 00root root 0000000 0000000 name: release
on:
workflow_dispatch:
jobs:
release:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-20.04, windows-2019, macos-11]
steps:
- uses: actions/checkout@v3
- name: setup
uses: actions/setup-python@v4
with:
python-version: '3.11'
architecture: x64
- name: update
run: python -m pip install -U pip wheel setuptools
- name: deps
run: python -m pip install cibuildwheel==2.16.2
- name: sdist
if: matrix.os == 'ubuntu-20.04'
run: python setup.py sdist -d package
- name: wheels
run: python -m cibuildwheel --output-dir package
- name: upload
uses: actions/upload-artifact@v3
with:
name: package
path: package
moderngl-glcontext-1573e57/.gitignore 0000664 0000000 0000000 00000000166 14512447336 0017614 0 ustar 00root root 0000000 0000000 /.vscode/*
/.pytest_cache
/.cache
/build
/dist
__pycache__
*.egg-info
*.pyc
*.pyd
*.pbd
*.lib
*.so
temp_*
.venv
moderngl-glcontext-1573e57/CHANGELOG.md 0000664 0000000 0000000 00000003165 14512447336 0017437 0 ustar 00root root 0000000 0000000
# Change Log
## 2.3.7
Python 3.11 support
## 2.3.6
Expose headless/standalone flag
## 2.3.3
* Missing manylinux wheels for python 3.9
* Minor issue in setup.py
## 2.3.0
python 3.9 support
## 2.3.dev0
* EGL backend will now use `eglQueryDevicesEXT` instead of only relying on `EGL_DEFAULT_DISPLAY`
* EGL backend now supports `device_index` for selecting a device
## 2.2.0
* x11 and egl backend will now use `ctypes.utils.find_library`
to locate GL and EGL if not `libgl` and `libegl` parameter
is passed to the backend
## 2.1.0
* Support setting backend arguments using environment variables.
* `GLCONTEXT_GLVERSION` for setting opengl version
* `GLCONTEXT_LINUX_LIBGL` for specifying libgl name
* `GLCONTEXT_LINUX_LIBX11` for specifying libx11 name
* `GLCONTEXT_LINUX_LIBEGL` for specifying libegl name
* `GLCONTEXT_WIN_LIBGL` for specifying dll name
* x11: More details in error messages
## 2.0.0
Support passing in values to backends for more detailed
configuration. Method signatures have changed so upgrading
from 1.* needs smaller code changes.
- `default_backend()` no longer takes any arguments
- The returned backend now takes `glversion` and other arguments
- The `standalone` argument is now called `mode` and can contain
`standalone`, `share` and `detect`.
- Added `get_backend` for requesting specific backends like EGL.
## 1.0.1
* darwin: Fixed a segfault when releasing a context
* x11: Fixed an issue causing context creation to fail
## 1.0.0
Initial release. Contains backends for wgl, darwin and x11
including experimental egl backend.
moderngl-glcontext-1573e57/LICENSE 0000664 0000000 0000000 00000002066 14512447336 0016632 0 ustar 00root root 0000000 0000000 MIT License
Copyright (c) 2021 ModernGL Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
moderngl-glcontext-1573e57/MANIFEST.in 0000664 0000000 0000000 00000000112 14512447336 0017351 0 ustar 00root root 0000000 0000000 recursive-include glcontext *.cpp *.hpp
include README.md
include LICENSE
moderngl-glcontext-1573e57/README.md 0000664 0000000 0000000 00000012406 14512447336 0017103 0 ustar 00root root 0000000 0000000 [](https://pypi.python.org/pypi/glcontext)
# glcontext
**glcontext** is a library providing OpenGL implementation for ModernGL on multiple platforms.
* [glcontext on github](https://github.com/moderngl/glcontext)
* [glcontext on pypi](https://pypi.org/project/glcontext)
* [ModernGL](https://github.com/moderngl/moderngl)
## Backends
A glcontext backend is either an extension or a submodule of the glcontext package.
The package itself does not import any of the backends.
Importing the base package `glcontext` must safe and lightweight.
## Structure
Every backend of glcontext must provide a factory function:
```py
def create_context(*args, **kwargs) -> GLContext:
pass
```
The create\_context method can take any number of positional and keyword arguments.
The factory function must return an object supporting the following methods:
```py
def load(self, name:str) -> int:
pass
```
The load method takes an OpenGL function name as an input and returns a C/C++ function pointer as a python integer.
The return value must be 0 for not implemented functions.
```py
def __enter__(self, name:str):
pass
```
The enter method calls `___MakeCurrent` to make the GLContext the calling thread's current rendering context.
`___MakeCurrent` stands for `wglMakeCurrent`, `glxMakeCurrent`, ...
```py
def __exit__(self, exc_type, exc_val, exc_tb):
pass
```
The exit method calls `___MakeCurrent` to make the GLContext no longer current.
```py
def release(self):
pass
```
The release method destroys the OpenGL context.
## Development Guide
There are "empty" example backends provided for developers to help adding new backends to the library.
There is a pure python example in [empty.py](#) and an extension example in [empty.cpp](#).
Besides their name match, they do not depend on each other, they are independent submodules of glcontext.
An "portable" backend implementation must load its dependency at runtime.
This rule is for simplifying the build of the entire package.
If an implementation cannot provide a "portable" backend, it will not be added to this library.
Non "portable" backends are welcome as third party libraries.
A backend must be lightweight, its size must fit within reasonable limits.
To add support for new platforms one must edit the `setup.py` too.
Platform specific dependencies are exceptions from the "portability" rule.
Example for platform specific dependencies:
- `gdi32.lib` on windows
- `libdl.a` on linux
Please note that `libGL.so` is loaded dinamically by the backends.
## Current backends
Each backend supports a `glversion` and `mode` parameters as a minimum.
The `glversion` is the minimum OpenGL version required while `mode`
decides how the context is created.
Modes
* `detect`: Will detect an existing active OpenGL context.
* `standalone`: Crates a headless OpenGL context
* `share`: Creates a new context sharing objects with the currently active context (headless)
### wgl
Parameters
* `glversion` (`int`): The minimum OpenGL version for the context
* `mode` (`str`): Creation mode. `detect` | `standalone` | `share`
* `libgl` (`str`): Name of gl library to load (default: `opengl32.dll`)
### x11
If `libgl` is not passed in the backend will try to locate
the GL library using `ctypes.utils.find_library`.
Parameters
* `glversion` (`int`): The minimum OpenGL version for the context
* `mode` (`str`): Creation mode. `detect` | `standalone` | `share`
* `libgl` (`str`): Name of gl library to load (default: `libGL.so`)
* `libx11` (`str`): Name of x11 library to load (default: `libX11.so`)
### darwin
Will create the the highest core context available.
Parameters
* `mode` (`str`): Creation mode. `detect` | `standalone`
### egl
Only supports standalone mode.
If `libgl` and/or `libegl` is not passed in the backend will try to locate
GL and/or EGL library using `ctypes.utils.find_library`.
Parameters
* `glversion` (`int`): The minimum OpenGL version for the context
* `mode` (`str`): Creation mode. `standalone`
* `libgl` (`str`): Name of gl library to load (default: `libGL.so`)
* `libegl` (`str`): Name of gl library to load (default: `libEGL.so`)
* `device_index` (`int`) The device index to use (default: `0`)
## Environment Variables
Environment variables can be set to configure backends.
These will get first priority if defined.
```bash
# Override OpenGL version code. For example: 410 (for opengl 4.1)
GLCONTEXT_GLVERSION
# Override libgl on linux. For example: libGL.1.so
GLCONTEXT_LINUX_LIBGL
# Override libx11 on linux. For exampleØ libX11.x.so
GLCONTEXT_LINUX_LIBX11
# Override libegl on linux. For exampleØ libEGL.x.so
GLCONTEXT_LINUX_LIBEGL
# Override gl dll on windows. For example: opengl32_custom.dll
GLCONTEXT_WIN_LIBGL
# Override the device index (egl)
GLCONTEXT_DEVICE_INDEX
```
## Running tests
```
pip install -r tests/requirements.txt
pytest tests
```
## Contributing
Contribution is welcome.
Pull Requests will be merged if they match the [Development Guide](#).
For prototypes, pure python implementations using ctypes are also welcome.
We will probably port it to a proper extension in the future.
Please ask questions [here](https://github.com/moderngl/glcontext/issues).
moderngl-glcontext-1573e57/glcontext/ 0000775 0000000 0000000 00000000000 14512447336 0017630 5 ustar 00root root 0000000 0000000 moderngl-glcontext-1573e57/glcontext/__init__.py 0000664 0000000 0000000 00000010201 14512447336 0021733 0 ustar 00root root 0000000 0000000 import os
__version__ = '2.3.7'
def default_backend():
"""Get default backend based on the detected platform.
Supports detecting an existing context and standalone contexts.
If no context if found for the platform we return the linux backend.
Example::
# Get the available backend
backend = get_default_backend(standalone=False/True)
# Create an opengl 3.3 context or detect the currently active
# context requiring at least opengl 3.3 support.
ctx = backend(330)
Returns:
A backend object for creating and/or detecting context
"""
PLATFORMS = {'windows', 'linux', 'darwin'}
import platform
target = platform.system().lower()
for known in PLATFORMS:
if target.startswith(known):
target = known
if target not in PLATFORMS:
target = 'linux'
if target == 'windows':
return _wgl()
if target == 'linux':
return _x11()
if target == 'darwin':
return _darwin()
raise ValueError("Cannot find suitable default backend")
def get_backend_by_name(name: str):
"""Request a specific backend by name"""
if name == 'egl':
return _egl()
raise ValueError("Cannot find supported backend: '{}'".format(name))
def _wgl():
"""Create wgl backend"""
from glcontext import wgl
def create(*args, **kwargs):
_apply_env_var(kwargs, 'glversion', 'GLCONTEXT_GLVERSION', arg_type=int)
_apply_env_var(kwargs, 'libgl', 'GLCONTEXT_WIN_LIBGL')
# make sure libgl is an absolute path
if 'libgl' in kwargs:
_libgl = kwargs['libgl']
if '/' in _libgl or '\\' in _libgl:
kwargs['libgl'] = os.path.abspath(_libgl)
kwargs = _strip_kwargs(kwargs, ['glversion', 'mode', 'libgl'])
return wgl.create_context(**kwargs)
return create
def _x11():
"""Create x11 backend"""
from glcontext import x11
from ctypes.util import find_library
def create(*args, **kwargs):
if not kwargs.get('libgl'):
kwargs['libgl'] = find_library('GL')
if not kwargs.get('libx11'):
kwargs['libx11'] = find_library("X11")
_apply_env_var(kwargs, 'glversion', 'GLCONTEXT_GLVERSION', arg_type=int)
_apply_env_var(kwargs, 'libgl', 'GLCONTEXT_LINUX_LIBGL')
_apply_env_var(kwargs, 'libx11', 'GLCONTEXT_LINUX_LIBX11')
kwargs = _strip_kwargs(kwargs, ['glversion', 'mode', 'libgl', 'libx11'])
return x11.create_context(**kwargs)
return create
def _darwin():
"""Create darwin/cgl context"""
from glcontext import darwin
def create(*args, **kwargs):
return darwin.create_context(**_strip_kwargs(kwargs, ['mode']))
return create
def _egl():
from glcontext import egl
from ctypes.util import find_library
def create(*args, **kwargs):
if not kwargs.get('libgl'):
kwargs['libgl'] = find_library('GL')
if not kwargs.get('libegl'):
kwargs['libegl'] = find_library('EGL')
_apply_env_var(kwargs, 'device_index', 'GLCONTEXT_DEVICE_INDEX', arg_type=int)
_apply_env_var(kwargs, 'glversion', 'GLCONTEXT_GLVERSION', arg_type=int)
_apply_env_var(kwargs, 'libgl', 'GLCONTEXT_LINUX_LIBGL')
_apply_env_var(kwargs, 'libegl', 'GLCONTEXT_LINUX_LIBEGL')
kwargs = _strip_kwargs(kwargs, ['glversion', 'mode', 'libgl', 'libegl', 'device_index'])
return egl.create_context(**kwargs)
return create
def _strip_kwargs(kwargs: dict, supported_args: list):
"""Strips away unwanted keyword arguments.
The backends are using ``PyArg_ParseTupleAndKeywords`` to
parse the incoming ``kwargs`` data. It's not well suited
to handle additional arguments.
- Removes None key arguments
- Removes unsupported arguments
"""
return {k: v for k, v in kwargs.items() if v is not None and k in supported_args}
def _apply_env_var(kwargs, arg_name, env_name, arg_type=str):
"""Injects an environment variable into the arg dict if present"""
value = os.environ.get(env_name, kwargs.get(arg_name))
if value:
kwargs[arg_name] = arg_type(value)
moderngl-glcontext-1573e57/glcontext/darwin.cpp 0000664 0000000 0000000 00000011502 14512447336 0021617 0 ustar 00root root 0000000 0000000 #include
#include
#include
#include
#import
#import
#import
#include
#include
struct GLContext {
PyObject_HEAD
CGLContextObj ctx;
int standalone;
void * old_context;
};
PyTypeObject * GLContext_type;
GLContext * meth_create_context(PyObject * self, PyObject * args, PyObject * kwargs) {
static char * keywords[] = {"mode", NULL};
const char * mode = "detect";
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s", keywords, &mode)) {
return NULL;
}
GLContext * res = PyObject_New(GLContext, GLContext_type);
if (!strcmp(mode, "detect")) {
res->standalone = false;
res->ctx = CGLGetCurrentContext();
if (!res->ctx) {
PyErr_Format(PyExc_Exception, "cannot detect OpenGL context");
return NULL;
}
return res;
}
if (!strcmp(mode, "standalone")) {
res->standalone = true;
GLint num_pixelformats = 0;
CGLPixelFormatObj pixelformat = 0;
CGLPixelFormatAttribute attribs[] = {
kCGLPFAOpenGLProfile,
(CGLPixelFormatAttribute)kCGLOGLPVersion_GL4_Core,
(CGLPixelFormatAttribute)0,
};
CGLChoosePixelFormat(attribs, &pixelformat, &num_pixelformats);
if (!pixelformat) {
CGLPixelFormatAttribute attribs[] = {
kCGLPFAOpenGLProfile,
(CGLPixelFormatAttribute)kCGLOGLPVersion_GL3_Core,
(CGLPixelFormatAttribute)0,
};
CGLChoosePixelFormat(attribs, &pixelformat, &num_pixelformats);
if (!pixelformat) {
CGLPixelFormatAttribute attribs[] = {
(CGLPixelFormatAttribute)0,
};
CGLChoosePixelFormat(attribs, &pixelformat, &num_pixelformats);
}
}
if (!pixelformat) {
PyErr_Format(PyExc_Exception, "cannot choose pixel format");
return NULL;
}
CGLContextObj cgl_context = NULL;
CGLCreateContext(pixelformat, NULL, &cgl_context);
CGLDestroyPixelFormat(pixelformat);
if (!cgl_context) {
PyErr_Format(PyExc_Exception, "cannot create OpenGL context");
return NULL;
}
res->ctx = cgl_context;
CGLSetCurrentContext(cgl_context);
return res;
}
PyErr_Format(PyExc_Exception, "unknown mode");
return NULL;
}
PyObject * GLContext_meth_load(GLContext * self, PyObject * arg) {
PyObject * prefix = PyUnicode_FromString("_");
PyObject * prefixed = PyNumber_Add(prefix, arg);
NSSymbol symbol = NULL;
const char * method = PyUnicode_AsUTF8(prefixed);
if (NSIsSymbolNameDefined(method)) {
symbol = NSLookupAndBindSymbol(method);
}
Py_DECREF(prefixed);
Py_DECREF(prefix);
return PyLong_FromVoidPtr(symbol ? NSAddressOfSymbol(symbol) : NULL);
}
PyObject * GLContext_meth_enter(GLContext * self) {
self->old_context = (void *)CGLGetCurrentContext();
CGLSetCurrentContext(self->ctx);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_exit(GLContext * self) {
CGLSetCurrentContext((CGLContextObj)self->old_context);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_release(GLContext * self) {
if (self->standalone) {
CGLSetCurrentContext(NULL);
CGLDestroyContext(self->ctx);
}
Py_RETURN_NONE;
}
void GLContext_dealloc(GLContext * self) {
Py_TYPE(self)->tp_free(self);
}
PyMethodDef GLContext_methods[] = {
{"load", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"load_opengl_function", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"release", (PyCFunction)GLContext_meth_release, METH_NOARGS, NULL},
{"__enter__", (PyCFunction)GLContext_meth_enter, METH_NOARGS, NULL},
{"__exit__", (PyCFunction)GLContext_meth_exit, METH_VARARGS, NULL},
{},
};
PyMemberDef GLContext_members[] = {
{"standalone", T_BOOL, offsetof(GLContext, standalone), READONLY, NULL},
{},
};
PyType_Slot GLContext_slots[] = {
{Py_tp_methods, GLContext_methods},
{Py_tp_members, GLContext_members},
{Py_tp_dealloc, (void *)GLContext_dealloc},
{},
};
PyType_Spec GLContext_spec = {"darwin.GLContext", sizeof(GLContext), 0, Py_TPFLAGS_DEFAULT, GLContext_slots};
PyMethodDef module_methods[] = {
{"create_context", (PyCFunction)meth_create_context, METH_VARARGS | METH_KEYWORDS, NULL},
{},
};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "darwin", NULL, -1, module_methods};
extern "C" PyObject * PyInit_darwin() {
PyObject * module = PyModule_Create(&module_def);
GLContext_type = (PyTypeObject *)PyType_FromSpec(&GLContext_spec);
PyModule_AddObject(module, "GLContext", (PyObject *)GLContext_type);
return module;
}
moderngl-glcontext-1573e57/glcontext/egl.cpp 0000664 0000000 0000000 00000034166 14512447336 0021115 0 ustar 00root root 0000000 0000000 #include
#include
#include
struct Display;
typedef unsigned int EGLenum;
typedef int EGLint;
typedef unsigned int EGLBoolean;
typedef Display * EGLNativeDisplayType;
typedef void * EGLConfig;
typedef void * EGLSurface;
typedef void * EGLContext;
typedef void * EGLDeviceEXT;
typedef void * EGLDisplay;
#define EGL_DEFAULT_DISPLAY 0
#define EGL_NO_CONTEXT 0
#define EGL_NO_SURFACE 0
#define EGL_NO_DISPLAY 0
#define EGL_PBUFFER_BIT 0x0001
#define EGL_WINDOW_BIT 0x0004
#define EGL_RENDERABLE_TYPE 0x3040
#define EGL_NONE 0x3038
#define EGL_OPENGL_BIT 0x0008
#define EGL_BLUE_SIZE 0x3022
#define EGL_DEPTH_SIZE 0x3025
#define EGL_RED_SIZE 0x3024
#define EGL_GREEN_SIZE 0x3023
#define EGL_SURFACE_TYPE 0x3033
#define EGL_OPENGL_API 0x30A2
#define EGL_WIDTH 0x3057
#define EGL_HEIGHT 0x3056
#define EGL_SUCCESS 0x3000
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001
#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1
#define EGL_PLATFORM_DEVICE_EXT 0x313F
#define EGL_PLATFORM_WAYLAND_EXT 0x31D8
#define EGL_PLATFORM_X11_EXT 0x31D5
#define EGL_DRAW 0x3059
#define EGL_READ 0x305A
typedef EGLint (* m_eglGetErrorProc)();
typedef EGLDisplay (* m_eglGetDisplayProc)(EGLNativeDisplayType);
typedef EGLBoolean (* m_eglInitializeProc)(EGLDisplay, EGLint *, EGLint *);
typedef EGLBoolean (* m_eglChooseConfigProc)(EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *);
typedef EGLBoolean (* m_eglBindAPIProc)(EGLenum);
typedef EGLContext (* m_eglCreateContextProc)(EGLDisplay, EGLConfig, EGLContext, const EGLint *);
typedef EGLBoolean (* m_eglDestroyContextProc)(EGLDisplay, EGLContext);
typedef EGLBoolean (* m_eglMakeCurrentProc)(EGLDisplay, EGLSurface, EGLSurface, EGLContext);
typedef void (* (* m_eglGetProcAddressProc)(const char *))();
typedef EGLBoolean (* m_eglQueryDevicesEXTProc)(EGLint, EGLDeviceEXT *, EGLint *);
typedef EGLDisplay (* m_eglGetPlatformDisplayEXTProc) (EGLenum, void *, const EGLint *);
typedef EGLContext (* m_eglGetCurrentContextProc) (void);
typedef EGLSurface (* m_eglGetCurrentSurfaceProc ) (EGLint readdraw);
typedef EGLDisplay (* m_eglGetCurrentDisplayProc )(void);
struct GLContext {
PyObject_HEAD
void * libgl;
void * libegl;
EGLContext ctx;
EGLDisplay dpy;
EGLConfig cfg;
EGLSurface wnd;
int standalone;
m_eglGetErrorProc m_eglGetError;
m_eglGetDisplayProc m_eglGetDisplay;
m_eglInitializeProc m_eglInitialize;
m_eglChooseConfigProc m_eglChooseConfig;
m_eglBindAPIProc m_eglBindAPI;
m_eglCreateContextProc m_eglCreateContext;
m_eglDestroyContextProc m_eglDestroyContext;
m_eglMakeCurrentProc m_eglMakeCurrent;
m_eglGetProcAddressProc m_eglGetProcAddress;
m_eglQueryDevicesEXTProc m_eglQueryDevicesEXT;
m_eglGetPlatformDisplayEXTProc m_eglGetPlatformDisplayEXT;
m_eglGetCurrentContextProc m_eglGetCurrentContext;
m_eglGetCurrentSurfaceProc m_eglGetCurrentSurface;
m_eglGetCurrentDisplayProc m_eglGetCurrentDisplay;
};
PyTypeObject * GLContext_type;
GLContext * meth_create_context(PyObject * self, PyObject * args, PyObject * kwargs) {
static char * keywords[] = {"mode", "libgl", "libegl", "glversion", "device_index", NULL};
const char * mode = "standalone";
const char * libgl = "libGL.so";
const char * libegl = "libEGL.so";
int glversion = 330;
int device_index = 0;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|sssii", keywords, &mode, &libgl, &libegl, &glversion, &device_index)) {
return NULL;
}
GLContext * res = PyObject_New(GLContext, GLContext_type);
res->libgl = dlopen(libgl, RTLD_LAZY);
if (!res->libgl) {
PyErr_Format(PyExc_Exception, "%s not loaded", libgl);
return NULL;
}
res->libegl = dlopen(libegl, RTLD_LAZY);
if (!res->libegl) {
PyErr_Format(PyExc_Exception, "%s not loaded", libegl);
return NULL;
}
res->m_eglGetError = (m_eglGetErrorProc)dlsym(res->libegl, "eglGetError");
if (!res->m_eglGetError) {
PyErr_Format(PyExc_Exception, "eglGetError not found");
return NULL;
}
res->m_eglGetDisplay = (m_eglGetDisplayProc)dlsym(res->libegl, "eglGetDisplay");
if (!res->m_eglGetDisplay) {
PyErr_Format(PyExc_Exception, "eglGetDisplay not found");
return NULL;
}
res->m_eglInitialize = (m_eglInitializeProc)dlsym(res->libegl, "eglInitialize");
if (!res->m_eglInitialize) {
PyErr_Format(PyExc_Exception, "eglInitialize not found");
return NULL;
}
res->m_eglChooseConfig = (m_eglChooseConfigProc)dlsym(res->libegl, "eglChooseConfig");
if (!res->m_eglChooseConfig) {
PyErr_Format(PyExc_Exception, "eglChooseConfig not found");
return NULL;
}
res->m_eglBindAPI = (m_eglBindAPIProc)dlsym(res->libegl, "eglBindAPI");
if (!res->m_eglBindAPI) {
PyErr_Format(PyExc_Exception, "eglBindAPI not found");
return NULL;
}
res->m_eglCreateContext = (m_eglCreateContextProc)dlsym(res->libegl, "eglCreateContext");
if (!res->m_eglCreateContext) {
PyErr_Format(PyExc_Exception, "eglCreateContext not found");
return NULL;
}
res->m_eglDestroyContext = (m_eglDestroyContextProc)dlsym(res->libegl, "eglDestroyContext");
if (!res->m_eglDestroyContext) {
PyErr_Format(PyExc_Exception, "eglDestroyContext not found");
return NULL;
}
res->m_eglMakeCurrent = (m_eglMakeCurrentProc)dlsym(res->libegl, "eglMakeCurrent");
if (!res->m_eglMakeCurrent) {
PyErr_Format(PyExc_Exception, "eglMakeCurrent not found");
return NULL;
}
res->m_eglGetProcAddress = (m_eglGetProcAddressProc)dlsym(res->libegl, "eglGetProcAddress");
if (!res->m_eglGetProcAddress) {
PyErr_Format(PyExc_Exception, "eglGetProcAddress not found");
return NULL;
}
res->m_eglQueryDevicesEXT = (m_eglQueryDevicesEXTProc)res->m_eglGetProcAddress("eglQueryDevicesEXT");
if (!res->m_eglQueryDevicesEXT) {
PyErr_Format(PyExc_Exception, "eglQueryDevicesEXT not found");
return NULL;
}
res->m_eglGetPlatformDisplayEXT = (m_eglGetPlatformDisplayEXTProc)res->m_eglGetProcAddress("eglGetPlatformDisplayEXT");
if (!res->m_eglGetPlatformDisplayEXT) {
PyErr_Format(PyExc_Exception, "eglGetPlatformDisplayEXT not found");
return NULL;
}
res->m_eglGetCurrentDisplay = (m_eglGetCurrentDisplayProc)res->m_eglGetProcAddress("eglGetCurrentDisplay");
if (!res->m_eglGetCurrentDisplay) {
PyErr_Format(PyExc_Exception, "eglGetCurrentDisplay not found");
return NULL;
}
res->m_eglGetCurrentContext = (m_eglGetCurrentContextProc)res->m_eglGetProcAddress("eglGetCurrentContext");
if (!res->m_eglGetCurrentContext) {
PyErr_Format(PyExc_Exception, "eglGetCurrentContext not found");
return NULL;
}
res->m_eglGetCurrentSurface = (m_eglGetCurrentSurfaceProc)res->m_eglGetProcAddress("eglGetCurrentSurface");
if (!res->m_eglGetCurrentSurface) {
PyErr_Format(PyExc_Exception, "eglGetCurrentSurfaceProc not found");
return NULL;
}
if (!strcmp(mode, "standalone")) {
res->standalone = true;
res->wnd = EGL_NO_SURFACE;
EGLint num_devices;
if (!res->m_eglQueryDevicesEXT(0, NULL, &num_devices)) {
PyErr_Format(PyExc_Exception, "eglQueryDevicesEXT failed (0x%x)", res->m_eglGetError());
return NULL;
}
if (device_index >= num_devices) {
PyErr_Format(PyExc_Exception, "requested device index %d, but found %d devices", device_index, num_devices);
return NULL;
}
EGLDeviceEXT * devices = (EGLDeviceEXT *)malloc(sizeof(EGLDeviceEXT) * num_devices);
if (!res->m_eglQueryDevicesEXT(num_devices, devices, &num_devices)) {
PyErr_Format(PyExc_Exception, "eglQueryDevicesEXT failed (0x%x)", res->m_eglGetError());
free(devices);
return NULL;
}
EGLDeviceEXT device = devices[device_index];
free(devices);
res->dpy = res->m_eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, device, 0);
if (res->dpy == EGL_NO_DISPLAY) {
PyErr_Format(PyExc_Exception, "eglGetPlatformDisplayEXT failed (0x%x)", res->m_eglGetError());
return NULL;
}
EGLint major, minor;
if (!res->m_eglInitialize(res->dpy, &major, &minor)) {
PyErr_Format(PyExc_Exception, "eglInitialize failed (0x%x)", res->m_eglGetError());
return NULL;
}
EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
EGLint num_configs = 0;
if (!res->m_eglChooseConfig(res->dpy, config_attribs, &res->cfg, 1, &num_configs)) {
PyErr_Format(PyExc_Exception, "eglChooseConfig failed (0x%x)", res->m_eglGetError());
return NULL;
}
if (!res->m_eglBindAPI(EGL_OPENGL_API)) {
PyErr_Format(PyExc_Exception, "eglBindAPI failed (0x%x)", res->m_eglGetError());
return NULL;
}
int ctxattribs[] = {
EGL_CONTEXT_MAJOR_VERSION, glversion / 100 % 10,
EGL_CONTEXT_MINOR_VERSION, glversion / 10 % 10,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
// EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, 1,
EGL_NONE,
};
res->ctx = res->m_eglCreateContext(res->dpy, res->cfg, EGL_NO_CONTEXT, ctxattribs);
if (!res->ctx) {
PyErr_Format(PyExc_Exception, "eglCreateContext failed (0x%x)", res->m_eglGetError());
return NULL;
}
res->m_eglMakeCurrent(res->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, res->ctx);
return res;
}
if (!strcmp(mode, "share")) {
res->standalone = false;
EGLContext ctx_share = res->m_eglGetCurrentContext();
if (!ctx_share) {
PyErr_Format(PyExc_Exception, "(share) eglGetCurrentContext: cannot detect OpenGL context");
return NULL;
}
res->wnd = res->m_eglGetCurrentSurface(EGL_DRAW);
if (!res->wnd) {
PyErr_Format(PyExc_Exception, "(share) m_eglGetCurrentSurface failed (0x%x)", res->m_eglGetError());
return NULL;
}
res->dpy = res->m_eglGetCurrentDisplay();
if (res->dpy == EGL_NO_DISPLAY) {
PyErr_Format(PyExc_Exception, "eglGetCurrentDisplay failed (0x%x)", res->m_eglGetError());
return NULL;
}
EGLint config_attribs[] = {
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_DEPTH_SIZE, 24,
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE
};
EGLint num_configs = 0;
if (!res->m_eglChooseConfig(res->dpy, config_attribs, &res->cfg, 1, &num_configs)) {
PyErr_Format(PyExc_Exception, "eglChooseConfig failed (0x%x)", res->m_eglGetError());
return NULL;
}
if (!res->m_eglBindAPI(EGL_OPENGL_API)) {
PyErr_Format(PyExc_Exception, "eglBindAPI failed (0x%x)", res->m_eglGetError());
return NULL;
}
int ctxattribs[] = {
EGL_CONTEXT_MAJOR_VERSION, glversion / 100 % 10,
EGL_CONTEXT_MINOR_VERSION, glversion / 10 % 10,
EGL_CONTEXT_OPENGL_PROFILE_MASK, EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT,
// EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE, 1,
EGL_NONE,
};
res->ctx = res->m_eglCreateContext(res->dpy, res->cfg, ctx_share, ctxattribs);
if (!res->ctx) {
PyErr_Format(PyExc_Exception, "eglCreateContext failed (0x%x)", res->m_eglGetError());
return NULL;
}
res->m_eglMakeCurrent(res->dpy, res->wnd, res->wnd, res->ctx);
return res;
}
PyErr_Format(PyExc_Exception, "unknown mode");
return NULL;
}
PyObject * GLContext_meth_load(GLContext * self, PyObject * arg) {
const char * method = PyUnicode_AsUTF8(arg);
void * proc = (void *)dlsym(self->libgl, method);
if (!proc) {
proc = (void *)self->m_eglGetProcAddress(method);
}
return PyLong_FromVoidPtr(proc);
}
PyObject * GLContext_meth_enter(GLContext * self) {
self->m_eglMakeCurrent(self->dpy, self->wnd, self->wnd, self->ctx);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_exit(GLContext * self) {
self->m_eglMakeCurrent(self->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_release(GLContext * self) {
self->m_eglDestroyContext(self->dpy, self->ctx);
Py_RETURN_NONE;
}
void GLContext_dealloc(GLContext * self) {
Py_TYPE(self)->tp_free(self);
}
PyMethodDef GLContext_methods[] = {
{"load", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"load_opengl_function", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"release", (PyCFunction)GLContext_meth_release, METH_NOARGS, NULL},
{"__enter__", (PyCFunction)GLContext_meth_enter, METH_NOARGS, NULL},
{"__exit__", (PyCFunction)GLContext_meth_exit, METH_VARARGS, NULL},
{},
};
PyMemberDef GLContext_members[] = {
{"standalone", T_BOOL, offsetof(GLContext, standalone), READONLY, NULL},
{},
};
PyType_Slot GLContext_slots[] = {
{Py_tp_methods, GLContext_methods},
{Py_tp_members, GLContext_members},
{Py_tp_dealloc, (void *)GLContext_dealloc},
{},
};
PyType_Spec GLContext_spec = {"egl.GLContext", sizeof(GLContext), 0, Py_TPFLAGS_DEFAULT, GLContext_slots};
PyMethodDef module_methods[] = {
{"create_context", (PyCFunction)meth_create_context, METH_VARARGS | METH_KEYWORDS, NULL},
{},
};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "egl", NULL, -1, module_methods};
extern "C" PyObject * PyInit_egl() {
PyObject * module = PyModule_Create(&module_def);
GLContext_type = (PyTypeObject *)PyType_FromSpec(&GLContext_spec);
PyModule_AddObject(module, "GLContext", (PyObject *)GLContext_type);
return module;
}
moderngl-glcontext-1573e57/glcontext/empty.cpp 0000664 0000000 0000000 00000003533 14512447336 0021476 0 ustar 00root root 0000000 0000000 #include
struct GLContext {
PyObject_HEAD
};
PyTypeObject * GLContext_type;
GLContext * meth_create_context(PyObject * self, PyObject * args, PyObject * kwargs) {
static char * keywords[] = {NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", keywords)) {
return NULL;
}
GLContext * res = PyObject_New(GLContext, GLContext_type);
return res;
}
PyObject * GLContext_meth_load(GLContext * self, PyObject * arg) {
return PyLong_FromVoidPtr(NULL);
}
PyObject * GLContext_meth_enter(GLContext * self) {
Py_RETURN_NONE;
}
PyObject * GLContext_meth_exit(GLContext * self) {
Py_RETURN_NONE;
}
PyObject * GLContext_meth_release(GLContext * self) {
Py_RETURN_NONE;
}
void GLContext_dealloc(GLContext * self) {
Py_TYPE(self)->tp_free(self);
}
PyMethodDef GLContext_methods[] = {
{"load_opengl_function", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"release", (PyCFunction)GLContext_meth_release, METH_NOARGS, NULL},
{"__enter__", (PyCFunction)GLContext_meth_enter, METH_NOARGS, NULL},
{"__exit__", (PyCFunction)GLContext_meth_exit, METH_VARARGS, NULL},
{},
};
PyType_Slot GLContext_slots[] = {
{Py_tp_methods, GLContext_methods},
{Py_tp_dealloc, (void *)GLContext_dealloc},
{},
};
PyType_Spec GLContext_spec = {"empty.GLContext", sizeof(GLContext), 0, Py_TPFLAGS_DEFAULT, GLContext_slots};
PyMethodDef module_methods[] = {
{"create_context", (PyCFunction)meth_create_context, METH_VARARGS | METH_KEYWORDS, NULL},
{},
};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "empty", NULL, -1, module_methods};
extern "C" PyObject * PyInit_empty() {
PyObject * module = PyModule_Create(&module_def);
GLContext_type = (PyTypeObject *)PyType_FromSpec(&GLContext_spec);
PyModule_AddObject(module, "GLContext", (PyObject *)GLContext_type);
return module;
}
moderngl-glcontext-1573e57/glcontext/empty.py 0000664 0000000 0000000 00000000432 14512447336 0021337 0 ustar 00root root 0000000 0000000 class GLContext:
def __init__(self):
pass
def load_opengl_function(self, name):
return 0
def __enter__(self):
pass
def __exit__(self, *args):
pass
def release(self):
pass
def create_context():
return GLContext()
moderngl-glcontext-1573e57/glcontext/headless.cpp 0000664 0000000 0000000 00000006013 14512447336 0022124 0 ustar 00root root 0000000 0000000 #include
#include
#include
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;
}
moderngl-glcontext-1573e57/glcontext/wgl.cpp 0000664 0000000 0000000 00000026224 14512447336 0021133 0 ustar 00root root 0000000 0000000 #include
#include
#include
#define WGL_CONTEXT_PROFILE_MASK 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT 0x0001
#define WGL_CONTEXT_MAJOR_VERSION 0x2091
#define WGL_CONTEXT_MINOR_VERSION 0x2092
typedef HGLRC (WINAPI * m_wglGetCurrentContextProc)();
typedef HDC (WINAPI * m_wglGetCurrentDCProc)();
typedef HGLRC (WINAPI * m_wglCreateContextProc)(HDC);
typedef BOOL (WINAPI * m_wglDeleteContextProc)(HGLRC);
typedef PROC (WINAPI * m_wglGetProcAddressProc)(LPCSTR);
typedef BOOL (WINAPI * m_wglMakeCurrentProc)(HDC, HGLRC);
typedef HGLRC (WINAPI * m_wglCreateContextAttribsARBProc)(HDC, HGLRC, const int *);
typedef BOOL (WINAPI * m_wglSwapIntervalEXTProc)(int);
HINSTANCE hinst;
struct GLContext {
PyObject_HEAD
HMODULE libgl;
HWND hwnd;
HDC hdc;
HGLRC hrc;
int standalone;
void * old_context;
void * old_display;
m_wglGetCurrentContextProc m_wglGetCurrentContext;
m_wglGetCurrentDCProc m_wglGetCurrentDC;
m_wglCreateContextProc m_wglCreateContext;
m_wglDeleteContextProc m_wglDeleteContext;
m_wglGetProcAddressProc m_wglGetProcAddress;
m_wglMakeCurrentProc m_wglMakeCurrent;
m_wglCreateContextAttribsARBProc m_wglCreateContextAttribsARB;
m_wglSwapIntervalEXTProc m_wglSwapIntervalEXT;
};
PyTypeObject * GLContext_type;
GLContext * meth_create_context(PyObject * self, PyObject * args, PyObject * kwargs) {
static char * keywords[] = {"mode", "libgl", "glversion", NULL};
const char * mode = "detect";
const char * libgl = "opengl32.dll";
int glversion = 330;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ssi", keywords, &mode, &libgl, &glversion)) {
return NULL;
}
GLContext * res = PyObject_New(GLContext, GLContext_type);
// The mode parameter is required for dll's specifed as libgl
// to load successfully along with its dependencies on Python 3.8+.
// This is due to the introduction of using a short dll load path
// inside of Python 3.8+.
int load_mode = LOAD_LIBRARY_SEARCH_DEFAULT_DIRS; // Search default dirs first
// Check whether libgl contains `/` or `\\`.
// We can treat that `libgl` would be absolute in that case.
if (strchr(libgl, '/') || strchr(libgl, '\\'))
{
// Search the dirs in which the dll is located
load_mode |= LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;
}
res->libgl = LoadLibraryEx(libgl, NULL, (DWORD)load_mode);
if (!res->libgl) {
DWORD last_error = GetLastError();
PyErr_Format(PyExc_Exception, "%s not loaded. Error code: %ld.", libgl, last_error);
return NULL;
}
res->m_wglGetCurrentContext = (m_wglGetCurrentContextProc)GetProcAddress(res->libgl, "wglGetCurrentContext");
if (!res->m_wglGetCurrentContext) {
PyErr_Format(PyExc_Exception, "wglGetCurrentContext not found");
return NULL;
}
res->m_wglGetCurrentDC = (m_wglGetCurrentDCProc)GetProcAddress(res->libgl, "wglGetCurrentDC");
if (!res->m_wglGetCurrentDC) {
PyErr_Format(PyExc_Exception, "wglGetCurrentDC not found");
return NULL;
}
res->m_wglCreateContext = (m_wglCreateContextProc)GetProcAddress(res->libgl, "wglCreateContext");
if (!res->m_wglCreateContext) {
PyErr_Format(PyExc_Exception, "wglCreateContext not found");
return NULL;
}
res->m_wglDeleteContext = (m_wglDeleteContextProc)GetProcAddress(res->libgl, "wglDeleteContext");
if (!res->m_wglDeleteContext) {
PyErr_Format(PyExc_Exception, "wglDeleteContext not found");
return NULL;
}
res->m_wglGetProcAddress = (m_wglGetProcAddressProc)GetProcAddress(res->libgl, "wglGetProcAddress");
if (!res->m_wglGetProcAddress) {
PyErr_Format(PyExc_Exception, "wglGetProcAddress not found");
return NULL;
}
res->m_wglMakeCurrent = (m_wglMakeCurrentProc)GetProcAddress(res->libgl, "wglMakeCurrent");
if (!res->m_wglMakeCurrent) {
PyErr_Format(PyExc_Exception, "wglMakeCurrent not found");
return NULL;
}
if (!strcmp(mode, "detect")) {
res->hwnd = NULL;
res->hrc = res->m_wglGetCurrentContext();
if (!res->hrc) {
PyErr_Format(PyExc_Exception, "cannot detect OpenGL context");
return NULL;
}
res->hdc = res->m_wglGetCurrentDC();
if (!res->hdc) {
PyErr_Format(PyExc_Exception, "wglGetCurrentDC failed");
return NULL;
}
return res;
}
if (!strcmp(mode, "share")) {
res->hwnd = NULL;
res->standalone = true;
HGLRC hrc_share = res->m_wglGetCurrentContext();
if (!hrc_share) {
PyErr_Format(PyExc_Exception, "cannot detect OpenGL context");
return NULL;
}
res->hdc = res->m_wglGetCurrentDC();
if (!res->hdc) {
PyErr_Format(PyExc_Exception, "wglGetCurrentDC failed");
return NULL;
}
FARPROC proc = res->m_wglGetProcAddress("wglCreateContextAttribsARB");
res->m_wglCreateContextAttribsARB = (m_wglCreateContextAttribsARBProc)proc;
if (!res->m_wglCreateContextAttribsARB) {
PyErr_Format(PyExc_Exception, "wglCreateContextAttribsARB failed");
return NULL;
}
res->m_wglMakeCurrent(NULL, NULL);
int attribs[] = {
WGL_CONTEXT_PROFILE_MASK, WGL_CONTEXT_CORE_PROFILE_BIT,
WGL_CONTEXT_MAJOR_VERSION, glversion / 100 % 10,
WGL_CONTEXT_MINOR_VERSION, glversion / 10 % 10,
0, 0,
};
res->hrc = res->m_wglCreateContextAttribsARB(res->hdc, hrc_share, attribs);
if (!res->hrc) {
PyErr_Format(PyExc_Exception, "wglCreateContextAttribsARB failed");
return NULL;
}
if (!res->m_wglMakeCurrent(res->hdc, res->hrc)) {
PyErr_Format(PyExc_Exception, "wglMakeCurrent failed");
return NULL;
}
return res;
}
if (!strcmp(mode, "standalone")) {
res->standalone = true;
res->hwnd = CreateWindow("glcontext", NULL, 0, 0, 0, 0, 0, NULL, NULL, hinst, NULL);
if (!res->hwnd) {
PyErr_Format(PyExc_Exception, "CreateWindow failed");
return NULL;
}
res->hdc = GetDC(res->hwnd);
if (!res->hdc) {
PyErr_Format(PyExc_Exception, "GetDC failed");
return NULL;
}
PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_GENERIC_ACCELERATED | PFD_DOUBLEBUFFER,
0,
24,
};
int pixelformat = ChoosePixelFormat(res->hdc, &pfd);
if (!pixelformat) {
PyErr_Format(PyExc_Exception, "ChoosePixelFormat failed");
return NULL;
}
if (!SetPixelFormat(res->hdc, pixelformat, &pfd)) {
PyErr_Format(PyExc_Exception, "SetPixelFormat failed");
return NULL;
}
HGLRC hrc_share = res->m_wglCreateContext(res->hdc);
if (!hrc_share) {
PyErr_Format(PyExc_Exception, "wglCreateContext failed");
return NULL;
}
if (!res->m_wglMakeCurrent(res->hdc, hrc_share)) {
PyErr_Format(PyExc_Exception, "wglMakeCurrent failed");
return NULL;
}
FARPROC proc = res->m_wglGetProcAddress("wglCreateContextAttribsARB");
res->m_wglCreateContextAttribsARB = (m_wglCreateContextAttribsARBProc)proc;
if (!res->m_wglCreateContextAttribsARB) {
PyErr_Format(PyExc_Exception, "wglCreateContextAttribsARB not found");
return NULL;
}
res->m_wglMakeCurrent(NULL, NULL);
if (!res->m_wglDeleteContext(hrc_share)) {
PyErr_Format(PyExc_Exception, "wglDeleteContext failed");
return NULL;
}
int attribs[] = {
WGL_CONTEXT_PROFILE_MASK, WGL_CONTEXT_CORE_PROFILE_BIT,
WGL_CONTEXT_MAJOR_VERSION, glversion / 100 % 10,
WGL_CONTEXT_MINOR_VERSION, glversion / 10 % 10,
0, 0,
};
res->hrc = res->m_wglCreateContextAttribsARB(res->hdc, NULL, attribs);
if (!res->hrc) {
PyErr_Format(PyExc_Exception, "wglCreateContextAttribsARB failed");
return NULL;
}
if (!res->m_wglMakeCurrent(res->hdc, res->hrc)) {
PyErr_Format(PyExc_Exception, "wglMakeCurrent failed");
return NULL;
}
return res;
}
PyErr_Format(PyExc_Exception, "unknown mode");
return NULL;
}
PyObject * GLContext_meth_load(GLContext * self, PyObject * arg) {
const char * name = PyUnicode_AsUTF8(arg);
void * proc = (void *)GetProcAddress(self->libgl, name);
if (!proc) {
proc = (void *)self->m_wglGetProcAddress(name);
}
return PyLong_FromVoidPtr(proc);
}
PyObject * GLContext_meth_enter(GLContext * self) {
self->old_context = (void *)self->m_wglGetCurrentContext();
self->old_display = (void *)self->m_wglGetCurrentDC();
self->m_wglMakeCurrent(self->hdc, self->hrc);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_exit(GLContext * self) {
self->m_wglMakeCurrent((HDC)self->old_display, (HGLRC)self->old_context);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_release(GLContext * self) {
self->m_wglMakeCurrent(NULL, NULL);
self->m_wglDeleteContext(self->hrc);
if (self->standalone) {
ReleaseDC(self->hwnd, self->hdc);
DestroyWindow(self->hwnd);
}
Py_RETURN_NONE;
}
void GLContext_dealloc(GLContext * self) {
Py_TYPE(self)->tp_free(self);
}
PyMethodDef GLContext_methods[] = {
{"load", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"load_opengl_function", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"release", (PyCFunction)GLContext_meth_release, METH_NOARGS, NULL},
{"__enter__", (PyCFunction)GLContext_meth_enter, METH_NOARGS, NULL},
{"__exit__", (PyCFunction)GLContext_meth_exit, METH_VARARGS, NULL},
{},
};
PyMemberDef GLContext_members[] = {
{"standalone", T_BOOL, offsetof(GLContext, standalone), READONLY, NULL},
{},
};
PyType_Slot GLContext_slots[] = {
{Py_tp_methods, GLContext_methods},
{Py_tp_members, GLContext_members},
{Py_tp_dealloc, (void *)GLContext_dealloc},
{},
};
PyType_Spec GLContext_spec = {"wgl.GLContext", sizeof(GLContext), 0, Py_TPFLAGS_DEFAULT, GLContext_slots};
PyMethodDef module_methods[] = {
{"create_context", (PyCFunction)meth_create_context, METH_VARARGS | METH_KEYWORDS, NULL},
{},
};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "wgl", NULL, -1, module_methods};
extern "C" PyObject * PyInit_wgl() {
PyObject * module = PyModule_Create(&module_def);
GLContext_type = (PyTypeObject *)PyType_FromSpec(&GLContext_spec);
PyModule_AddObject(module, "GLContext", (PyObject *)GLContext_type);
return module;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_ATTACH) {
hinst = hinstDLL;
WNDCLASSEX wnd_class = {
sizeof(WNDCLASSEX), CS_OWNDC, DefWindowProc, 0, 0, hinst, NULL, NULL, NULL, NULL, "glcontext", NULL,
};
if (!RegisterClassEx(&wnd_class)) {
return NULL;
}
}
return true;
}
moderngl-glcontext-1573e57/glcontext/windowed.cpp 0000664 0000000 0000000 00000003621 14512447336 0022156 0 ustar 00root root 0000000 0000000 #include
#if defined(_WIN32) || defined(_WIN64)
#include
PyObject * meth_load_opengl_function(PyObject * self, PyObject * arg) {
if (!PyUnicode_CheckExact(arg)) {
return NULL;
}
HMODULE module = GetModuleHandle("opengl32");
if (!module) {
return NULL;
}
const char * name = PyUnicode_AsUTF8(arg);
void * proc = (void *)GetProcAddress(module, name);
if (!proc) {
proc = wglGetProcAddress(name);
}
return PyLong_FromVoidPtr(proc);
}
#elif defined(__APPLE__)
#include
#include
#import
#import
#import
#include
#include
PyObject * meth_load_opengl_function(PyObject * self, PyObject * arg) {
if (!PyUnicode_CheckExact(arg)) {
return NULL;
}
PyObject * prefix = PyUnicode_FromString("_");
PyObject * prefixed = PyNumber_Add(prefix, arg);
NSSymbol symbol = NULL;
const char * method = PyUnicode_AsUTF8(prefixed);
if (NSIsSymbolNameDefined(method)) {
symbol = NSLookupAndBindSymbol(method);
}
Py_DECREF(prefixed);
Py_DECREF(prefix);
return PyLong_FromVoidPtr(symbol ? NSAddressOfSymbol(symbol) : NULL);
}
#else
#include
#include
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 *)glXGetProcAddress((unsigned char *)name));
}
#endif
PyMethodDef module_methods[] = {
{"load_opengl_function", (PyCFunction)meth_load_opengl_function, METH_O},
{},
};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "windowed", NULL, -1, module_methods};
extern "C" PyObject * PyInit_windowed() {
PyObject * module = PyModule_Create(&module_def);
return module;
}
moderngl-glcontext-1573e57/glcontext/x11.cpp 0000664 0000000 0000000 00000043335 14512447336 0020755 0 ustar 00root root 0000000 0000000 #include
#include
#include
#include
#include
#define GLX_CONTEXT_MAJOR_VERSION 0x2091
#define GLX_CONTEXT_MINOR_VERSION 0x2092
#define GLX_CONTEXT_PROFILE_MASK 0x9126
#define GLX_CONTEXT_CORE_PROFILE_BIT 0x0001
#define GLX_RGBA 4
#define GLX_DOUBLEBUFFER 5
#define GLX_RED_SIZE 8
#define GLX_GREEN_SIZE 9
#define GLX_BLUE_SIZE 10
#define GLX_DEPTH_SIZE 12
typedef struct __GLXcontextRec * GLXContext;
typedef struct __GLXFBConfigRec * GLXFBConfig;
typedef XID GLXDrawable;
typedef GLXFBConfig * (* m_glXChooseFBConfigProc)(Display *, int, const int *, int *);
typedef XVisualInfo * (* m_glXChooseVisualProc)(Display *, int, int *);
typedef Display * (* m_glXGetCurrentDisplayProc)();
typedef GLXContext (* m_glXGetCurrentContextProc)();
typedef GLXDrawable (* m_glXGetCurrentDrawableProc)();
typedef Bool (* m_glXMakeCurrentProc)(Display *, GLXDrawable, GLXContext);
typedef void (* m_glXDestroyContextProc)(Display *, GLXContext);
typedef GLXContext (* m_glXCreateContextProc)(Display *, XVisualInfo *, GLXContext, Bool);
typedef void (*(* m_glXGetProcAddressProc)(const unsigned char *))();
typedef GLXContext (* m_glXCreateContextAttribsARBProc)(Display *, GLXFBConfig, GLXContext, int, const int *);
typedef Display * (* m_XOpenDisplayProc)(const char *);
typedef int (* m_XDefaultScreenProc)(Display *);
typedef Window (* m_XRootWindowProc)(Display *, int);
typedef Colormap (* m_XCreateColormapProc)(Display *, Window, Visual *, int);
typedef Window (* m_XCreateWindowProc)(Display *, Window, int, int, unsigned int, unsigned int, unsigned int, int, unsigned int, Visual *, unsigned long, XSetWindowAttributes *);
typedef int (* m_XDestroyWindowProc)(Display *, Window);
typedef int (* m_XCloseDisplayProc)(Display *);
typedef int (* m_XFreeProc)(void *);
typedef XErrorHandler (* m_XSetErrorHandlerProc)(XErrorHandler);
int SilentXErrorHandler(Display * d, XErrorEvent * e) {
return 0;
}
struct GLContext {
PyObject_HEAD
void * libgl;
void * libx11;
Display * dpy;
GLXFBConfig * fbc;
XVisualInfo * vi;
Window wnd;
GLXContext ctx;
int standalone;
int own_window;
void * old_context;
void * old_display;
void * old_window;
m_glXChooseFBConfigProc m_glXChooseFBConfig;
m_glXChooseVisualProc m_glXChooseVisual;
m_glXGetCurrentDisplayProc m_glXGetCurrentDisplay;
m_glXGetCurrentContextProc m_glXGetCurrentContext;
m_glXGetCurrentDrawableProc m_glXGetCurrentDrawable;
m_glXMakeCurrentProc m_glXMakeCurrent;
m_glXDestroyContextProc m_glXDestroyContext;
m_glXCreateContextProc m_glXCreateContext;
m_glXGetProcAddressProc m_glXGetProcAddress;
m_glXCreateContextAttribsARBProc m_glXCreateContextAttribsARB;
m_XOpenDisplayProc m_XOpenDisplay;
m_XDefaultScreenProc m_XDefaultScreen;
m_XRootWindowProc m_XRootWindow;
m_XCreateColormapProc m_XCreateColormap;
m_XCreateWindowProc m_XCreateWindow;
m_XDestroyWindowProc m_XDestroyWindow;
m_XCloseDisplayProc m_XCloseDisplay;
m_XFreeProc m_XFree;
m_XSetErrorHandlerProc m_XSetErrorHandler;
};
PyTypeObject * GLContext_type;
GLContext * meth_create_context(PyObject * self, PyObject * args, PyObject * kwargs) {
static char * keywords[] = {"mode", "libgl", "libx11", "glversion", NULL};
const char * mode = "detect";
const char * libgl = "libGL.so";
const char * libx11 = "libX11.so";
int glversion = 330;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|sssi", keywords, &mode, &libgl, &libx11, &glversion)) {
return NULL;
}
GLContext * res = PyObject_New(GLContext, GLContext_type);
res->libgl = dlopen(libgl, RTLD_LAZY);
if (!res->libgl) {
PyErr_Format(PyExc_Exception, "%s not found in /lib, /usr/lib or LD_LIBRARY_PATH", libgl);
return NULL;
}
res->m_glXChooseFBConfig = (m_glXChooseFBConfigProc)dlsym(res->libgl, "glXChooseFBConfig");
if (!res->m_glXChooseFBConfig) {
PyErr_Format(PyExc_Exception, "glXChooseFBConfig not found");
return NULL;
}
res->m_glXChooseVisual = (m_glXChooseVisualProc)dlsym(res->libgl, "glXChooseVisual");
if (!res->m_glXChooseVisual) {
PyErr_Format(PyExc_Exception, "glXChooseVisual not found");
return NULL;
}
res->m_glXGetCurrentDisplay = (m_glXGetCurrentDisplayProc)dlsym(res->libgl, "glXGetCurrentDisplay");
if (!res->m_glXGetCurrentDisplay) {
PyErr_Format(PyExc_Exception, "glXGetCurrentDisplay not found");
return NULL;
}
res->m_glXGetCurrentContext = (m_glXGetCurrentContextProc)dlsym(res->libgl, "glXGetCurrentContext");
if (!res->m_glXGetCurrentContext) {
PyErr_Format(PyExc_Exception, "glXGetCurrentContext not found");
return NULL;
}
res->m_glXGetCurrentDrawable = (m_glXGetCurrentDrawableProc)dlsym(res->libgl, "glXGetCurrentDrawable");
if (!res->m_glXGetCurrentDrawable) {
PyErr_Format(PyExc_Exception, "glXGetCurrentDrawable not found");
return NULL;
}
res->m_glXMakeCurrent = (m_glXMakeCurrentProc)dlsym(res->libgl, "glXMakeCurrent");
if (!res->m_glXMakeCurrent) {
PyErr_Format(PyExc_Exception, "glXMakeCurrent not found");
return NULL;
}
res->m_glXDestroyContext = (m_glXDestroyContextProc)dlsym(res->libgl, "glXDestroyContext");
if (!res->m_glXDestroyContext) {
PyErr_Format(PyExc_Exception, "glXDestroyContext not found");
return NULL;
}
res->m_glXCreateContext = (m_glXCreateContextProc)dlsym(res->libgl, "glXCreateContext");
if (!res->m_glXCreateContext) {
PyErr_Format(PyExc_Exception, "glXCreateContext not found");
return NULL;
}
res->m_glXGetProcAddress = (m_glXGetProcAddressProc)dlsym(res->libgl, "glXGetProcAddress");
if (!res->m_glXGetProcAddress) {
PyErr_Format(PyExc_Exception, "glXGetProcAddress not found");
return NULL;
}
if (strcmp(mode, "detect")) {
res->libx11 = dlopen(libx11, RTLD_LAZY);
if (!res->libx11) {
PyErr_Format(PyExc_Exception, "(detect) %s not loaded", libx11);
return NULL;
}
res->m_XOpenDisplay = (m_XOpenDisplayProc)dlsym(res->libx11, "XOpenDisplay");
if (!res->m_XOpenDisplay) {
PyErr_Format(PyExc_Exception, "(detect) XOpenDisplay not found");
return NULL;
}
res->m_XDefaultScreen = (m_XDefaultScreenProc)dlsym(res->libx11, "XDefaultScreen");
if (!res->m_XDefaultScreen) {
PyErr_Format(PyExc_Exception, "(detect) XDefaultScreen not found");
return NULL;
}
res->m_XRootWindow = (m_XRootWindowProc)dlsym(res->libx11, "XRootWindow");
if (!res->m_XRootWindow) {
PyErr_Format(PyExc_Exception, "(detect) XRootWindow not found");
return NULL;
}
res->m_XCreateColormap = (m_XCreateColormapProc)dlsym(res->libx11, "XCreateColormap");
if (!res->m_XCreateColormap) {
PyErr_Format(PyExc_Exception, "(detect) XCreateColormap not found");
return NULL;
}
res->m_XCreateWindow = (m_XCreateWindowProc)dlsym(res->libx11, "XCreateWindow");
if (!res->m_XCreateWindow) {
PyErr_Format(PyExc_Exception, "(detect) XCreateWindow not found");
return NULL;
}
res->m_XDestroyWindow = (m_XDestroyWindowProc)dlsym(res->libx11, "XDestroyWindow");
if (!res->m_XDestroyWindow) {
PyErr_Format(PyExc_Exception, "(detect) XDestroyWindow not found");
return NULL;
}
res->m_XCloseDisplay = (m_XCloseDisplayProc)dlsym(res->libx11, "XCloseDisplay");
if (!res->m_XCloseDisplay) {
PyErr_Format(PyExc_Exception, "(detect) XCloseDisplay not found");
return NULL;
}
res->m_XFree = (m_XFreeProc)dlsym(res->libx11, "XFree");
if (!res->m_XFree) {
PyErr_Format(PyExc_Exception, "(detect) XFree not found");
return NULL;
}
res->m_XSetErrorHandler = (m_XSetErrorHandlerProc)dlsym(res->libx11, "XSetErrorHandler");
if (!res->m_XSetErrorHandler) {
PyErr_Format(PyExc_Exception, "(detect) XSetErrorHandler not found");
return NULL;
}
}
if (!strcmp(mode, "detect")) {
res->standalone = false;
res->own_window = false;
res->ctx = res->m_glXGetCurrentContext();
if (!res->ctx) {
PyErr_Format(PyExc_Exception, "(detect) glXGetCurrentContext: cannot detect OpenGL context");
return NULL;
}
res->wnd = res->m_glXGetCurrentDrawable();
if (!res->wnd) {
PyErr_Format(PyExc_Exception, "(detect) glXGetCurrentDrawable failed");
return NULL;
}
res->dpy = res->m_glXGetCurrentDisplay();
if (!res->dpy) {
PyErr_Format(PyExc_Exception, "(detect) glXGetCurrentDisplay failed");
return NULL;
}
res->fbc = NULL;
res->vi = NULL;
return res;
}
if (!strcmp(mode, "share")) {
res->standalone = true;
res->own_window = false;
GLXContext ctx_share = res->m_glXGetCurrentContext();
if (!ctx_share) {
PyErr_Format(PyExc_Exception, "(share) glXGetCurrentContext: cannot detect OpenGL context");
return NULL;
}
res->wnd = res->m_glXGetCurrentDrawable();
if (!res->wnd) {
PyErr_Format(PyExc_Exception, "(share) glXGetCurrentDrawable failed");
return NULL;
}
res->dpy = res->m_glXGetCurrentDisplay();
if (!res->dpy) {
PyErr_Format(PyExc_Exception, "(share) glXGetCurrentDisplay failed");
return NULL;
}
int nelements = 0;
res->fbc = res->m_glXChooseFBConfig(res->dpy, res->m_XDefaultScreen(res->dpy), 0, &nelements);
if (!res->fbc) {
res->m_XCloseDisplay(res->dpy);
PyErr_Format(PyExc_Exception, "(share) glXChooseFBConfig failed");
return NULL;
}
static int attribute_list[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
None,
};
res->vi = res->m_glXChooseVisual(res->dpy, res->m_XDefaultScreen(res->dpy), attribute_list);
if (!res->vi) {
res->m_XCloseDisplay(res->dpy);
PyErr_Format(PyExc_Exception, "(share) glXChooseVisual: cannot choose visual");
return NULL;
}
res->m_XSetErrorHandler(SilentXErrorHandler);
if (glversion) {
void (* proc)() = res->m_glXGetProcAddress((const unsigned char *)"glXCreateContextAttribsARB");
res->m_glXCreateContextAttribsARB = (m_glXCreateContextAttribsARBProc)proc;
if (!res->m_glXCreateContextAttribsARB) {
PyErr_Format(PyExc_Exception, "(share) glXCreateContextAttribsARB not found");
return NULL;
}
int attribs[] = {
GLX_CONTEXT_PROFILE_MASK, GLX_CONTEXT_CORE_PROFILE_BIT,
GLX_CONTEXT_MAJOR_VERSION, glversion / 100 % 10,
GLX_CONTEXT_MINOR_VERSION, glversion / 10 % 10,
0, 0,
};
res->ctx = res->m_glXCreateContextAttribsARB(res->dpy, *res->fbc, ctx_share, true, attribs);
} else {
res->ctx = res->m_glXCreateContext(res->dpy, res->vi, ctx_share, true);
}
if (!res->ctx) {
PyErr_Format(PyExc_Exception, "(share) cannot create context");
return NULL;
}
res->m_XSetErrorHandler(NULL);
if (!res->m_glXMakeCurrent(res->dpy, res->wnd, res->ctx)) {
PyErr_Format(PyExc_Exception, "(share) glXMakeCurrent failed");
return NULL;
}
return res;
}
if (!strcmp(mode, "standalone")) {
res->standalone = true;
res->own_window = true;
res->dpy = res->m_XOpenDisplay(NULL);
if (!res->dpy) {
res->dpy = res->m_XOpenDisplay(":0.0");
}
if (!res->dpy) {
PyErr_Format(PyExc_Exception, "(standalone) XOpenDisplay: cannot open display");
return NULL;
}
int nelements = 0;
res->fbc = res->m_glXChooseFBConfig(res->dpy, res->m_XDefaultScreen(res->dpy), 0, &nelements);
if (!res->fbc) {
res->m_XCloseDisplay(res->dpy);
PyErr_Format(PyExc_Exception, "(standalone) glXChooseFBConfig failed");
return NULL;
}
static int attribute_list[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_DEPTH_SIZE, 24,
None,
};
res->vi = res->m_glXChooseVisual(res->dpy, res->m_XDefaultScreen(res->dpy), attribute_list);
if (!res->vi) {
res->m_XCloseDisplay(res->dpy);
PyErr_Format(PyExc_Exception, "(standalone) glXChooseVisual: cannot choose visual");
return NULL;
}
XSetWindowAttributes swa;
swa.colormap = res->m_XCreateColormap(res->dpy, res->m_XRootWindow(res->dpy, res->vi->screen), res->vi->visual, AllocNone);
swa.border_pixel = 0;
swa.event_mask = StructureNotifyMask;
res->wnd = res->m_XCreateWindow(
res->dpy, res->m_XRootWindow(res->dpy, res->vi->screen), 0, 0, 1, 1, 0, res->vi->depth, InputOutput,
res->vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa
);
if (!res->wnd) {
res->m_XCloseDisplay(res->dpy);
PyErr_Format(PyExc_Exception, "(standalone) XCreateWindow: cannot create window");
return NULL;
}
res->m_XSetErrorHandler(SilentXErrorHandler);
if (glversion) {
void (* proc)() = res->m_glXGetProcAddress((const unsigned char *)"glXCreateContextAttribsARB");
res->m_glXCreateContextAttribsARB = (m_glXCreateContextAttribsARBProc)proc;
if (!res->m_glXCreateContextAttribsARB) {
PyErr_Format(PyExc_Exception, "(standalone) glXCreateContextAttribsARB not found");
return NULL;
}
int attribs[] = {
GLX_CONTEXT_PROFILE_MASK, GLX_CONTEXT_CORE_PROFILE_BIT,
GLX_CONTEXT_MAJOR_VERSION, glversion / 100 % 10,
GLX_CONTEXT_MINOR_VERSION, glversion / 10 % 10,
0, 0,
};
res->ctx = res->m_glXCreateContextAttribsARB(res->dpy, *res->fbc, NULL, true, attribs);
} else {
res->ctx = res->m_glXCreateContext(res->dpy, res->vi, NULL, true);
}
if (!res->ctx) {
PyErr_Format(PyExc_Exception, "(standalone) cannot create context");
return NULL;
}
res->m_XSetErrorHandler(NULL);
if (!res->m_glXMakeCurrent(res->dpy, res->wnd, res->ctx)) {
PyErr_Format(PyExc_Exception, "(standalone) glXMakeCurrent failed");
return NULL;
}
return res;
}
PyErr_Format(PyExc_Exception, "unknown mode");
return NULL;
}
PyObject * GLContext_meth_load(GLContext * self, PyObject * arg) {
const char * method = PyUnicode_AsUTF8(arg);
void * proc = (void *)dlsym(self->libgl, method);
if (!proc) {
proc = (void *)self->m_glXGetProcAddress((const unsigned char *)method);
}
return PyLong_FromVoidPtr(proc);
}
PyObject * GLContext_meth_enter(GLContext * self) {
self->old_display = (void *)self->m_glXGetCurrentDisplay();
self->old_window = (void *)self->m_glXGetCurrentDrawable();
self->old_context = (void *)self->m_glXGetCurrentContext();
self->m_glXMakeCurrent(self->dpy, self->wnd, self->ctx);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_exit(GLContext * self) {
self->m_glXMakeCurrent((Display *)self->old_display, (Window)self->old_window, (GLXContext)self->old_context);
Py_RETURN_NONE;
}
PyObject * GLContext_meth_release(GLContext * self) {
if (self->standalone) {
self->m_glXMakeCurrent(self->dpy, None, NULL);
self->m_glXDestroyContext(self->dpy, self->ctx);
}
if (self->own_window) {
self->m_XDestroyWindow(self->dpy, self->wnd);
self->m_XCloseDisplay(self->dpy);
}
if (self->fbc) {
self->m_XFree(self->fbc);
self->fbc = NULL;
}
if (self->vi) {
self->m_XFree(self->vi);
self->vi = NULL;
}
Py_RETURN_NONE;
}
void GLContext_dealloc(GLContext * self) {
Py_TYPE(self)->tp_free(self);
}
PyMethodDef GLContext_methods[] = {
{"load", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"load_opengl_function", (PyCFunction)GLContext_meth_load, METH_O, NULL},
{"release", (PyCFunction)GLContext_meth_release, METH_NOARGS, NULL},
{"__enter__", (PyCFunction)GLContext_meth_enter, METH_NOARGS, NULL},
{"__exit__", (PyCFunction)GLContext_meth_exit, METH_VARARGS, NULL},
{},
};
PyMemberDef GLContext_members[] = {
{"standalone", T_BOOL, offsetof(GLContext, standalone), READONLY, NULL},
{},
};
PyType_Slot GLContext_slots[] = {
{Py_tp_methods, GLContext_methods},
{Py_tp_members, GLContext_members},
{Py_tp_dealloc, (void *)GLContext_dealloc},
{},
};
PyType_Spec GLContext_spec = {"x11.GLContext", sizeof(GLContext), 0, Py_TPFLAGS_DEFAULT, GLContext_slots};
PyMethodDef module_methods[] = {
{"create_context", (PyCFunction)meth_create_context, METH_VARARGS | METH_KEYWORDS, NULL},
{},
};
PyModuleDef module_def = {PyModuleDef_HEAD_INIT, "x11", NULL, -1, module_methods};
extern "C" PyObject * PyInit_x11() {
PyObject * module = PyModule_Create(&module_def);
GLContext_type = (PyTypeObject *)PyType_FromSpec(&GLContext_spec);
PyModule_AddObject(module, "GLContext", (PyObject *)GLContext_type);
return module;
}
moderngl-glcontext-1573e57/pyproject.toml 0000664 0000000 0000000 00000000171 14512447336 0020534 0 ustar 00root root 0000000 0000000 [build-system]
requires = [
"setuptools >= 40.6.2",
"wheel >= 0.30.0",
]
build-backend = "setuptools.build_meta"
moderngl-glcontext-1573e57/setup.py 0000664 0000000 0000000 00000006255 14512447336 0017343 0 ustar 00root root 0000000 0000000 import platform
import sys
from setuptools import Extension, setup
PLATFORMS = {'windows', 'linux', 'darwin'}
target = platform.system().lower()
for known in PLATFORMS:
if target.startswith(known):
target = known
if target not in PLATFORMS:
target = 'linux'
if target == 'darwin':
import os
if sys.version_info[:2] < (3, 12):
from distutils.sysconfig import get_config_var
from distutils.version import LooseVersion
if 'MACOSX_DEPLOYMENT_TARGET' not in os.environ:
current_system = LooseVersion(platform.mac_ver()[0])
python_target = LooseVersion(get_config_var('MACOSX_DEPLOYMENT_TARGET'))
if python_target < '10.9' and current_system >= '10.9':
os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.9'
wgl = Extension(
name='glcontext.wgl',
sources=['glcontext/wgl.cpp'],
extra_compile_args=['-fpermissive'] if 'GCC' in sys.version else [],
libraries=['user32', 'gdi32'],
)
x11 = Extension(
name='glcontext.x11',
sources=['glcontext/x11.cpp'],
extra_compile_args=['-fpermissive'],
libraries=['dl'],
)
egl = Extension(
name='glcontext.egl',
sources=['glcontext/egl.cpp'],
extra_compile_args=['-fpermissive'],
libraries=['dl'],
)
headless = Extension(
name='glcontext.headless',
sources=['glcontext/headless.cpp'],
libraries=['EGL'],
)
if target == 'windows':
windowed = Extension(
name='glcontext.windowed',
sources=['glcontext/windowed.cpp'],
libraries=['opengl32'],
)
if target == 'linux':
windowed = Extension(
name='glcontext.windowed',
sources=['glcontext/windowed.cpp'],
extra_compile_args=['-fpermissive'],
libraries=['GL'],
)
if target == 'darwin':
windowed = Extension(
name='glcontext.windowed',
sources=['glcontext/windowed.cpp'],
extra_compile_args=['-fpermissive', '-Wno-deprecated-declarations'],
extra_link_args=['-framework', 'OpenGL', '-Wno-deprecated'],
)
darwin = Extension(
name='glcontext.darwin',
sources=['glcontext/darwin.cpp'],
extra_compile_args=['-fpermissive', '-Wno-deprecated-declarations'],
extra_link_args=['-framework', 'OpenGL', '-Wno-deprecated'],
)
ext_modules = {
'windows': [wgl],
'linux': [x11, egl],
'darwin': [darwin],
}
setup(
name='glcontext',
version='2.5.0',
description='Portable OpenGL Context',
long_description=open('README.md', encoding='utf-8').read(),
long_description_content_type='text/markdown',
url='https://github.com/moderngl/glcontext',
author='Szabolcs Dombi',
author_email='cprogrammer1994@gmail.com',
license='MIT',
platforms=['any'],
packages=['glcontext'],
ext_modules=ext_modules[target],
classifiers=[
'Development Status :: 5 - Production/Stable',
'License :: OSI Approved :: MIT License',
'Operating System :: OS Independent',
'Topic :: Games/Entertainment',
'Topic :: Multimedia :: Graphics',
'Topic :: Multimedia :: Graphics :: 3D Rendering',
'Topic :: Scientific/Engineering :: Visualization',
'Programming Language :: Python :: 3 :: Only',
],
)
moderngl-glcontext-1573e57/test.py 0000664 0000000 0000000 00000000745 14512447336 0017160 0 ustar 00root root 0000000 0000000 import ctypes
from glcontext import headless
devices = headless.devices()
headless.init(device=next(x['device'] for x in devices if 'EGL_MESA_device_software' in x['extensions']))
glGetStringPtr = headless.load_opengl_function('glGetString')
glGetString = ctypes.cast(glGetStringPtr, ctypes.CFUNCTYPE(ctypes.c_char_p, ctypes.c_uint32))
print(glGetString(0x1F00).decode())
print(glGetString(0x1F01).decode())
print(glGetString(0x1F02).decode())
print(glGetString(0x1F03).decode())
moderngl-glcontext-1573e57/tests/ 0000775 0000000 0000000 00000000000 14512447336 0016763 5 ustar 00root root 0000000 0000000 moderngl-glcontext-1573e57/tests/default_context_test.py 0000664 0000000 0000000 00000003577 14512447336 0023600 0 ustar 00root root 0000000 0000000 import os
from unittest import TestCase
import psutil
import glcontext
class ContextTestCase(TestCase):
def test_create(self):
"""Basic context testing"""
# Create a standalone context
# os.environ['GLCONTEXT_WIN_LIBGL'] = 'moo.dll'
# os.environ['GLCONTEXT_LINUX_LIBGL'] = 'ligGL.so.1'
# os.environ['GLCONTEXT_GLVERSION'] = '430'
backend = glcontext.default_backend()
ctx = backend(mode='standalone', glversion=330)
# Ensure methods are present
self.assertTrue(callable(ctx.load))
self.assertTrue(callable(ctx.release))
self.assertTrue(callable(ctx.__enter__))
self.assertTrue(callable(ctx.__exit__))
# Enter and exit context
with ctx:
pass
# Ensure method loading works
ptr = ctx.load('glEnable')
self.assertIsInstance(ptr, int)
self.assertGreater(ptr, 0)
# Load non-existent gl method
# NOTE: Disabled for now since x11 returns positive values
# for non-existent methods
# ptr = ctx.load('bogus')
# self.assertIsInstance(ptr, int)
# self.assertEqual(ptr, 0)
def test_mass_create(self):
"""Create and destroy a large quantity of contexts.
The rss memory usage should not grow more than 5x
after allocating 1000 contexts.
"""
process = psutil.Process(os.getpid())
start_rss = process.memory_info().rss
for i in range(1000):
ctx = glcontext.default_backend()(mode='standalone', glversion=330)
# Ensure we can enter context and load a method as a minimum
with ctx:
self.assertGreater(ctx.load('glBegin'), 0)
ctx.release()
end_rss = process.memory_info().rss
self.assertTrue(end_rss / start_rss < 5.0)
moderngl-glcontext-1573e57/tests/requirements.txt 0000664 0000000 0000000 00000000020 14512447336 0022237 0 ustar 00root root 0000000 0000000 pytest
psutil