mirror of
https://github.com/emilk/egui.git
synced 2026-08-30 21:30:03 -04:00
refactor eframe viewport sync rendering for glow and wgpu
This commit is contained in:
@@ -1073,113 +1073,18 @@ mod glow_integration {
|
|||||||
let c_painter = painter.clone();
|
let c_painter = painter.clone();
|
||||||
let c_time = integration.beginning;
|
let c_time = integration.beginning;
|
||||||
|
|
||||||
// ## Sync Rendering
|
|
||||||
integration.egui_ctx.set_render_sync_callback(
|
integration.egui_ctx.set_render_sync_callback(
|
||||||
move |egui_ctx, mut viewport_builder, pair, render| {
|
move |egui_ctx, viewport_builder, pair, render| {
|
||||||
|
Self::render_sync_viewport(
|
||||||
let has_window = c_glutin.read().viewports.get(&pair).is_some();
|
egui_ctx,
|
||||||
if !has_window{
|
viewport_builder,
|
||||||
if viewport_builder.icon.is_none(){
|
pair,
|
||||||
viewport_builder.icon = c_glutin.read().builders.get(&pair.parent).and_then(|b|b.icon.clone());
|
render,
|
||||||
}
|
&c_glutin,
|
||||||
|
&c_gl,
|
||||||
{
|
&c_painter,
|
||||||
let mut glutin = c_glutin.write();
|
c_time,
|
||||||
glutin.viewports.entry(pair.this).or_insert(Arc::new(RwLock::new(Window{ gl_surface: None, window: None, pair, render: None, egui_winit: None })));
|
);
|
||||||
glutin.builders.entry(pair.this).or_insert(viewport_builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
let win = c_glutin.read().viewports[&pair].clone();
|
|
||||||
let event_loop;
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
unsafe{
|
|
||||||
event_loop = WINIT_EVENT_LOOP.with(|event_loop|event_loop.read().as_ref().unwrap());
|
|
||||||
}
|
|
||||||
c_glutin.write().init_window(&win, event_loop).expect("Cannot init window on egui::Context::create_viewport_sync");
|
|
||||||
}
|
|
||||||
|
|
||||||
'try_render: {
|
|
||||||
let window = c_glutin.read().viewports.get(&pair).cloned();
|
|
||||||
if let Some(window) = window {
|
|
||||||
let output;
|
|
||||||
{
|
|
||||||
let window = &mut *window.write();
|
|
||||||
if let Some(winit_state) = &mut window.egui_winit {
|
|
||||||
if let Some(win) = window.window.clone() {
|
|
||||||
let win = win.read();
|
|
||||||
let mut input = winit_state.take_egui_input(&win);
|
|
||||||
input.time = Some(c_time.elapsed().as_secs_f64());
|
|
||||||
output = egui_ctx.run(
|
|
||||||
input,
|
|
||||||
pair,
|
|
||||||
|ctx| {
|
|
||||||
render(ctx);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
let glutin = &mut *c_glutin.write();
|
|
||||||
|
|
||||||
let screen_size_in_pixels: [u32; 2] =
|
|
||||||
win.inner_size().into();
|
|
||||||
|
|
||||||
let clipped_primitives = egui_ctx.tessellate(output.shapes);
|
|
||||||
|
|
||||||
glutin.current_gl_context = Some(
|
|
||||||
glutin
|
|
||||||
.current_gl_context
|
|
||||||
.take()
|
|
||||||
.unwrap()
|
|
||||||
.make_not_current()
|
|
||||||
.unwrap()
|
|
||||||
.make_current(window.gl_surface.as_ref().unwrap())
|
|
||||||
.unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
if !window
|
|
||||||
.gl_surface
|
|
||||||
.as_ref()
|
|
||||||
.unwrap()
|
|
||||||
.is_current(glutin.current_gl_context.as_ref().unwrap())
|
|
||||||
{
|
|
||||||
let builder = &&glutin.builders[&window.pair];
|
|
||||||
log::error!("egui::create_viewport_sync with title: `{}` is not created in main thread, try to use wgpu!", builder.title);
|
|
||||||
}
|
|
||||||
|
|
||||||
egui_glow::painter::clear(
|
|
||||||
&c_gl,
|
|
||||||
screen_size_in_pixels,
|
|
||||||
[0.0, 0.0, 0.0, 0.0],
|
|
||||||
);
|
|
||||||
|
|
||||||
c_painter.write().paint_and_update_textures(
|
|
||||||
screen_size_in_pixels,
|
|
||||||
egui_ctx.pixels_per_point(),
|
|
||||||
&clipped_primitives,
|
|
||||||
&output.textures_delta,
|
|
||||||
);
|
|
||||||
crate::profile_scope!("swap_buffers");
|
|
||||||
let _ = window
|
|
||||||
.gl_surface
|
|
||||||
.as_ref()
|
|
||||||
.expect("failed to get surface to swap buffers")
|
|
||||||
.swap_buffers(
|
|
||||||
glutin.current_gl_context.as_ref().expect(
|
|
||||||
"failed to get current context to swap buffers",
|
|
||||||
),
|
|
||||||
);
|
|
||||||
winit_state.handle_platform_output(
|
|
||||||
&win,
|
|
||||||
egui_ctx,
|
|
||||||
output.platform_output,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
break 'try_render;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break 'try_render;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -1194,6 +1099,125 @@ mod glow_integration {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn render_sync_viewport(
|
||||||
|
egui_ctx: &egui::Context,
|
||||||
|
mut viewport_builder: ViewportBuilder,
|
||||||
|
pair: ViewportIdPair,
|
||||||
|
render: Box<dyn FnOnce(&egui::Context) + '_>,
|
||||||
|
glutin: &RwLock<GlutinWindowContext>,
|
||||||
|
gl: &glow::Context,
|
||||||
|
painter: &RwLock<egui_glow::Painter>,
|
||||||
|
time: Instant,
|
||||||
|
) {
|
||||||
|
let has_window = glutin.read().viewports.get(&pair).is_some();
|
||||||
|
|
||||||
|
// This will create a new native window if is needed
|
||||||
|
if !has_window {
|
||||||
|
// Inherit parent icon if none
|
||||||
|
{
|
||||||
|
let glutin = glutin.read();
|
||||||
|
if viewport_builder.icon.is_none() && glutin.builders.get(&pair).is_none() {
|
||||||
|
viewport_builder.icon = glutin
|
||||||
|
.builders
|
||||||
|
.get(&pair.parent)
|
||||||
|
.and_then(|b| b.icon.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut glutin = glutin.write();
|
||||||
|
glutin
|
||||||
|
.viewports
|
||||||
|
.entry(pair.this)
|
||||||
|
.or_insert(Arc::new(RwLock::new(Window {
|
||||||
|
gl_surface: None,
|
||||||
|
window: None,
|
||||||
|
pair,
|
||||||
|
render: None,
|
||||||
|
egui_winit: None,
|
||||||
|
})));
|
||||||
|
glutin.builders.entry(pair.this).or_insert(viewport_builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
let win = glutin.read().viewports[&pair].clone();
|
||||||
|
let event_loop;
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {
|
||||||
|
event_loop =
|
||||||
|
WINIT_EVENT_LOOP.with(|event_loop| event_loop.read().as_ref().unwrap());
|
||||||
|
}
|
||||||
|
glutin
|
||||||
|
.write()
|
||||||
|
.init_window(&win, event_loop)
|
||||||
|
.expect("Cannot init window on egui::Context::create_viewport_sync");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rendering the sync viewport
|
||||||
|
|
||||||
|
let window = glutin.read().viewports.get(&pair).cloned();
|
||||||
|
let Some(window) = window else { return };
|
||||||
|
let output;
|
||||||
|
|
||||||
|
let window = &mut *window.write();
|
||||||
|
let Some(winit_state) = &mut window.egui_winit else { return };
|
||||||
|
let Some(win) = window.window.clone() else { return };
|
||||||
|
let win = win.read();
|
||||||
|
let mut input = winit_state.take_egui_input(&win);
|
||||||
|
input.time = Some(time.elapsed().as_secs_f64());
|
||||||
|
output = egui_ctx.run(input, pair, |ctx| {
|
||||||
|
render(ctx);
|
||||||
|
});
|
||||||
|
let glutin = &mut *glutin.write();
|
||||||
|
|
||||||
|
let screen_size_in_pixels: [u32; 2] = win.inner_size().into();
|
||||||
|
|
||||||
|
let clipped_primitives = egui_ctx.tessellate(output.shapes);
|
||||||
|
|
||||||
|
glutin.current_gl_context = Some(
|
||||||
|
glutin
|
||||||
|
.current_gl_context
|
||||||
|
.take()
|
||||||
|
.unwrap()
|
||||||
|
.make_not_current()
|
||||||
|
.unwrap()
|
||||||
|
.make_current(window.gl_surface.as_ref().unwrap())
|
||||||
|
.unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if !window
|
||||||
|
.gl_surface
|
||||||
|
.as_ref()
|
||||||
|
.unwrap()
|
||||||
|
.is_current(glutin.current_gl_context.as_ref().unwrap())
|
||||||
|
{
|
||||||
|
let builder = &&glutin.builders[&window.pair];
|
||||||
|
log::error!("egui::create_viewport_sync with title: `{}` is not created in main thread, try to use wgpu!", builder.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
egui_glow::painter::clear(gl, screen_size_in_pixels, [0.0, 0.0, 0.0, 0.0]);
|
||||||
|
|
||||||
|
painter.write().paint_and_update_textures(
|
||||||
|
screen_size_in_pixels,
|
||||||
|
egui_ctx.pixels_per_point(),
|
||||||
|
&clipped_primitives,
|
||||||
|
&output.textures_delta,
|
||||||
|
);
|
||||||
|
crate::profile_scope!("swap_buffers");
|
||||||
|
let _ = window
|
||||||
|
.gl_surface
|
||||||
|
.as_ref()
|
||||||
|
.expect("failed to get surface to swap buffers")
|
||||||
|
.swap_buffers(
|
||||||
|
glutin
|
||||||
|
.current_gl_context
|
||||||
|
.as_ref()
|
||||||
|
.expect("failed to get current context to swap buffers"),
|
||||||
|
);
|
||||||
|
winit_state.handle_platform_output(&win, egui_ctx, output.platform_output);
|
||||||
|
}
|
||||||
|
|
||||||
fn process_viewport_builders(
|
fn process_viewport_builders(
|
||||||
glutin_ctx: &Arc<RwLock<GlutinWindowContext>>,
|
glutin_ctx: &Arc<RwLock<GlutinWindowContext>>,
|
||||||
mut viewports: Vec<ViewportOutput>,
|
mut viewports: Vec<ViewportOutput>,
|
||||||
@@ -1976,9 +2000,9 @@ mod wgpu_integration {
|
|||||||
id: ViewportId,
|
id: ViewportId,
|
||||||
builder: &ViewportBuilder,
|
builder: &ViewportBuilder,
|
||||||
windows_id: &mut HashMap<winit::window::WindowId, ViewportId>,
|
windows_id: &mut HashMap<winit::window::WindowId, ViewportId>,
|
||||||
painter: &Arc<RwLock<egui_wgpu::winit::Painter>>,
|
painter: &RwLock<egui_wgpu::winit::Painter>,
|
||||||
window: &mut Option<Arc<RwLock<winit::window::Window>>>,
|
window: &mut Option<Arc<RwLock<winit::window::Window>>>,
|
||||||
state: &Arc<RwLock<Option<egui_winit::State>>>,
|
state: &RwLock<Option<egui_winit::State>>,
|
||||||
event_loop: &EventLoopWindowTarget<UserEvent>,
|
event_loop: &EventLoopWindowTarget<UserEvent>,
|
||||||
) {
|
) {
|
||||||
if let Ok(new_window) = create_winit_window_builder(builder).build(event_loop) {
|
if let Ok(new_window) = create_winit_window_builder(builder).build(event_loop) {
|
||||||
@@ -2135,79 +2159,19 @@ mod wgpu_integration {
|
|||||||
let c_painter = painter.clone();
|
let c_painter = painter.clone();
|
||||||
let c_windows_id = windows_id.clone();
|
let c_windows_id = windows_id.clone();
|
||||||
|
|
||||||
// ## Sync Rendering
|
|
||||||
integration.egui_ctx.set_render_sync_callback(
|
integration.egui_ctx.set_render_sync_callback(
|
||||||
move |egui_ctx, mut viewport_builder, ViewportIdPair{ this: viewport_id, parent: parent_id }, render| {
|
move |egui_ctx, viewport_builder, pair, render| {
|
||||||
// Creating a new native window
|
Self::render_sync_viewport(
|
||||||
if c_viewports.read().get(&viewport_id).is_none(){
|
egui_ctx,
|
||||||
let mut _windows = c_viewports.write();
|
viewport_builder,
|
||||||
|
pair,
|
||||||
{
|
render,
|
||||||
let builders = c_builders.read();
|
&c_viewports,
|
||||||
if viewport_builder.icon.is_none() && builders.get(&viewport_id).is_none(){
|
&c_builders,
|
||||||
viewport_builder.icon = builders.get(&parent_id).unwrap().icon.clone();
|
c_time,
|
||||||
}
|
&c_painter,
|
||||||
}
|
&c_windows_id,
|
||||||
|
);
|
||||||
let Window{window, state, ..} = _windows.entry(viewport_id).or_insert(Window{window: None, state: Arc::new(RwLock::new(None)), render: None, parent_id });
|
|
||||||
let _ = c_builders.write().entry(viewport_id).or_insert(viewport_builder.clone());
|
|
||||||
|
|
||||||
let event_loop;
|
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
unsafe{
|
|
||||||
event_loop = WINIT_EVENT_LOOP.with(|event_loop|event_loop.read().as_ref().unwrap());
|
|
||||||
}
|
|
||||||
Self::init_window(viewport_id, &viewport_builder, &mut c_windows_id.write(), &c_painter, window, state, event_loop);
|
|
||||||
}
|
|
||||||
'try_render: {
|
|
||||||
let window = c_viewports.read().get(&viewport_id).cloned();
|
|
||||||
if let Some(window) = window {
|
|
||||||
let output;
|
|
||||||
{
|
|
||||||
if let Some(winit_state) = &mut *window.state.write() {
|
|
||||||
if let Some(win) = window.window {
|
|
||||||
let win = win.read();
|
|
||||||
let mut input = winit_state.take_egui_input(&win);
|
|
||||||
input.time = Some(c_time.elapsed().as_secs_f64());
|
|
||||||
output = egui_ctx.run(
|
|
||||||
input,
|
|
||||||
ViewportIdPair::new(viewport_id, parent_id),
|
|
||||||
|ctx| {
|
|
||||||
render(ctx);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if let Err(err) = pollster::block_on(
|
|
||||||
c_painter.write().set_window(viewport_id, Some(&win)),
|
|
||||||
){
|
|
||||||
log::error!("when rendering viewport_id: {viewport_id}, set_window Error {err}");
|
|
||||||
}
|
|
||||||
|
|
||||||
let clipped_primitives = egui_ctx.tessellate(output.shapes);
|
|
||||||
c_painter.write().paint_and_update_textures(
|
|
||||||
viewport_id,
|
|
||||||
egui_ctx.pixels_per_point(),
|
|
||||||
[0.0, 0.0, 0.0, 0.0],
|
|
||||||
&clipped_primitives,
|
|
||||||
&output.textures_delta,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
winit_state.handle_platform_output(
|
|
||||||
&win,
|
|
||||||
egui_ctx,
|
|
||||||
output.platform_output,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
break 'try_render;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
break 'try_render;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2222,6 +2186,97 @@ mod wgpu_integration {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
fn render_sync_viewport(
|
||||||
|
egui_ctx: &egui::Context,
|
||||||
|
mut viewport_builder: ViewportBuilder,
|
||||||
|
pair: ViewportIdPair,
|
||||||
|
render: Box<dyn FnOnce(&egui::Context) + '_>,
|
||||||
|
c_viewports: &Viewports,
|
||||||
|
c_builders: &RwLock<HashMap<ViewportId, ViewportBuilder>>,
|
||||||
|
c_time: Instant,
|
||||||
|
c_painter: &RwLock<egui_wgpu::winit::Painter>,
|
||||||
|
c_windows_id: &RwLock<HashMap<winit::window::WindowId, ViewportId>>,
|
||||||
|
) {
|
||||||
|
// Creating a new native window if is needed
|
||||||
|
if c_viewports.read().get(&pair).is_none() {
|
||||||
|
let mut _windows = c_viewports.write();
|
||||||
|
|
||||||
|
{
|
||||||
|
let builders = c_builders.read();
|
||||||
|
if viewport_builder.icon.is_none() && builders.get(&pair).is_none() {
|
||||||
|
viewport_builder.icon =
|
||||||
|
builders.get(&pair.parent).and_then(|b| b.icon.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let Window { window, state, .. } = _windows.entry(pair.this).or_insert(Window {
|
||||||
|
window: None,
|
||||||
|
state: Arc::new(RwLock::new(None)),
|
||||||
|
render: None,
|
||||||
|
parent_id: pair.parent,
|
||||||
|
});
|
||||||
|
let _ = c_builders
|
||||||
|
.write()
|
||||||
|
.entry(pair.this)
|
||||||
|
.or_insert(viewport_builder.clone());
|
||||||
|
|
||||||
|
let event_loop;
|
||||||
|
|
||||||
|
#[allow(unsafe_code)]
|
||||||
|
unsafe {
|
||||||
|
event_loop =
|
||||||
|
WINIT_EVENT_LOOP.with(|event_loop| event_loop.read().as_ref().unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::init_window(
|
||||||
|
pair.this,
|
||||||
|
&viewport_builder,
|
||||||
|
&mut c_windows_id.write(),
|
||||||
|
c_painter,
|
||||||
|
window,
|
||||||
|
state,
|
||||||
|
event_loop,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// render sync viewport
|
||||||
|
|
||||||
|
let window = c_viewports.read().get(&pair).cloned();
|
||||||
|
let Some(window) = window else { return };
|
||||||
|
let output;
|
||||||
|
let Some(winit_state) = &mut *window.state.write() else { return };
|
||||||
|
let Some(win) = window.window else { return };
|
||||||
|
let win = win.read();
|
||||||
|
let mut input = winit_state.take_egui_input(&win);
|
||||||
|
input.time = Some(c_time.elapsed().as_secs_f64());
|
||||||
|
output = egui_ctx.run(input, pair, |ctx| {
|
||||||
|
render(ctx);
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Err(err) =
|
||||||
|
pollster::block_on(c_painter.write().set_window(pair.this, Some(&win)))
|
||||||
|
{
|
||||||
|
log::error!(
|
||||||
|
"when rendering viewport_id: {}, set_window Error {err}",
|
||||||
|
pair.this
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let clipped_primitives = egui_ctx.tessellate(output.shapes);
|
||||||
|
c_painter.write().paint_and_update_textures(
|
||||||
|
pair.this,
|
||||||
|
egui_ctx.pixels_per_point(),
|
||||||
|
[0.0, 0.0, 0.0, 0.0],
|
||||||
|
&clipped_primitives,
|
||||||
|
&output.textures_delta,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
winit_state.handle_platform_output(&win, egui_ctx, output.platform_output);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitApp for WgpuWinitApp {
|
impl WinitApp for WgpuWinitApp {
|
||||||
|
|||||||
Reference in New Issue
Block a user