Created
May 24, 2023 15:38
-
-
Save hikari-no-yume/d454c8c4cdc0b6e460238238f53aec07 to your computer and use it in GitHub Desktop.
sharing between GL contexts in a single window, with SDL2
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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