Render Contexts
Trial is "backend agnostic" in that it can work with several underlying libraries to handle the OpenGL context and window management. The standard and most well-tested backend is the GLFW integration through trial-glfw.
Typically, management of the context is handled by main
and the associated launch
. For highest convenience, you'll probably just want to create your own wrapper around launch
that passes the appropriate arguments for context construction via the :context
initarg.
Context Objects
The context combines both a window and an OpenGL context, treating them as the same. It is expected that games do not utilise multiple windows, instead using virtual windows within the main game window if required.
There may be multiple context instances in flight at once, in order to allow asynchronous upload of resources such as textures through shared contexts in background threads. However, there can only be one primary context in flight at a time, and only one context of any kind can be current to any one thread at a time.
In order to issue OpenGL commands, an appropriate context must be current on the thread. Many commands are only available on the primary context. Typically you will only need one context, and with the render-loop
class, all the drawing will be contained on one thread anyway.
The base context object has a rather wide API to interact with. The context itself has a handler
to which it sends events whenever input or other changes come along. Typically the handler will be a main
instance, which then sends the events along to the scene for delivery. See the event-loop.
Context Interaction
*context*
Accesses the current contextmake-context
Create a new context instance. Should be used to construct shared contextslaunch-with-context
Should be called to launchmain
with a valid primary context instancedestroy-context
Destroy the context and make it unusable. Frees all GL resourcesvalid-p
Whether the context is still valid and thus usable at allmake-current
To make the context current in this thread. Post this, GL commands may be used. Beware of stealing the context from another thread, usewith-context
for safe managementdone-current
To free the context up from this thread. Post this, no GL commands may be usedcurrent-p
Whether the context is current in this threadwith-context
Invoke body with the context bound locally. Ensures proper context sharingprofile
What profile is used. Should be one of::core :compatibility :es NIL
version
The major and minor version of OpenGL as a list of two elements
Window Interaction
Note that these functions may be no-ops on some backends where the concept of a "window" does not apply.
hide
Hides the windowshow
Makes the window visible, changes its fullscreen behaviour, and video modevisible-p
Whether the window is currently visible or notresize
Resize the window. Typically you want to useshow
with a video mode insteadquit
Closes the window and shuts things downshow-cursor
Ensure the OS cursor can be seenhide-cursor
Hides the OS cursor turning it invisiblelock-cursor
Locks the OS cursor within the window preventing it from escaping. Use with care to prevent over-eager cursor captureunlock-cursor
Unlock the OS cursor allowing it to escape the windowcursor-position
Return the current cursor position within the windowcursor
Access the cursor's image. A few system-defined cursors are provided via symbols:NIL
The system's default cursor:arrow
An arrow for pointing at things:text
A caret for text editing:hand
A hand for grabbing and moving:horizontal-resize
A horizontal arrow for resizing:vertical-resize
A vertical arrow for resizing:crosshair
A crosshair for picking and placing
title
Access the title shown on the windowvsync
Access whether vertical screen synchronisation is in effectwidth
Return the window's current width in pixelsheight
Return the window's current height in pixels
System Interaction
Some interactions with the rest of the operating system are also provided:
clipboard
Access the clipboard contents. A context must, in the very least, support strings, but may also support arbitrary octet vector contentlocal-key-string
Return the name of the key in the current layout for the given scan-code. Meaning if the user has, say, a Dvorak layout, the scan-code:t
will yield"y"
. You should use this function whenever you intend to display a key prompt to the user.
Video Modes and Monitors
One important part is the handling of "video modes" or screen resolution and refresh rate. Trial defines a video mode "structure" as a list composed out of: (width height [refresh-rate [display-descriptor-string]])
.
A user may have multiple monitors connected, and the available list of video modes for each may be different. To list the available monitors, use list-monitors
, and the current monitor the window is on can be retrieved with current-monitor
.
The monitor structure is backend-dependent, but must support getting its string name
. To get the monitor back from its name, use find-monitor
. If the monitor has since been removed or is not present, it may not be returned even with a valid name.
To get the video modes available, use list-video-modes
. To activate one, pass the mode to show
. If the mode came from a monitor listing, it will include the monitor's name, ensuring that the window will be shown on the correct monitor.
Events
Aside from the keyboard and mouse input events, the context is also responsible for sending the following events:
resize
After the window has changed size. Typically requires updating camera and UIlose-focus
After the window has lost focus. May be useful to pause the gamegain-focus
After the window has received focus. May be useful to unpause the gamewindow-hidden
After the window has been hidden or minimisedwindow-shown
After the window has been restored from being hidden or minimised
Context Management
Typically managing a context directly is cumbersome and a lot of extra scaffolding is needed. The first part is the render-loop
. On its own, the render loop does not care about a context at all. ALl it does is, after being start
ed, it maintains a thread that calls update
and render
on the loop in regular intervals – fixed timestep intervals for update
and as much as possible under the constraints of frame limits and such for render
.
The display
as a render-loop upgrade then ties the loop behaviour to an actual context instance, manages the cleanup and setup of the context, and so on. It introduces setup-rendering
for initial setup of GL attributes and modes.
Finally, the main
instance ties everything together with a scene
for event management, and a loader
for resource management (see resources). This is typically what you want to subclass for your own games, as it provides most of the convenience and is required for many of the other integrations with other subsystems.