#opengl #opengl-context #gl #khronos #graphics

gl-headless

Easiest way to create a headless OpenGL context

3 unstable releases

0.2.2 May 31, 2023
0.2.1 May 31, 2023
0.2.0 May 31, 2023
0.1.0 May 30, 2023

#92 in Rendering

MIT license

15KB
159 lines

gl-headless

Latest Version Docs License

Easiest way to create a headless OpenGL context.

Simply add #[gl_headless] to any function (even main), then call that function as you otherwise would. Within the scope of the function, an OpenGL context will be available.

See all available options in the documentation for #[gl_headless].

Simple Example

[dependencies]
gl = "0.14"
gl-headless = "0.2"
use gl_headless::gl_headless;

#[gl_headless]
unsafe fn main() {
    let (mut major, mut minor) = (0, 0);
    gl::GetIntegerv(gl::MAJOR_VERSION, &mut major);
    gl::GetIntegerv(gl::MINOR_VERSION, &mut minor);
    println!("OpenGL {major}.{minor}");
}

Specify OpenGL Version

By default #[gl_headless] attempts to create an OpenGL 4.6 context. To use a specific version add, e.g. version = "3.3":

use gl_headless::gl_headless;

#[gl_headless(version = "3.3")]
unsafe fn main() {
    let (mut major, mut minor) = (0, 0);
    gl::GetIntegerv(gl::MAJOR_VERSION, &mut major);
    gl::GetIntegerv(gl::MINOR_VERSION, &mut minor);
    println!("OpenGL {major}.{minor}");
}

Parameters & Return Type

Specify function parameters and return type as you otherwise would:

use gl_headless::gl_headless;

fn main() {
    let version = get_version("OpenGL");
    println!("{version}");
}

#[gl_headless]
fn get_version(prefix: &str) -> String {
    let (mut major, mut minor) = (0, 0);
    unsafe {
        gl::GetIntegerv(gl::MAJOR_VERSION, &mut major);
        gl::GetIntegerv(gl::MINOR_VERSION, &mut minor);
    }
    format!("{prefix} {major}.{minor}")
}

Multiple Functions

Multiple functions can use #[gl_headless]:

use gl_headless::gl_headless;

fn main() {
    unsafe {
        example1();
        example2();
    }
}

#[gl_headless(version = "3.3")]
unsafe fn example1() {
    let (mut major, mut minor) = (0, 0);
    gl::GetIntegerv(gl::MAJOR_VERSION, &mut major);
    gl::GetIntegerv(gl::MINOR_VERSION, &mut minor);
    println!("OpenGL {major}.{minor}");
}

#[gl_headless]
unsafe fn example2() {
    let mut handle = 0;
    gl::CreateBuffers(1, &mut handle);

    let data: [f32; 5] = [1.0, 2.0, 3.0, 4.0, 5.0];
    gl::NamedBufferData(
        handle,
        std::mem::size_of_val(&data) as _,
        data.as_ptr() as *const _,
        gl::STATIC_DRAW,
    );

    let mut byte_size = 0;
    gl::GetNamedBufferParameteriv(handle, gl::BUFFER_SIZE, &mut byte_size);
    let float_count = (byte_size as usize) / std::mem::size_of::<f32>() as usize;

    let mut floats = vec![0.0_f32; float_count];
    gl::GetNamedBufferSubData(
        handle,
        0,
        std::mem::size_of_val(floats.as_slice()) as _,
        floats.as_mut_ptr() as *mut _,
    );

    println!("Write: {:?}", data);
    println!("Read:  {:?}", floats);

    assert_eq!(data, floats.as_slice());
}

Dependencies

~2–3MB
~62K SLoC