| """Debug utilities for EGL operations""" | |
| from OpenGL.EGL import * | |
| import itertools | |
| def eglErrorName(value): | |
| """Returns error constant if known, otherwise returns value""" | |
| return KNOWN_ERRORS.get(value, value) | |
| KNOWN_ERRORS = { | |
| EGL_SUCCESS: EGL_SUCCESS, | |
| EGL_NOT_INITIALIZED: EGL_NOT_INITIALIZED, | |
| EGL_BAD_ACCESS: EGL_BAD_ACCESS, | |
| EGL_BAD_ALLOC: EGL_BAD_ALLOC, | |
| EGL_BAD_ATTRIBUTE: EGL_BAD_ATTRIBUTE, | |
| EGL_BAD_CONTEXT: EGL_BAD_CONTEXT, | |
| EGL_BAD_CONFIG: EGL_BAD_CONFIG, | |
| EGL_BAD_CURRENT_SURFACE: EGL_BAD_CURRENT_SURFACE, | |
| EGL_BAD_DISPLAY: EGL_BAD_DISPLAY, | |
| EGL_BAD_SURFACE: EGL_BAD_SURFACE, | |
| EGL_BAD_MATCH: EGL_BAD_MATCH, | |
| EGL_BAD_PARAMETER: EGL_BAD_PARAMETER, | |
| EGL_BAD_NATIVE_PIXMAP: EGL_BAD_NATIVE_PIXMAP, | |
| EGL_BAD_NATIVE_WINDOW: EGL_BAD_NATIVE_WINDOW, | |
| EGL_CONTEXT_LOST: EGL_CONTEXT_LOST, | |
| } | |
| def write_ppm(buf, filename): | |
| """Write height * width * 3-component buffer as ppm to filename | |
| This lets us write a simple image format without | |
| using any libraries that can be viewed on most | |
| linux workstations. | |
| """ | |
| with open(filename, "w") as f: | |
| (h, w, c) = buf.shape | |
| f.write("P3\n") | |
| f.write("# ascii ppm file created by pyopengl\n") | |
| f.write("%i %i\n" % (w, h)) | |
| f.write("255\n") | |
| for y in range(h - 1, -1, -1): | |
| for x in range(w): | |
| pixel = buf[y, x] | |
| l = " %3d %3d %3d" % (pixel[0], pixel[1], pixel[2]) | |
| f.write(l) | |
| f.write("\n") | |
| def debug_config(display, config): | |
| """Get debug display for the given configuration""" | |
| result = {} | |
| value = EGLint() | |
| for attr in CONFIG_ATTRS: | |
| if not eglGetConfigAttrib(display, config, attr, value): | |
| log.warning("Failed to get attribute %s from config", attr) | |
| continue | |
| if attr in BITMASK_FIELDS: | |
| attr_value = {} | |
| for subattr in BITMASK_FIELDS[attr]: | |
| if value.value & subattr: | |
| attr_value[subattr.name] = True | |
| else: | |
| attr_value = value.value | |
| result[attr.name] = attr_value | |
| return result | |
| def debug_configs(display, configs=None, max_count=256): | |
| """Present a formatted list of configs for the display""" | |
| if configs is None: | |
| configs = (EGLConfig * max_count)() | |
| num_configs = EGLint() | |
| eglGetConfigs(display, configs, max_count, num_configs) | |
| if not num_configs.value: | |
| return [] | |
| configs = configs[: num_configs.value] | |
| debug_configs = [debug_config(display, cfg) for cfg in configs] | |
| return debug_configs | |
| SURFACE_TYPE_BITS = [ | |
| EGL_MULTISAMPLE_RESOLVE_BOX_BIT, | |
| EGL_PBUFFER_BIT, | |
| EGL_PIXMAP_BIT, | |
| EGL_SWAP_BEHAVIOR_PRESERVED_BIT, | |
| EGL_VG_ALPHA_FORMAT_PRE_BIT, | |
| EGL_VG_COLORSPACE_LINEAR_BIT, | |
| EGL_WINDOW_BIT, | |
| ] | |
| RENDERABLE_TYPE_BITS = [ | |
| EGL_OPENGL_BIT, | |
| EGL_OPENGL_ES_BIT, | |
| EGL_OPENGL_ES2_BIT, | |
| EGL_OPENGL_ES3_BIT, | |
| EGL_OPENVG_BIT, | |
| ] | |
| CAVEAT_BITS = [ | |
| EGL_NONE, | |
| EGL_SLOW_CONFIG, | |
| EGL_NON_CONFORMANT_CONFIG, | |
| ] | |
| TRANSPARENT_BITS = [ | |
| EGL_NONE, | |
| EGL_TRANSPARENT_RGB, | |
| ] | |
| CONFIG_ATTRS = [ | |
| EGL_CONFIG_ID, | |
| EGL_RED_SIZE, | |
| EGL_GREEN_SIZE, | |
| EGL_BLUE_SIZE, | |
| EGL_DEPTH_SIZE, | |
| EGL_ALPHA_SIZE, | |
| EGL_ALPHA_MASK_SIZE, | |
| EGL_BUFFER_SIZE, | |
| EGL_STENCIL_SIZE, | |
| EGL_BIND_TO_TEXTURE_RGB, | |
| EGL_BIND_TO_TEXTURE_RGBA, | |
| EGL_COLOR_BUFFER_TYPE, | |
| EGL_CONFIG_CAVEAT, | |
| EGL_CONFORMANT, | |
| EGL_LEVEL, | |
| EGL_LUMINANCE_SIZE, | |
| EGL_MAX_PBUFFER_WIDTH, | |
| EGL_MAX_PBUFFER_HEIGHT, | |
| EGL_MAX_PBUFFER_PIXELS, | |
| EGL_MIN_SWAP_INTERVAL, | |
| EGL_MAX_SWAP_INTERVAL, | |
| EGL_NATIVE_RENDERABLE, | |
| EGL_NATIVE_VISUAL_ID, | |
| EGL_NATIVE_VISUAL_TYPE, | |
| EGL_RENDERABLE_TYPE, | |
| EGL_SAMPLE_BUFFERS, | |
| EGL_SAMPLES, | |
| EGL_SURFACE_TYPE, | |
| EGL_TRANSPARENT_TYPE, | |
| EGL_TRANSPARENT_RED_VALUE, | |
| EGL_TRANSPARENT_GREEN_VALUE, | |
| EGL_TRANSPARENT_BLUE_VALUE, | |
| ] | |
| BITMASK_FIELDS = dict( | |
| [ | |
| (EGL_SURFACE_TYPE, SURFACE_TYPE_BITS), | |
| (EGL_RENDERABLE_TYPE, RENDERABLE_TYPE_BITS), | |
| (EGL_CONFORMANT, RENDERABLE_TYPE_BITS), | |
| (EGL_CONFIG_CAVEAT, CAVEAT_BITS), | |
| (EGL_TRANSPARENT_TYPE, TRANSPARENT_BITS), | |
| ] | |
| ) | |
| def bit_renderer(bit): | |
| def render(value): | |
| if bit.name in value: | |
| return " Y" | |
| else: | |
| return " ." | |
| return render | |
| CONFIG_FORMAT = [ | |
| (EGL_CONFIG_ID, "0x%x", "id", "cfg"), | |
| (EGL_BUFFER_SIZE, "%i", "sz", "bf"), | |
| (EGL_LEVEL, "%i", "l", "lv"), | |
| (EGL_RED_SIZE, "%i", "r", "cbuf"), | |
| (EGL_GREEN_SIZE, "%i", "g", "cbuf"), | |
| (EGL_BLUE_SIZE, "%i", "b", "cbuf"), | |
| (EGL_ALPHA_SIZE, "%i", "a", "cbuf"), | |
| (EGL_DEPTH_SIZE, "%i", "th", "dp"), | |
| (EGL_STENCIL_SIZE, "%i", "t", "s"), | |
| (EGL_SAMPLES, "%i", "ns", "mult"), | |
| (EGL_SAMPLE_BUFFERS, "%i", "bu", "mult"), | |
| (EGL_NATIVE_VISUAL_ID, "0x%x", "id", "visual"), | |
| (EGL_RENDERABLE_TYPE, bit_renderer(EGL_OPENGL_BIT), "gl", "render"), | |
| (EGL_RENDERABLE_TYPE, bit_renderer(EGL_OPENGL_ES_BIT), "es", "render"), | |
| (EGL_RENDERABLE_TYPE, bit_renderer(EGL_OPENGL_ES2_BIT), "e2", "render"), | |
| (EGL_RENDERABLE_TYPE, bit_renderer(EGL_OPENGL_ES3_BIT), "e3", "render"), | |
| (EGL_RENDERABLE_TYPE, bit_renderer(EGL_OPENVG_BIT), "vg", "render"), | |
| (EGL_SURFACE_TYPE, bit_renderer(EGL_WINDOW_BIT), "wn", "surface"), | |
| (EGL_SURFACE_TYPE, bit_renderer(EGL_PBUFFER_BIT), "pb", "surface"), | |
| (EGL_SURFACE_TYPE, bit_renderer(EGL_PIXMAP_BIT), "px", "surface"), | |
| ] | |
| def format_debug_configs(debug_configs, formats=CONFIG_FORMAT): | |
| """Format config for compact debugging display | |
| Produces a config summary display for a set of | |
| debug_configs as a text-mode table. | |
| Uses `formats` (default `CONFIG_FORMAT`) to determine | |
| which fields are extracted and how they are formatted | |
| along with the column/subcolum set to be rendered in | |
| the overall header. | |
| returns formatted ASCII table for display in debug | |
| logs or utilities | |
| """ | |
| columns = [] | |
| for (key, format, subcol, col) in formats: | |
| column = [] | |
| max_width = 0 | |
| for row in debug_configs: | |
| if isinstance(row, EGLConfig): | |
| raise TypeError(row, "Call debug_config(display,config)") | |
| try: | |
| value = row[key.name] | |
| except KeyError: | |
| formatted = "_" | |
| else: | |
| if isinstance(format, str): | |
| formatted = format % (value) | |
| else: | |
| formatted = format(value) | |
| max_width = max((len(formatted), max_width)) | |
| column.append(formatted) | |
| columns.append( | |
| { | |
| "rows": column, | |
| "key": key, | |
| "format": format, | |
| "subcol": subcol, | |
| "col": col, | |
| "width": max_width, | |
| } | |
| ) | |
| headers = [] | |
| subheaders = [] | |
| rows = [headers, subheaders] | |
| last_column = None | |
| last_column_width = 0 | |
| for header, subcols in itertools.groupby(columns, lambda x: x["col"]): | |
| subcols = list(subcols) | |
| width = sum([col["width"] for col in subcols]) + (len(subcols) - 1) | |
| headers.append(header.center(width, ".")[:width]) | |
| for column in columns: | |
| subheaders.append(column["subcol"].rjust(column["width"])[: column["width"]]) | |
| rows.extend( | |
| zip(*[[v.rjust(col["width"], " ") for v in col["rows"]] for col in columns]) | |
| ) | |
| return "\n".join([" ".join(row) for row in rows]) | |