Spaces:
Paused
Paused
Suprhimp
commited on
Commit
·
a23ea39
1
Parent(s):
7e9e319
update
Browse files- lib/glcontext.py +142 -0
- opengl.py +2 -1
- requirements.txt +1 -2
lib/glcontext.py
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""Headless GPU-accelerated OpenGL context creation on Google Colaboratory.
|
2 |
+
|
3 |
+
Typical usage:
|
4 |
+
|
5 |
+
# Optional PyOpenGL configuratiopn can be done here.
|
6 |
+
# import OpenGL
|
7 |
+
# OpenGL.ERROR_CHECKING = True
|
8 |
+
|
9 |
+
# 'glcontext' must be imported before any OpenGL.* API.
|
10 |
+
from lucid.misc.gl.glcontext import create_opengl_context
|
11 |
+
|
12 |
+
# Now it's safe to import OpenGL and EGL functions
|
13 |
+
import OpenGL.GL as gl
|
14 |
+
|
15 |
+
# create_opengl_context() creates a GL context that is attached to an
|
16 |
+
# offscreen surface of the specified size. Note that rendering to buffers
|
17 |
+
# of other sizes and formats is still possible with OpenGL Framebuffers.
|
18 |
+
#
|
19 |
+
# Users are expected to directly use the EGL API in case more advanced
|
20 |
+
# context management is required.
|
21 |
+
width, height = 640, 480
|
22 |
+
create_opengl_context((width, height))
|
23 |
+
|
24 |
+
# OpenGL context is available here.
|
25 |
+
|
26 |
+
"""
|
27 |
+
|
28 |
+
from __future__ import print_function
|
29 |
+
|
30 |
+
# pylint: disable=unused-import,g-import-not-at-top,g-statement-before-imports
|
31 |
+
|
32 |
+
try:
|
33 |
+
import OpenGL
|
34 |
+
except:
|
35 |
+
print('This module depends on PyOpenGL.')
|
36 |
+
print('Please run "\033[1m!pip install -q pyopengl\033[0m" '
|
37 |
+
'prior importing this module.')
|
38 |
+
raise
|
39 |
+
|
40 |
+
import ctypes
|
41 |
+
from ctypes import pointer, util
|
42 |
+
import os
|
43 |
+
|
44 |
+
os.environ['PYOPENGL_PLATFORM'] = 'egl'
|
45 |
+
|
46 |
+
# OpenGL loading workaround.
|
47 |
+
#
|
48 |
+
# * PyOpenGL tries to load libGL, but we need libOpenGL, see [1,2].
|
49 |
+
# This could have been solved by a symlink libGL->libOpenGL, but:
|
50 |
+
#
|
51 |
+
# * Python 2.7 can't find libGL and linEGL due to a bug (see [3])
|
52 |
+
# in ctypes.util, that was only wixed in Python 3.6.
|
53 |
+
#
|
54 |
+
# So, the only solution I've found is to monkeypatch ctypes.util
|
55 |
+
# [1] https://devblogs.nvidia.com/egl-eye-opengl-visualization-without-x-server/
|
56 |
+
# [2] https://devblogs.nvidia.com/linking-opengl-server-side-rendering/
|
57 |
+
# [3] https://bugs.python.org/issue9998
|
58 |
+
_find_library_old = ctypes.util.find_library
|
59 |
+
try:
|
60 |
+
|
61 |
+
def _find_library_new(name):
|
62 |
+
return {
|
63 |
+
'GL': 'libOpenGL.so',
|
64 |
+
'EGL': 'libEGL.so',
|
65 |
+
}.get(name, _find_library_old(name))
|
66 |
+
util.find_library = _find_library_new
|
67 |
+
import OpenGL.GL as gl
|
68 |
+
import OpenGL.EGL as egl
|
69 |
+
from OpenGL import error
|
70 |
+
from OpenGL.EGL.EXT.device_base import egl_get_devices
|
71 |
+
from OpenGL.raw.EGL.EXT.platform_device import EGL_PLATFORM_DEVICE_EXT
|
72 |
+
except:
|
73 |
+
print('Unable to load OpenGL libraries. '
|
74 |
+
'Make sure you use GPU-enabled backend.')
|
75 |
+
print('Press "Runtime->Change runtime type" and set '
|
76 |
+
'"Hardware accelerator" to GPU.')
|
77 |
+
raise
|
78 |
+
finally:
|
79 |
+
util.find_library = _find_library_old
|
80 |
+
|
81 |
+
def create_initialized_headless_egl_display():
|
82 |
+
"""Creates an initialized EGL display directly on a device."""
|
83 |
+
for device in egl_get_devices():
|
84 |
+
display = egl.eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, device, None)
|
85 |
+
|
86 |
+
if display != egl.EGL_NO_DISPLAY and egl.eglGetError() == egl.EGL_SUCCESS:
|
87 |
+
# `eglInitialize` may or may not raise an exception on failure depending
|
88 |
+
# on how PyOpenGL is configured. We therefore catch a `GLError` and also
|
89 |
+
# manually check the output of `eglGetError()` here.
|
90 |
+
try:
|
91 |
+
initialized = egl.eglInitialize(display, None, None)
|
92 |
+
except error.GLError:
|
93 |
+
pass
|
94 |
+
else:
|
95 |
+
if initialized == egl.EGL_TRUE and egl.eglGetError() == egl.EGL_SUCCESS:
|
96 |
+
return display
|
97 |
+
return egl.EGL_NO_DISPLAY
|
98 |
+
|
99 |
+
def create_opengl_context(surface_size=(640, 480)):
|
100 |
+
"""Create offscreen OpenGL context and make it current.
|
101 |
+
|
102 |
+
Users are expected to directly use EGL API in case more advanced
|
103 |
+
context management is required.
|
104 |
+
|
105 |
+
Args:
|
106 |
+
surface_size: (width, height), size of the offscreen rendering surface.
|
107 |
+
"""
|
108 |
+
egl_display = create_initialized_headless_egl_display()
|
109 |
+
if egl_display == egl.EGL_NO_DISPLAY:
|
110 |
+
raise ImportError('Cannot initialize a headless EGL display.')
|
111 |
+
|
112 |
+
major, minor = egl.EGLint(), egl.EGLint()
|
113 |
+
egl.eglInitialize(egl_display, pointer(major), pointer(minor))
|
114 |
+
|
115 |
+
config_attribs = [
|
116 |
+
egl.EGL_SURFACE_TYPE, egl.EGL_PBUFFER_BIT, egl.EGL_BLUE_SIZE, 8,
|
117 |
+
egl.EGL_GREEN_SIZE, 8, egl.EGL_RED_SIZE, 8, egl.EGL_DEPTH_SIZE, 24,
|
118 |
+
egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_BIT, egl.EGL_NONE
|
119 |
+
]
|
120 |
+
config_attribs = (egl.EGLint * len(config_attribs))(*config_attribs)
|
121 |
+
|
122 |
+
num_configs = egl.EGLint()
|
123 |
+
egl_cfg = egl.EGLConfig()
|
124 |
+
egl.eglChooseConfig(egl_display, config_attribs, pointer(egl_cfg), 1,
|
125 |
+
pointer(num_configs))
|
126 |
+
|
127 |
+
width, height = surface_size
|
128 |
+
pbuffer_attribs = [
|
129 |
+
egl.EGL_WIDTH,
|
130 |
+
width,
|
131 |
+
egl.EGL_HEIGHT,
|
132 |
+
height,
|
133 |
+
egl.EGL_NONE,
|
134 |
+
]
|
135 |
+
pbuffer_attribs = (egl.EGLint * len(pbuffer_attribs))(*pbuffer_attribs)
|
136 |
+
egl_surf = egl.eglCreatePbufferSurface(egl_display, egl_cfg, pbuffer_attribs)
|
137 |
+
|
138 |
+
egl.eglBindAPI(egl.EGL_OPENGL_API)
|
139 |
+
|
140 |
+
egl_context = egl.eglCreateContext(egl_display, egl_cfg, egl.EGL_NO_CONTEXT,
|
141 |
+
None)
|
142 |
+
egl.eglMakeCurrent(egl_display, egl_surf, egl_surf, egl_context)
|
opengl.py
CHANGED
@@ -15,7 +15,8 @@
|
|
15 |
import OpenGL
|
16 |
import ctypes
|
17 |
import ctypes.util
|
18 |
-
from lucid.misc.gl.glcontext import create_opengl_context
|
|
|
19 |
|
20 |
from OpenGL.GL import *
|
21 |
import OpenGL.GL.shaders
|
|
|
15 |
import OpenGL
|
16 |
import ctypes
|
17 |
import ctypes.util
|
18 |
+
# from lucid.misc.gl.glcontext import create_opengl_context
|
19 |
+
from lib.glcontext import create_opengl_context
|
20 |
|
21 |
from OpenGL.GL import *
|
22 |
import OpenGL.GL.shaders
|
requirements.txt
CHANGED
@@ -5,5 +5,4 @@ uvicorn
|
|
5 |
pydantic
|
6 |
glfw
|
7 |
PyOpenGL==3.1.5
|
8 |
-
boto3
|
9 |
-
lucid==0.2.3
|
|
|
5 |
pydantic
|
6 |
glfw
|
7 |
PyOpenGL==3.1.5
|
8 |
+
boto3
|
|