Implemented basic context sharing in viewport example

This commit is contained in:
Robin Quint 2022-03-16 08:53:18 +01:00
parent cbb98f5289
commit 57230dc81f

View File

@ -23,8 +23,8 @@ fn main() {
imgui.set_ini_filename(None); imgui.set_ini_filename(None);
let mut main_viewport = Viewport::new(&event_loop, true, true); let (mut main_viewport, context) = Viewport::new(&event_loop);
main_viewport.init_font_texture(&mut imgui); main_viewport.init_font_texture(&mut imgui, &context);
let mut winit_platform = imgui_winit_support::WinitPlatform::init(&mut imgui); let mut winit_platform = imgui_winit_support::WinitPlatform::init(&mut imgui);
imgui_winit_support::WinitPlatform::init_viewports( imgui_winit_support::WinitPlatform::init_viewports(
@ -40,6 +40,8 @@ fn main() {
let mut storage = ViewportStorage { let mut storage = ViewportStorage {
window_target, window_target,
context: &context,
main_viewport: &main_viewport,
viewports: &mut viewports, viewports: &mut viewports,
}; };
winit_platform.handle_viewport_event( winit_platform.handle_viewport_event(
@ -73,18 +75,20 @@ fn main() {
let mut storage = ViewportStorage { let mut storage = ViewportStorage {
window_target, window_target,
context: &context,
main_viewport: &main_viewport,
viewports: &mut viewports, viewports: &mut viewports,
}; };
winit_platform.update_viewports(&mut imgui, &mut storage); winit_platform.update_viewports(&mut imgui, &mut storage);
let main_draw_data = imgui.render(); let main_draw_data = imgui.render();
render_viewport(&mut main_viewport, main_draw_data); render_viewport(&mut main_viewport, main_draw_data, &context);
for (id, viewport) in &mut viewports { for (id, viewport) in &mut viewports {
viewport.init_font_texture(&mut imgui); viewport.init_font_texture(&mut imgui, &context);
let draw_data = imgui.viewport_by_id(*id).unwrap().draw_data(); let draw_data = imgui.viewport_by_id(*id).unwrap().draw_data();
render_viewport(viewport, draw_data); render_viewport(viewport, draw_data, &context);
} }
} }
} }
@ -104,18 +108,18 @@ fn render(imgui: &mut imgui::Context) {
ui.end_frame_early(); ui.end_frame_early();
} }
fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) { fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData, context: &glow::Context) {
let pos = viewport.window().inner_position().unwrap(); let pos = viewport.window().inner_position().unwrap();
unsafe { unsafe {
viewport.make_current(); viewport.make_current();
viewport.context.disable(glow::SCISSOR_TEST); context.disable(glow::SCISSOR_TEST);
viewport.context.clear(glow::COLOR_BUFFER_BIT); context.clear(glow::COLOR_BUFFER_BIT);
viewport.context.enable(glow::SCISSOR_TEST); context.enable(glow::SCISSOR_TEST);
viewport.context.bind_vertex_array(Some(viewport.vao)); context.bind_vertex_array(Some(viewport.vao));
viewport.context.use_program(Some(viewport.shader)); context.use_program(Some(viewport.shader));
let left = draw_data.display_pos[0]; let left = draw_data.display_pos[0];
let right = draw_data.display_pos[0] + draw_data.display_size[0]; let right = draw_data.display_pos[0] + draw_data.display_size[0];
@ -140,34 +144,25 @@ fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) {
1.0, 1.0,
]; ];
let loc = viewport let loc = context
.context
.get_uniform_location(viewport.shader, "u_Matrix") .get_uniform_location(viewport.shader, "u_Matrix")
.unwrap(); .unwrap();
viewport context.uniform_matrix_4_f32_slice(Some(&loc), false, &matrix);
.context
.uniform_matrix_4_f32_slice(Some(&loc), false, &matrix);
viewport.context.blend_func_separate( context.blend_func_separate(
glow::SRC_ALPHA, glow::SRC_ALPHA,
glow::ONE_MINUS_SRC_ALPHA, glow::ONE_MINUS_SRC_ALPHA,
glow::ONE, glow::ONE,
glow::ZERO, glow::ZERO,
); );
viewport.context.enable(glow::BLEND); context.enable(glow::BLEND);
viewport context.bind_buffer(glow::ARRAY_BUFFER, Some(viewport.vbo));
.context context.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(viewport.ibo));
.bind_buffer(glow::ARRAY_BUFFER, Some(viewport.vbo));
viewport
.context
.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(viewport.ibo));
viewport context.bind_texture(glow::TEXTURE_2D, viewport.font_tex);
.context
.bind_texture(glow::TEXTURE_2D, viewport.font_tex);
viewport.context.viewport( context.viewport(
0, 0,
0, 0,
viewport.window().inner_size().width as i32, viewport.window().inner_size().width as i32,
@ -177,7 +172,7 @@ fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) {
for draw_list in draw_data.draw_lists() { for draw_list in draw_data.draw_lists() {
unsafe { unsafe {
viewport.context.buffer_data_u8_slice( context.buffer_data_u8_slice(
glow::ARRAY_BUFFER, glow::ARRAY_BUFFER,
std::slice::from_raw_parts( std::slice::from_raw_parts(
draw_list.vtx_buffer().as_ptr() as *const u8, draw_list.vtx_buffer().as_ptr() as *const u8,
@ -185,7 +180,7 @@ fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) {
), ),
glow::STREAM_DRAW, glow::STREAM_DRAW,
); );
viewport.context.buffer_data_u8_slice( context.buffer_data_u8_slice(
glow::ELEMENT_ARRAY_BUFFER, glow::ELEMENT_ARRAY_BUFFER,
std::slice::from_raw_parts( std::slice::from_raw_parts(
draw_list.idx_buffer().as_ptr() as *const u8, draw_list.idx_buffer().as_ptr() as *const u8,
@ -193,12 +188,7 @@ fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) {
), ),
glow::STREAM_DRAW, glow::STREAM_DRAW,
); );
viewport.context.bind_vertex_buffer( context.bind_vertex_buffer(0, Some(viewport.vbo), 0, size_of::<DrawVert>() as i32);
0,
Some(viewport.vbo),
0,
size_of::<DrawVert>() as i32,
);
} }
for cmd in draw_list.commands() { for cmd in draw_list.commands() {
@ -211,11 +201,9 @@ fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) {
let width = (cmd_params.clip_rect[2] - cmd_params.clip_rect[0]) as i32; let width = (cmd_params.clip_rect[2] - cmd_params.clip_rect[0]) as i32;
let height = (cmd_params.clip_rect[3] - cmd_params.clip_rect[1]) as i32; let height = (cmd_params.clip_rect[3] - cmd_params.clip_rect[1]) as i32;
viewport context.scissor(x, window_height - (y + height), width, height);
.context context.enable(glow::SCISSOR_TEST);
.scissor(x, window_height - (y + height), width, height); context.draw_elements_base_vertex(
viewport.context.enable(glow::SCISSOR_TEST);
viewport.context.draw_elements_base_vertex(
glow::TRIANGLES, glow::TRIANGLES,
count as i32, count as i32,
glow::UNSIGNED_SHORT, glow::UNSIGNED_SHORT,
@ -232,16 +220,15 @@ fn render_viewport(viewport: &mut Viewport, draw_data: &DrawData) {
struct ViewportStorage<'a, T: 'static> { struct ViewportStorage<'a, T: 'static> {
window_target: &'a glutin::event_loop::EventLoopWindowTarget<T>, window_target: &'a glutin::event_loop::EventLoopWindowTarget<T>,
main_viewport: &'a Viewport,
context: &'a glow::Context,
viewports: &'a mut HashMap<imgui::Id, Viewport>, viewports: &'a mut HashMap<imgui::Id, Viewport>,
} }
impl<'a, T: 'static> imgui_winit_support::WinitPlatformViewportStorage for ViewportStorage<'a, T> { impl<'a, T: 'static> imgui_winit_support::WinitPlatformViewportStorage for ViewportStorage<'a, T> {
fn create_window(&mut self, id: imgui::Id, flags: imgui::ViewportFlags) { fn create_window(&mut self, id: imgui::Id, flags: imgui::ViewportFlags) {
let viewport = Viewport::new( let viewport =
self.window_target, Viewport::new_shared(self.window_target, self.main_viewport, self.context, flags);
false,
!flags.contains(ViewportFlags::NO_DECORATION),
);
self.viewports.insert(id, viewport); self.viewports.insert(id, viewport);
} }
@ -268,7 +255,6 @@ impl<'a, T: 'static> imgui_winit_support::WinitPlatformViewportStorage for Viewp
struct Viewport { struct Viewport {
window: Option<glutin::ContextWrapper<PossiblyCurrent, glutin::window::Window>>, window: Option<glutin::ContextWrapper<PossiblyCurrent, glutin::window::Window>>,
context: glow::Context,
vao: glow::VertexArray, vao: glow::VertexArray,
vbo: glow::Buffer, vbo: glow::Buffer,
ibo: glow::Buffer, ibo: glow::Buffer,
@ -277,17 +263,13 @@ struct Viewport {
} }
impl Viewport { impl Viewport {
fn new<T>( fn new<T>(event_loop: &glutin::event_loop::EventLoopWindowTarget<T>) -> (Self, glow::Context) {
event_loop: &glutin::event_loop::EventLoopWindowTarget<T>,
visible: bool,
decorated: bool,
) -> Self {
let wb = glutin::window::WindowBuilder::new() let wb = glutin::window::WindowBuilder::new()
.with_inner_size(glutin::dpi::LogicalSize::new(800.0, 600.0)) .with_inner_size(glutin::dpi::LogicalSize::new(800.0, 600.0))
.with_resizable(true) .with_resizable(true)
.with_title("Viewports") .with_title("Viewports")
.with_visible(visible) .with_visible(true)
.with_decorations(decorated); .with_decorations(true);
let window = unsafe { let window = unsafe {
glutin::ContextBuilder::new() glutin::ContextBuilder::new()
.with_double_buffer(Some(true)) .with_double_buffer(Some(true))
@ -339,9 +321,66 @@ impl Viewport {
(vao, vbo, ibo, program) (vao, vbo, ibo, program)
}; };
(
Self {
window: Some(window),
vao,
vbo,
ibo,
shader,
font_tex: None,
},
context,
)
}
fn new_shared<T>(
event_loop: &glutin::event_loop::EventLoopWindowTarget<T>,
main_viewport: &Viewport,
context: &glow::Context,
flags: imgui::ViewportFlags,
) -> Self {
let wb = glutin::window::WindowBuilder::new()
.with_inner_size(glutin::dpi::LogicalSize::new(100.0, 100.0))
.with_resizable(true)
.with_title("<unnamed>")
.with_always_on_top(flags.contains(ViewportFlags::TOP_MOST))
.with_decorations(!flags.contains(ViewportFlags::NO_DECORATION))
.with_visible(false);
let window = unsafe {
glutin::ContextBuilder::new()
.with_double_buffer(Some(true))
.with_vsync(true)
.with_shared_lists(main_viewport.window.as_ref().unwrap().context())
.build_windowed(wb, event_loop)
.unwrap()
.make_current()
.unwrap()
};
let (vao, vbo, ibo, shader) = unsafe {
let vao = context.create_vertex_array().unwrap();
let vbo = context.create_buffer().unwrap();
let ibo = context.create_buffer().unwrap();
context.bind_vertex_array(Some(vao));
context.vertex_attrib_binding(0, 0);
context.vertex_attrib_binding(1, 0);
context.vertex_attrib_binding(2, 0);
context.vertex_attrib_format_f32(0, 2, glow::FLOAT, false, 0);
context.vertex_attrib_format_f32(1, 2, glow::FLOAT, false, 8);
context.vertex_attrib_format_f32(2, 4, glow::UNSIGNED_BYTE, true, 16);
context.enable_vertex_attrib_array(0);
context.enable_vertex_attrib_array(1);
context.enable_vertex_attrib_array(2);
context.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(ibo));
context.bind_vertex_array(None);
(vao, vbo, ibo, main_viewport.shader)
};
Self { Self {
window: Some(window), window: Some(window),
context,
vao, vao,
vbo, vbo,
ibo, ibo,
@ -350,7 +389,7 @@ impl Viewport {
} }
} }
fn init_font_texture(&mut self, imgui: &mut imgui::Context) { fn init_font_texture(&mut self, imgui: &mut imgui::Context, context: &glow::Context) {
if self.font_tex.is_some() { if self.font_tex.is_some() {
return; return;
} }
@ -358,11 +397,11 @@ impl Viewport {
unsafe { unsafe {
self.make_current(); self.make_current();
let font_tex = self.context.create_texture().unwrap(); let font_tex = context.create_texture().unwrap();
let data = imgui.fonts().build_rgba32_texture(); let data = imgui.fonts().build_rgba32_texture();
self.context.bind_texture(glow::TEXTURE_2D, Some(font_tex)); context.bind_texture(glow::TEXTURE_2D, Some(font_tex));
self.context.tex_image_2d( context.tex_image_2d(
glow::TEXTURE_2D, glow::TEXTURE_2D,
0, 0,
glow::RGBA as i32, glow::RGBA as i32,
@ -373,22 +412,22 @@ impl Viewport {
glow::UNSIGNED_BYTE, glow::UNSIGNED_BYTE,
Some(data.data), Some(data.data),
); );
self.context.tex_parameter_i32( context.tex_parameter_i32(
glow::TEXTURE_2D, glow::TEXTURE_2D,
glow::TEXTURE_MAG_FILTER, glow::TEXTURE_MAG_FILTER,
glow::LINEAR as i32, glow::LINEAR as i32,
); );
self.context.tex_parameter_i32( context.tex_parameter_i32(
glow::TEXTURE_2D, glow::TEXTURE_2D,
glow::TEXTURE_MIN_FILTER, glow::TEXTURE_MIN_FILTER,
glow::LINEAR as i32, glow::LINEAR as i32,
); );
self.context.tex_parameter_i32( context.tex_parameter_i32(
glow::TEXTURE_2D, glow::TEXTURE_2D,
glow::TEXTURE_WRAP_S, glow::TEXTURE_WRAP_S,
glow::CLAMP_TO_EDGE as i32, glow::CLAMP_TO_EDGE as i32,
); );
self.context.tex_parameter_i32( context.tex_parameter_i32(
glow::TEXTURE_2D, glow::TEXTURE_2D,
glow::TEXTURE_WRAP_T, glow::TEXTURE_WRAP_T,
glow::CLAMP_TO_EDGE as i32, glow::CLAMP_TO_EDGE as i32,