diff options
| author | HampusM <hampus@hampusmat.com> | 2026-04-20 17:28:23 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-04-20 17:28:23 +0200 |
| commit | ac3fedba0239632b350a252b74e520b42912e6e2 (patch) | |
| tree | caca17a70d1a8e7a0dff9879761847b2a460827e | |
| parent | c81a754f462e7fa141743fc83b6de172f53758ae (diff) | |
| -rw-r--r-- | engine/src/renderer.rs | 60 | ||||
| -rw-r--r-- | engine/src/renderer/opengl.rs | 120 |
2 files changed, 85 insertions, 95 deletions
diff --git a/engine/src/renderer.rs b/engine/src/renderer.rs index 79f2bd5..bdbbe0c 100644 --- a/engine/src/renderer.rs +++ b/engine/src/renderer.rs @@ -4,9 +4,11 @@ use std::sync::atomic::{AtomicU64, Ordering}; use bitflags::bitflags; use ecs::entity::obtainer::Obtainer as EntityObtainer; +use ecs::event::component::Changed; use ecs::pair::{ChildOf, Pair, Wildcard}; use ecs::phase::{POST_UPDATE as POST_UPDATE_PHASE, Phase}; use ecs::sole::Single; +use ecs::system::observer::Observe; use ecs::uid::Uid; use ecs::{Component, Query, Sole, declare_entity}; @@ -25,6 +27,7 @@ use crate::shader::cursor::{ }; use crate::texture::Texture; use crate::vector::Vec2; +use crate::windowing::window::Window; pub mod blending; pub mod main_render_pass; @@ -190,6 +193,11 @@ pub enum Command RemoveMesh(ObjectId), DrawMesh(ObjectId, DrawMeshOptions), UpdateDrawProperties(DrawProperties, DrawPropertiesUpdateFlags), + SetViewport + { + size: Dimens<u32>, + position: Vec2<u32>, + }, } builder! { @@ -444,6 +452,58 @@ pub fn enqueue_commands_from_render_passes( } } +#[tracing::instrument(skip_all)] +fn handle_window_changed( + observe: Observe<Pair<Changed, Window>>, + entity_obtainer: EntityObtainer, +) +{ + for evt_match in &observe { + let window_ent = evt_match.get_ent_infallible(); + + let Some(window_surface_spec) = window_ent.get::<SurfaceSpec>() else { + continue; + }; + + let Some(renderer_ctx_ent_id) = window_ent + .get_matching_components( + Pair::builder() + .relation::<WindowUsingRendererCtx>() + .target_id(Wildcard::uid()) + .build() + .id(), + ) + .next() + .map(|comp_ref| comp_ref.id().target_entity()) + else { + continue; + }; + + let Some(renderer_ctx_ent) = entity_obtainer.get_entity(renderer_ctx_ent_id) + else { + tracing::error!("Renderer context entity does not exist"); + continue; + }; + + let Some(mut command_queue) = renderer_ctx_ent.get_mut::<CommandQueue>() else { + tracing::error!( + "Renderer context entity does not have a {} component", + type_name::<CommandQueue>() + ); + continue; + }; + + command_queue.queue.push_front(Command::SetViewport { + position: Vec2 { x: 0, y: 0 }, + size: *evt_match.get_changed_comp().inner_size(), + }); + + command_queue + .queue + .push_front(Command::MakeCurrent(window_surface_spec.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 9ba1d3a..1cd46b2 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -5,8 +5,7 @@ use std::borrow::Cow; use std::collections::HashMap; use ecs::actions::Actions; -use ecs::entity::obtainer::Obtainer as EntityObtainer; -use ecs::event::component::{Changed, Removed}; +use ecs::event::component::Removed; use ecs::pair::{Pair, Wildcard}; use ecs::query::term::Without; use ecs::sole::Single; @@ -37,12 +36,12 @@ use opengl_bindings::debug::{ use opengl_bindings::misc::{ BufferClearMask as GlBufferClearMask, Capability, - SetViewportError as GlSetViewportError, clear_buffers, define_scissor_box as gl_define_scissor_box, enable, get_viewport as gl_get_viewport, set_enabled, + set_viewport as gl_set_viewport, }; use opengl_bindings::shader::{ Error as GlShaderError, @@ -179,83 +178,12 @@ 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_changed); + collector.add_observer(super::handle_window_changed); collector.add_observer(handle_window_removed); } } #[tracing::instrument(skip_all)] -fn handle_window_changed( - observe: Observe<Pair<Changed, Window>>, - entity_obtainer: EntityObtainer, -) -{ - for evt_match in &observe { - let window_ent = evt_match.get_ent_infallible(); - - tracing::trace!( - new_state = ?evt_match.get_changed_comp(), - "Handling window change" - ); - - let Some(surface_spec) = window_ent.get::<SurfaceSpec>() else { - continue; - }; - - let Some(renderer_ctx_ent_id) = window_ent - .get_matching_components( - Pair::builder() - .relation::<WindowUsingRendererCtx>() - .target_id(Wildcard::uid()) - .build() - .id(), - ) - .next() - .map(|comp_ref| comp_ref.id().target_entity()) - else { - continue; - }; - - let Some(renderer_ctx_ent) = entity_obtainer.get_entity(renderer_ctx_ent_id) - else { - tracing::error!("Renderer context entity does not exist"); - continue; - }; - - let Some(graphics_context) = renderer_ctx_ent.get::<GraphicsContext>() else { - tracing::error!( - "Renderer context entity does not have a GraphicsContext component" - ); - continue; - }; - - let Some(surface) = graphics_context.surfaces.get(&surface_spec.id) else { - tracing::error!( - window_entity_id = %window_ent.uid(), - "Surface specified by window entity's {} component does not exist", - type_name::<SurfaceSpec>() - ); - continue; - }; - - let Ok(current_graphics_context) = - graphics_context.gl_context.make_current(surface) - else { - tracing::error!("Failed to make graphics context current"); - continue; - }; - - if let Err(err) = set_viewport( - ¤t_graphics_context, - Vec2::default(), - evt_match.get_changed_comp().inner_size(), - ) { - tracing::error!("Failed to set viewport: {err}"); - } - } -} - -#[tracing::instrument(skip_all)] fn handle_window_removed(observe: Observe<Pair<Removed, Window>>, mut actions: Actions) { for evt_match in &observe { @@ -488,9 +416,11 @@ fn init_window_graphics( continue; }; - if let Err(err) = - set_viewport(&curr_gl_context, Vec2 { x: 0, y: 0 }, window.inner_size()) - { + if let Err(err) = gl_set_viewport( + &curr_gl_context, + &Vec2 { x: 0, y: 0 }.into(), + &window.inner_size().clone().into(), + ) { tracing::error!("Failed to set viewport: {err}"); } @@ -1177,6 +1107,23 @@ fn handle_commands( ); } } + RendererCommand::SetViewport { + size: viewport_size, + position: viewport_position, + } => { + let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { + tracing::error!("No GL context is current"); + continue; + }; + + if let Err(err) = gl_set_viewport( + curr_gl_ctx, + &viewport_position.into(), + &viewport_size.into(), + ) { + tracing::error!("Failed to set viewport: {err}"); + } + } } } } @@ -1244,23 +1191,6 @@ fn create_texture_object( Ok(()) } -fn set_viewport( - current_context: &CurrentContextWithFns<'_>, - position: Vec2<u32>, - size: &Dimens<u32>, -) -> Result<(), GlSetViewportError> -{ - let position = - opengl_bindings::data_types::Vec2::<u32> { x: position.x, y: position.y }; - - let size = opengl_bindings::data_types::Dimens::<u32> { - width: size.width, - height: size.height, - }; - - opengl_bindings::misc::set_viewport(current_context, &position, &size) -} - fn draw_mesh( current_context: &CurrentContextWithFns<'_>, graphics_mesh: &GraphicsMesh, |
