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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
|
from __future__ import print_function
import os, logging, pprint
log = logging.getLogger(__name__)
if not os.environ.get("PYOPENGL_PLATFORM"):
os.environ["PYOPENGL_PLATFORM"] = "egl"
if "DISPLAY" in os.environ:
del os.environ["DISPLAY"]
import logging, contextlib
from functools import wraps
# from OpenGL.GL import *
from OpenGL.EGL import *
from OpenGL.EGL import debug
from OpenGL import arrays
from OpenGL.EGL import gbmdevice
from OpenGL.EGL.MESA import platform_gbm
from OpenGL.EGL.EXT import platform_device, platform_base, device_base
API_MAP = {
EGL_OPENGL_BIT: EGL_OPENGL_API,
EGL_OPENGL_ES2_BIT: EGL_OPENGL_ES_API,
EGL_OPENGL_ES_BIT: EGL_OPENGL_ES_API,
}
def platformDisplay(device):
"""Get platform display from device specifier
device -- EGLDeviceEXT, gbm card* path, or gbm card* ordinal (index)
returns display, created_device (or None if passed in)
raises RuntimeError if we can't create the display
"""
created_device = display = None
if isinstance(device, (str, int)):
created_device = device = gbmdevice.open_device(device)
if eglGetPlatformDisplay:
display = eglGetPlatformDisplay(
platform_device.EGL_PLATFORM_DEVICE_EXT
if isinstance(device, EGLDeviceEXT)
else platform_gbm.EGL_PLATFORM_GBM_MESA,
device,
ctypes.c_void_p(0),
)
if display == EGL_NO_DISPLAY:
raise RuntimeError("Unable to create EGL display on %s" % (display))
else:
raise RuntimeError("eglGetPlatformDisplay has no implementation")
if not created_device:
try:
name = get_device_name(device)
if name is not None:
log.debug("DRM Name: %s", name)
except EGLError:
log.debug("Unable to retrieve the DRM name")
return display, created_device
def gbmPlatformSurface(display, config, platform_device, width, height):
"""Create a GBM platform surface for display with config on platform_device
returns egl_surface, gbm_surface
"""
visual = EGLint()
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, visual)
platform_surface = gbmdevice.create_surface(
platform_device,
width,
height,
format=visual.value,
flags=gbmdevice.GBM_BO_USE_RENDERING,
)
if not platform_surface:
raise RuntimeError("Unable to allocate a gbm surface")
surface = eglCreatePlatformWindowSurface(display, config, platform_surface, None)
if surface == EGL_NO_SURFACE:
log.error("Failed to create the EGL surface on the GBM surface")
raise RuntimeError("Platform window surface creation failure")
return surface, platform_surface
def choose_config(display, attributes):
"""utility to choose config for the display based on attributes"""
num_configs = EGLint()
configs = (EGLConfig * 1)()
local_attributes = arrays.GLintArray.asArray(attributes)
success = eglChooseConfig(display, local_attributes, configs, 1, num_configs)
if not success:
raise NoConfig("Unable to complete config filtering", attributes)
if not num_configs:
raise NoConfig(
"No compatible configs found", attributes,
)
return configs[0]
@contextlib.contextmanager
def egl_context(
width=256,
height=256,
api=EGL_OPENGL_BIT,
attributes=(
EGL_BLUE_SIZE,
8,
EGL_RED_SIZE,
8,
EGL_GREEN_SIZE,
8,
EGL_DEPTH_SIZE,
24,
EGL_COLOR_BUFFER_TYPE,
EGL_RGB_BUFFER,
# EGL_CONFIG_CAVEAT, EGL_NONE, # Don't allow slow/non-conformant
),
pbuffer=False,
device=None,
output="output.ppm",
):
"""Setup a context for rendering"""
major, minor = EGLint(), EGLint()
created_device = platform_surface = surface = None
if device is None:
display = eglGetDisplay(EGL_DEFAULT_DISPLAY)
if display == EGL_NO_DISPLAY:
raise RuntimeError(EGL_NO_DISPLAY, "Could not create default display")
else:
display, created_device = platformDisplay(device)
try:
# print("Display: %s"%(display.address,))
try:
eglInitialize(display, major, minor)
except EGLError as err:
log.warning("eglInitilise failure on %s: %s", display, err.err)
raise NoEGLSupport(display)
log.debug(
"Available configs:\n%s",
debug.format_debug_configs(debug.debug_configs(display)),
)
# for config in configs[:num_configs.value]:
# log.debug("Config: %s",pprint.pformat(debug.debug_config(display,config)))
local_attributes = list(attributes[:])
if pbuffer:
local_attributes.extend(
[EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,]
)
else:
local_attributes.extend(
[EGL_SURFACE_TYPE, EGL_WINDOW_BIT,]
)
local_attributes.extend(
[EGL_CONFORMANT, api, EGL_NONE,] # end of list
)
config = choose_config(display, local_attributes,)
log.debug(
"Selected config:\n%s",
debug.format_debug_configs(debug.debug_configs(display, configs=[config])),
)
surface_attributes = [
EGL_WIDTH,
width,
EGL_HEIGHT,
height,
EGL_NONE,
]
if pbuffer:
surface = eglCreatePbufferSurface(display, config, surface_attributes,)
else:
surface, platform_surface = gbmPlatformSurface(
display, config, created_device, width, height
)
eglBindAPI(API_MAP[api])
ctx = eglCreateContext(display, config, EGL_NO_CONTEXT, None)
if ctx == EGL_NO_CONTEXT:
raise RuntimeError("Unable to create context")
eglMakeCurrent(display, surface, surface, ctx)
yield display, ctx, surface
if output:
log.debug("Doing readpixels for writing buffer")
from OpenGL import arrays
content = arrays.GLubyteArray.zeros((width, height, 3))
if api == EGL_OPENGL_BIT:
from OpenGL.GL import glReadPixels, GL_UNSIGNED_BYTE, GL_RGB
elif api == EGL_OPENGL_ES3_BIT:
from OpenGL.GLES3 import glReadPixels, GL_UNSIGNED_BYTE, GL_RGB
elif api == EGL_OPENGL_ES2_BIT:
from OpenGL.GLES2 import glReadPixels, GL_UNSIGNED_BYTE, GL_RGB
elif api == EGL_OPENGL_ES_BIT:
from OpenGL.GLES1 import glReadPixels, GL_UNSIGNED_BYTE, GL_RGB
content = glReadPixels(
0, 0, width, height, GL_RGB, type=GL_UNSIGNED_BYTE, array=content
)
debug.write_ppm(content, output)
# glFinish()
finally:
if display:
eglMakeCurrent(display, None, None, None)
if surface:
eglDestroySurface(display, surface)
eglTerminate(display)
if platform_surface:
gbmdevice.gbm.gbm_surface_destroy(platform_surface)
if created_device:
gbmdevice.close_device(created_device)
class NoEGLSupport(Exception):
"""Raised if we could not initialise an egl context"""
class NoConfig(Exception):
"""Raised if we did not find any configs"""
def debug_info(setup):
from OpenGL.GL import (
glClearColor,
glClear,
GL_COLOR_BUFFER_BIT,
GL_DEPTH_BUFFER_BIT,
glGetString,
GL_VENDOR,
GL_EXTENSIONS,
glFinish,
)
display, ctx, surface = setup
glClearColor(1.0, 1.0, 1.0, 1.0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
log.info("Vendor: %s", glGetString(GL_VENDOR))
log.info("Extensions: %s", glGetString(GL_EXTENSIONS))
glFinish()
def get_device_name(device):
"""Try to get the display's DRM device name
This is almost certainly not going to work on
anything other than Linux
"""
from OpenGL.EGL.EXT.device_query import (
eglQueryDeviceStringEXT,
)
from OpenGL.EGL.EXT.device_drm import (
EGL_DRM_DEVICE_FILE_EXT,
)
if eglQueryDeviceStringEXT:
name = eglQueryDeviceStringEXT(
device,
EGL_DRM_DEVICE_FILE_EXT
)
return name.decode('ascii',errors='ignore')
return None
def main():
# NOTE: having two different implementations here is
# likely somewhat broken due to the
# OpenGL functions having retrieved their
# function pointers during the first pass and then
# trying to run them against the second
for device in sorted(device_base.egl_get_devices(), key=lambda x: x.address):
log.info("Starting tests with: %s", device)
try:
with egl_context(device=device, pbuffer=True) as setup:
debug_info(setup)
except (NoEGLSupport, NoConfig) as err:
log.info("Cannot configure: %s", err)
except (EGLError, RuntimeError):
log.exception("Failed during: %s", device)
for device in gbmdevice.enumerate_devices():
log.info("Starting tests with: %s", device)
try:
with egl_context(device=device, pbuffer=False) as setup:
debug_info(setup)
except (NoEGLSupport, NoConfig) as err:
log.info("Cannot configure: %s", err)
except (EGLError, RuntimeError):
log.exception("Failed during: %s", device)
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
main()
|