Skip to content

Instantly share code, notes, and snippets.

@hikari-no-yume
Created May 24, 2023 15:38
Show Gist options
  • Save hikari-no-yume/d454c8c4cdc0b6e460238238f53aec07 to your computer and use it in GitHub Desktop.
Save hikari-no-yume/d454c8c4cdc0b6e460238238f53aec07 to your computer and use it in GitHub Desktop.
sharing between GL contexts in a single window, with SDL2
use sdl2::video::{GLContext, GLProfile, Window};
use sdl2::{EventPump, VideoSubsystem};
use std::time::Instant;
fn make_big_gl() -> (u32, u32, Vec<u8>) {
let small_gl_data = b"\
00GGGG00L0000000\
0G0000G0L0000000\
G0000000L0000000\
G0000000L0000000\
G00GGGG0L0000000\
G00000G0L0000000\
G00000G0L0000000\
0GGGGG00LLLLLLLL\
";
let small_gl_width = 16;
let small_gl_height = 8;
let big_gl_width = small_gl_width * 1;
let big_gl_height = small_gl_height * 1;
let mut big_gl_data = Vec::<u8>::with_capacity(big_gl_width * big_gl_height);
for y in 0..big_gl_height {
for x in 0..big_gl_width {
big_gl_data.push(small_gl_data[(y % small_gl_height) * small_gl_width + x % small_gl_width]);
}
}
(big_gl_width.try_into().unwrap(), big_gl_height.try_into().unwrap(), big_gl_data)
}
fn test_opengl(
video_ctx: &VideoSubsystem,
window: &Window,
gl_ctx: &GLContext,
color: (f32, f32, f32, f32),
with_tex: Option<u32>,
) -> u32 {
window.gl_make_current(gl_ctx).unwrap();
#[allow(non_snake_case)]
let tex = unsafe {
let glClearColor: unsafe extern "C" fn(f32, f32, f32, f32) =
std::mem::transmute(video_ctx.gl_get_proc_address("glClearColor"));
let glClear: unsafe extern "C" fn(u32) =
std::mem::transmute(video_ctx.gl_get_proc_address("glClear"));
let glGetString: unsafe extern "C" fn(u32) -> *const u8 =
std::mem::transmute(video_ctx.gl_get_proc_address("glGetString"));
let glGenTextures: unsafe extern "C" fn(u32, *const u32) =
std::mem::transmute(video_ctx.gl_get_proc_address("glGenTextures"));
let glBindTexture: unsafe extern "C" fn(u32, u32) =
std::mem::transmute(video_ctx.gl_get_proc_address("glBindTexture"));
let glTexImage2D: unsafe extern "C" fn(u32, u32, u32, u32, u32, u32, u32, u32, *const u8) = std::mem::transmute(video_ctx.gl_get_proc_address("glTexImage2D"));
let glTexParameteri: unsafe extern "C" fn(u32, u32, u32) = std::mem::transmute(video_ctx.gl_get_proc_address("glTexParameteri"));
let glEnable: unsafe extern "C" fn(u32) = std::mem::transmute(video_ctx.gl_get_proc_address("glEnable"));
let glBegin: unsafe extern "C" fn(u32) = std::mem::transmute(video_ctx.gl_get_proc_address("glBegin"));
let glEnd: unsafe extern "C" fn() = std::mem::transmute(video_ctx.gl_get_proc_address("glEnd"));
let glVertex2f: unsafe extern "C" fn(f32, f32) = std::mem::transmute(video_ctx.gl_get_proc_address("glVertex2f"));
let glTexCoord2f: unsafe extern "C" fn(f32, f32) = std::mem::transmute(video_ctx.gl_get_proc_address("glTexCoord2f"));
glClearColor(color.0, color.1, color.2, color.3);
// GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT
glClear(0x00004000 | 0x00000400 | 0x00000100);
// GL_VERSION
let version_str = std::ffi::CStr::from_ptr(glGetString(0x1F02) as *const _);
println!("glGetString(GL_VERSION): {:?}", version_str.to_str());
let tex = with_tex.unwrap_or_else(|| {
let mut tex = 0;
glGenTextures(1, &mut tex);
glBindTexture(
0x0DE1, // GL_TEXTURE_2D
tex,
);
let (width, height, data) = make_big_gl();
glTexImage2D(
0x0DE1, // GL_TEXTURE_2D
0,
0x1909, // GL_LUMINANCE,
width,
height,
0,
0x1909, // GL_LUMINANCE
0x1401, // GL_UNSIGNED_BYTE
data.as_ptr(),
);
glTexParameteri(
0x0DE1, // GL_TEXTURE_2D,
0x2801, // GL_TEXTURE_MIN_FILTER,
0x2600, // GL_NEAREST
);
glTexParameteri(
0x0DE1, // GL_TEXTURE_2D,
0x2800, // GL_TEXTURE_MAG_FILTER,
0x2600, // GL_NEAREST
);
tex
});
glBindTexture(
0x0DE1, // GL_TEXTURE_2D
tex,
);
glEnable(
0x0DE1, // GL_TEXTURE_2D
);
glBegin(
0x0007, // GL_QUADS
);
glTexCoord2f(0.0, 0.0);
glVertex2f(0.0, 0.0);
glTexCoord2f(1.0, 0.0);
glVertex2f(1.0, 0.0);
glTexCoord2f(1.0, 1.0);
glVertex2f(1.0, 1.0);
glTexCoord2f(0.0, 1.0);
glVertex2f(0.0, 1.0);
glEnd();
tex
};
window.gl_swap_window();
tex
}
fn make_gl_ctx(
video_ctx: &VideoSubsystem,
window: &Window,
version: (u8, u8),
profile: GLProfile,
share: bool,
) -> GLContext {
let (major, minor) = version;
let attr = video_ctx.gl_attr();
attr.set_context_major_version(major);
attr.set_context_minor_version(minor);
attr.set_context_profile(profile);
attr.set_share_with_current_context(share);
window.gl_create_context().unwrap()
}
fn wait(pump: &mut EventPump, secs: u64) {
let start = Instant::now();
loop {
let _ = pump.poll_event();
if Instant::now().duration_since(start).as_secs() >= secs {
return;
}
}
}
pub fn main() {
let sdl_ctx = sdl2::init().unwrap();
let video_ctx = sdl_ctx.video().unwrap();
let window = video_ctx
.window("Test Window", 128, 128)
.opengl()
.build()
.unwrap();
let mut event_pump = sdl_ctx.event_pump().unwrap();
let ctx1 = make_gl_ctx(&video_ctx, &window, (2, 1), GLProfile::Compatibility, false);
let tex = test_opengl(&video_ctx, &window, &ctx1, (1.0, 0.0, 0.0, 0.0), None);
wait(&mut event_pump, 3);
let ctx2 = make_gl_ctx(&video_ctx, &window, (2, 1), GLProfile::Compatibility, true);
//let ctx2 = make_gl_ctx(&video_ctx, &window, (3, 2), sdl2::video::GLProfile::Core, true);
loop {
test_opengl(&video_ctx, &window, &ctx2, (0.0, 1.0, 0.0, 0.0), Some(tex));
wait(&mut event_pump, 3);
test_opengl(&video_ctx, &window, &ctx1, (0.0, 0.0, 1.0, 0.0), Some(tex));
wait(&mut event_pump, 3);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment