diff options
| author | HampusM <hampus@hampusmat.com> | 2026-04-22 16:26:19 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-04-22 16:26:19 +0200 |
| commit | 0b99ad032ed63253aa3f534bcf8eee39a12c0388 (patch) | |
| tree | be3137fc0ca946dc0b4728853aabe7dd70446aca | |
| parent | 4c378d7173fae64ea77c6ead7258c30ff64f2789 (diff) | |
feat(engine): make opengl renderer module not handle window removals
| -rw-r--r-- | engine/src/renderer.rs | 63 | ||||
| -rw-r--r-- | engine/src/renderer/opengl.rs | 75 |
2 files changed, 84 insertions, 54 deletions
diff --git a/engine/src/renderer.rs b/engine/src/renderer.rs index 970a241..14b8d49 100644 --- a/engine/src/renderer.rs +++ b/engine/src/renderer.rs @@ -3,8 +3,9 @@ use std::collections::VecDeque; use std::sync::atomic::{AtomicU64, Ordering}; use bitflags::bitflags; +use ecs::actions::Actions; use ecs::entity::obtainer::Obtainer as EntityObtainer; -use ecs::event::component::Changed; +use ecs::event::component::{Changed, Removed}; use ecs::pair::{ChildOf, Pair, Wildcard}; use ecs::phase::{POST_UPDATE as POST_UPDATE_PHASE, Phase}; use ecs::sole::Single; @@ -97,6 +98,7 @@ impl ecs::extension::Extension for Extension collector.add_system(*RENDER_PHASE, enqueue_commands_from_render_passes); collector.add_observer(handle_window_changed); + collector.add_observer(handle_window_removed); opengl::Extension::default().collect(collector); } @@ -212,6 +214,7 @@ pub struct RenderPass #[non_exhaustive] pub enum Command { + RemoveSurface(SurfaceId), MakeCurrent(SurfaceId), ClearBuffers(BufferClearMask), SwapBuffers(SurfaceId), @@ -550,6 +553,64 @@ fn handle_window_changed( } } +#[tracing::instrument(skip_all)] +fn handle_window_removed(observe: Observe<Pair<Removed, Window>>, mut actions: Actions) +{ + for evt_match in &observe { + let window_ent_id = evt_match.id(); + + let window_ent = evt_match.get_ent_infallible(); + + tracing::debug!( + entity_id = %window_ent_id, + title = %evt_match.get_removed_comp().title, + "Handling removal of window" + ); + + let Some(window_surface_spec) = window_ent.get::<SurfaceSpec>() else { + continue; + }; + + actions.remove_comps::<(SurfaceSpec,)>(window_ent_id); + + let Some(with_renderer_ctx_pair) = window_ent + .get_first_wildcard_pair_match::<WindowUsingRendererCtx, Wildcard>() + else { + tracing::warn!( + "Window entity is missing a ({}, *) pair", + type_name::<WindowUsingRendererCtx>() + ); + continue; + }; + + let Some(renderer_context_ent) = with_renderer_ctx_pair.get_target_ent() else { + continue; + }; + + let Some(mut command_queue) = renderer_context_ent.get_mut::<CommandQueue>() + else { + continue; + }; + + command_queue + .queue + .push_front(Command::RemoveSurface(window_surface_spec.id)); + + let renderer_context_ent_id = with_renderer_ctx_pair.id().target_entity(); + + actions.remove_components( + renderer_context_ent_id, + [Pair::builder() + .relation::<CtxUsedByWindow>() + .target_id(window_ent_id) + .build() + .id()], + ); + + actions.remove_components(window_ent_id, [with_renderer_ctx_pair.id()]); + } +} + // TODO: Maybe move this struct to somewhere more appropriate #[derive(Default, Clone, Component)] pub struct PendingShaderBindings diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index d744da4..860416e 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -1,18 +1,15 @@ //! OpenGL renderer. -use std::any::type_name; use std::borrow::Cow; use std::collections::HashMap; use ecs::actions::Actions; -use ecs::event::component::Removed; -use ecs::pair::{Pair, Wildcard}; +use ecs::pair::Pair; use ecs::query::term::Without; use ecs::sole::Single; -use ecs::system::observer::Observe; use ecs::{Component, Query}; use glutin::display::GetGlDisplay; -use glutin::prelude::GlDisplay; +use glutin::prelude::{GlDisplay, PossiblyCurrentGlContext}; use glutin::surface::{ GlSurface, Surface as GlutinSurface, @@ -163,53 +160,6 @@ impl ecs::extension::Extension for Extension collector.add_system(*POST_RENDER_PHASE, prepare_windows); collector.add_system(*POST_RENDER_PHASE, init_window_graphics); - - collector.add_observer(handle_window_removed); - } -} - -#[tracing::instrument(skip_all)] -fn handle_window_removed(observe: Observe<Pair<Removed, Window>>, mut actions: Actions) -{ - for evt_match in &observe { - let window_ent_id = evt_match.id(); - - let window_ent = evt_match.get_ent_infallible(); - - tracing::debug!( - entity_id = %window_ent_id, - title = %evt_match.get_removed_comp().title, - "Handling removal of window" - ); - - actions.remove_comps::<(SurfaceSpec, WindowGlConfig)>(window_ent_id); - - let Some(with_renderer_ctx_pair) = window_ent - .get_first_wildcard_pair_match::<WindowUsingRendererCtx, Wildcard>() - else { - tracing::warn!( - "Window entity is missing a ({}, *) pair", - type_name::<WindowUsingRendererCtx>() - ); - continue; - }; - - let renderer_context_ent_id = with_renderer_ctx_pair.id().target_entity(); - - actions.remove_comps::<(GraphicsContext, RendererObjectStore)>( - renderer_context_ent_id, - ); - - actions.remove_components( - renderer_context_ent_id, - [Pair::builder() - .relation::<RendererCtxUsedByWindow>() - .target_id(window_ent_id) - .build() - .id()], - ); - - actions.remove_components(window_ent_id, [with_renderer_ctx_pair.id()]); } } @@ -480,7 +430,7 @@ fn handle_commands( { let GraphicsContext { ref gl_context, - ref surfaces, + ref mut surfaces, ref mut shader_uniform_buffer_objs, objects: ref mut graphics_ctx_objects, next_object_key: ref mut next_graphics_ctx_object_key, @@ -496,6 +446,25 @@ fn handle_commands( let _tracing_span_enter = tracing_span.enter(); match command { + RendererCommand::RemoveSurface(surface_id) => { + let Some(surface) = surfaces.remove(&surface_id) else { + tracing::error!(surface_id=?surface_id, "Surface does not exist"); + continue; + }; + + if surface.is_current(gl_context.context()) { + opt_curr_gl_ctx = None; + + if let Err(err) = gl_context.context().make_not_current_in_place() + { + tracing::error!( + "Failed to make GL context not current: {err}" + ); + } + } + + drop(surface); + } RendererCommand::MakeCurrent(surface_id) => { let Some(surface) = surfaces.get(&surface_id) else { tracing::error!(surface_id=?surface_id, "Surface does not exist"); |
