X11::GLX::DWIM - Do What I Mean, with OpenGL on X11


version 0.06


  my $glx= X11::GLX::DWIM->new( \%options );
  while (1) {
  # defaults above:
  #   Connect to default X11 Display
  #   32-bit RGBA visual, double buffered
  #   rendering to full-screen window.  Direct-render if supported.
  #   begin_frame calls glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT)
  #   end_frame calls glXSwapBuffers and reports any glError


This module wraps all of the relevant X11::Xlib and X11::GLX function calls needed to create the most common types of rendering target for OpenGL.



Instance of X11::Xlib::Display. Lazy-built from $DISPLAY environment var, or connects to localhost.


Instance of X11::Xlib::Screen. Defaults to the default screen of the display.


The GLX version number. Read-only, lazy-built from "display".


The GLX version in major * 100 + minor binary-coded-decimal format. Useful for comparing version numbers without worrying about floating point rounding errors.


The list of extensions supported by this implementation of GLX. Read-only, lazy-built from "display".


  X11::GLX::DWIM->new( fbconfig => $fbconfig )
  X11::GLX::DWIM->new( fbconfig => \@glx_fbconfig_flags )

Lazy-built, read-only. Instance of X11::Xlib::FBConfig. Can be initialized with an arrayref of parameters (integer codes) to pass to glXChooseFBConfig.

Will be undef unless GLX version is 1.3 or higher, since FBConfig was not introduced until this version.


  X11::GLX::DWIM->new( visual_info => $vis )
  X11::GLX::DWIM->new( visual_info => \@glx_vis_flags )
  X11::GLX::DWIM->new( visual_info => \%visual_info_fields )

Lazy-built, read-only. Instance of X11::Xlib::XVisualInfo. Can be initialized with an arrayref of parameters (integer codes) to pass to glXChooseVisual, or with a hashref of fields to pass to the constructor of XVisualInfo.

If you have GLX 1.3 or higher, any initializer for this attribute will instead be converted to the appropriate glXChooseFBConfig arguments and the resulting visual_info will come from ->fbconfig->visual_info.


Lazy-built, read-only. Instance of X11::Xlib::Colormap. Defaults to a new colormap compatible with "visual_info".


An instance of X11::GLX::Context. You can also initialize it with a hash of arguments for the call to glXCreateContext or glXCreateNewContext. (the latter is used if GLX version is >= 1.3)

    direct => $bool,            # for direct rendering ("DRI")
    shared => $context_or_xid,  # X11::GLX::Context, or the X11 ID of an indirect context

If already initialized, this will destroy any previous context.

If your server supports it, and your context is indirect, you can discover the X11 ID for a GLX context with:

  my $xid= $glx->glx_context->id

and then use that ID for the shared option when creating later GL contexts in other processes. See "Shared GL Contexts" in X11::GLX.


Returns whether glx_context has been initialized.


Destroy the current GLX context, also clearing the "target".


Pixmap or Window which OpenGL should render to. (glXMakeCurrent). You can set this to an existing XID of a window or GLX pixmap, an object representing one (X11::Xlib::Window, etc), or a hashref specifying parameters to either "create_render_window" or "create_render_pixmap". If lazy-built with no initializer, it defaults to a full-screen window.

  $glx->target( $xid );                # existing window or GLX pixmap
  $glx->target({ window => \%args });  # shortcut for create_render_window()
  $glx->target({ pixmap => \%args });  # shortcut for create_render_pixmap()
  $glx->target;                        # defaults to full-screen window


Returns true if the target has been initialized. Use this to prevent triggering a lazy-build of the initial target.


Use this to un-set the target.


The bits passed to glClear in the convenience function "begin_frame".



If you're still rockin' the old-school OpenGL 1.4 matrix system, you can use this attribute to set up a quick projection matrix. If the GLX context target is initialized, setting this attribute will immediately change the GL projection matrix. Otherwise these settings are used as the default once that happens.

See "apply_gl_projection"



  $glx->target( $glx->create_render_window( \%args ) );

Create a window suitable for use as an OpenGL rendering target. %args can be:

  x        - default 0
  y        - default 0
  width    - default to screen width
  height   - default to screen height
  class    - default to InputOutput

There are dozens of other parameters you can specify. See "new_window" in X11::Xlib::Display.


  $glx->target( $glx->create_render_pixmap( \%args ) );

Create a pixmap suitable for use as an OpenGL rendering target. %args can be:

  width - required
  height - required
  depth  - defaults to depth of your visual


Convenience method; initializes rendering target if it wasn't already done, then clears the GL buffers.


Convenience method; calls glXSwapBuffers and then logs any glGetError bits that were set, via Log::Any


Call glXSwapBuffers


Convenience method to call glGetError repeatedly and build a hash of the symbolic names of the error constants.


For old-school OpenGL (i.e. non-shader), this sets up a simple perspective projection matrix.

    ortho => $bool,
    left => ..., right => ..., top => ..., bottom => ...,
    near => ..., far => ..., z => ...,
    aspect => ..., mirror_x => $bool, mirror_y => $bool,

If ortho is true, it calls glOrtho, else glFrustum. The left, right, top, bottom, near, far parameters are as documented for these functions, but if you request a Frustum and specify a non-zero z then it scales the parameters so that a vertex ($left,$top,$z) displays at the upper-left corner of the screen. (normally the upper left would be ($left,$top,$near)) This allows you to separate the near clipping plane from the plane you use to scale your coordinates.

If you specify x, y, or z, it calls glTranslated(-x,-y,-z) after the glFrustum or glOrtho.

If you specify aspect and omit one or more of left, right, bottom, top, then it calculates the missing dimension by this aspect ratio. If aspect is the string 'auto', it will calculate the missing dimension based on the combination of the window aspect ratio in pixels times the pixel physical aspect ratio in millimeters (as reported by X11) to give you a square coordinate system. If both dimensions are missing, top defaults to -bottom, or 1, and the rest is calculated from that.

If you specify mirror_x or mirror_y, it will flip the coordinate system so that +x is leftward or +y is downward. (remember, GL coordinates have +y upward by default). This will also call glFrontFace to match, so mirrored X or Y is GL_CW (clockwise) and neither mirrored or both mirrored is the default GL_CCW (counter clockwise).


Michael Conrad <>


This software is copyright (c) 2021 by Michael Conrad.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.