SDL2::Video#

📦 std

Windows and OpenGL contexts.

This is the part of SDL2 that puts something on the screen: it opens a window, moves and resizes it, and - when you ask for one - gives it an OpenGL context to render into.

The SDL2::Window object#

SDL2::Window->new takes named arguments, all optional except that a window with no size is not much use:

my $win = SDL2::Window->new(
    title => 'my program',   # window caption
    x     => undef,          # position; undef means "let the system choose"
    y     => undef,
    w     => 640,            # size in pixels (default 640 x 480)
    h     => 480,
    flags => 0,              # OR of SDL_WINDOW_* constants
    shown => 1,              # false opens the window hidden
    opengl => 0,             # true adds SDL_WINDOW_OPENGL
    resizable => 0,          # true adds SDL_WINDOW_RESIZABLE
);

It calls SDL_Init(SDL_INIT_VIDEO) for you if the video subsystem is not up yet, and croaks if the window cannot be created. The window closes and is freed when the last reference to $win goes away.

Its methods:

  • $win->title / $win->set_title($text) - the caption.

  • $win->size - the list ($w, $h); $win->set_size($w, $h) to change it.

  • $win->position - the list ($x, $y); $win->set_position($x, $y).

  • $win->show / $win->hide / $win->raise - visibility.

  • $win->minimize / $win->maximize / $win->restore.

  • $win->set_fullscreen($flags) - 0 for windowed, SDL_WINDOW_FULLSCREEN_DESKTOP for borderless full screen.

  • $win->id - the numeric id events carry in their window_id field.

  • $win->flags - the OR of the SDL_WINDOW_* bits currently set.

  • $win->wm_info - the window manager’s own handles for this window, as a hash reference. What a graphics API other than OpenGL needs in order to draw here; see below.

  • $win->renderer(%opts) - a SDL2::Renderer drawing into this window.

  • $win->gl_context - an SDL2::GLContext, made current immediately.

  • $win->gl_swap - show the frame just drawn by OpenGL.

  • $win->destroy - close it now rather than at scope exit.

  • $win->handle - the raw pointer, for passing to the direct layer.

The SDL2::GLContext object#

$win->gl_context returns one, already current. Ask for the OpenGL version you need BEFORE creating the window, with SDL_GL_SetAttribute:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

my $win = SDL2::Window->new(w => 800, h => 600, opengl => 1);
my $ctx = $win->gl_context;

Its methods are $ctx->make_current($win), $ctx->handle and $ctx->destroy. SDL_GL_GetProcAddress($name) resolves an OpenGL entry point through the context, which is how a Perl OpenGL binding finds the modern functions without GLEW.

Drawing on the window with something other than OpenGL#

A GPU API that is not OpenGL does not take a context from SDL; it takes the window manager’s own handles and builds its own surface on them. $win->wm_info is where those come from:

my $wm = $win->wm_info;
# { subsystem => 2, driver => 'x11', display => ..., window => ... }

driver is the same lowercase name SDL_GetCurrentVideoDriver returns, and it decides which other keys are there: display and window under X11, display and surface under Wayland. They are plain integers - a C pointer and an X11 XID - meant to be handed straight back to whatever asked for them, not followed from Perl.

Peta::WebGPU::Device->new(window => $win) is the one consumer in the runtime today; it reads exactly these keys.