The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

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

VERSION

version 0.06

SYNOPSIS

  my $glx= X11::GLX::DWIM->new( \%options );
  while (1) {
    $glx->begin_frame();
    my_custom_opengl_rendering();
    $glx->end_frame();
  }
  
  # 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

DESCRIPTION

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.

ATTRIBUTES

display

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

screen

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

glx_version

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

glx_version_bcd

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

glx_extensions

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

fbconfig

  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.

visual_info

  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.

colormap

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

glx_context

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)

  $glx->glx_context({
    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.

has_glx_context

Returns whether glx_context has been initialized.

clear_glx_context

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

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

has_target

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

clear_target

Use this to un-set the target.

gl_clear_bits

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

Defaults to GL_COLOR_BUFFER_BIT + GL_DEPTH_BUFFER_BIT

gl_projection

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"

METHODS

create_render_window

  $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.

create_render_pixmap

  $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

begin_frame

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

end_frame

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

swap_buffers

Call glXSwapBuffers

get_gl_errors

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

apply_gl_projection

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

  $glx->apply_gl_projection(
    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).

AUTHOR

Michael Conrad <mike@nrdvana.net>

COPYRIGHT AND LICENSE

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.