text: """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
          print("P3", file=f)
          print("# ascii ppm file created by pyopengl", file=f)
          print("%i %i" % (w, h), file=f)
          print("255", file=f)
          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])
  