summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-04-22 16:26:19 +0200
committerHampusM <hampus@hampusmat.com>2026-04-22 16:26:19 +0200
commit0b99ad032ed63253aa3f534bcf8eee39a12c0388 (patch)
treebe3137fc0ca946dc0b4728853aabe7dd70446aca
parent4c378d7173fae64ea77c6ead7258c30ff64f2789 (diff)
feat(engine): make opengl renderer module not handle window removals
-rw-r--r--engine/src/renderer.rs63
-rw-r--r--engine/src/renderer/opengl.rs75
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");