summaryrefslogtreecommitdiff
path: root/engine/src/renderer
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/renderer')
-rw-r--r--engine/src/renderer/blending.rs89
-rw-r--r--engine/src/renderer/main_render_pass.rs247
-rw-r--r--engine/src/renderer/object.rs136
-rw-r--r--engine/src/renderer/opengl.rs1445
-rw-r--r--engine/src/renderer/opengl/glutin_compat.rs268
-rw-r--r--engine/src/renderer/opengl/graphics_mesh.rs216
6 files changed, 0 insertions, 2401 deletions
diff --git a/engine/src/renderer/blending.rs b/engine/src/renderer/blending.rs
deleted file mode 100644
index 9ae2f82..0000000
--- a/engine/src/renderer/blending.rs
+++ /dev/null
@@ -1,89 +0,0 @@
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Config
-{
- pub source_factor: Factor,
- pub destination_factor: Factor,
- pub equation: Equation,
-}
-
-impl Default for Config
-{
- fn default() -> Self
- {
- Self {
- source_factor: Factor::One,
- destination_factor: Factor::Zero,
- equation: Equation::default(),
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-#[non_exhaustive]
-pub enum Factor
-{
- /// Factor will be the RGBA color `(0,0,0,0)`
- Zero,
-
- /// Factor will be the RGBA color `(1,1,1,1)`
- One,
-
- /// Factor will be the source color
- SrcColor,
-
- /// Factor will be the RGBA color `(1,1,1,1) - source color`
- OneMinusSrcColor,
-
- /// Factor will be the destination color
- DstColor,
-
- /// Factor will be the RGBA color `(1,1,1,1) - destination color`
- OneMinusDstColor,
-
- /// Factor will be the alpha component of the source color.
- SrcAlpha,
-
- /// Factor will be the RGBA color `(1,1,1,1) - source color alpha`
- OneMinusSrcAlpha,
-
- /// Factor will be the alpha component of the destination color.
- DstAlpha,
-
- /// Factor will be the RGBA color `(1,1,1,1) - destination color alpha`
- OneMinusDstAlpha,
-
- /// Factor will be the constant color
- ConstantColor,
-
- /// Factor will be the RGBA color `(1,1,1,1) - constant color`
- OneMinusConstantColor,
-
- /// Factor will be the alpha component of the constant color.
- ConstantAlpha,
-
- /// Factor will be the RGBA color `(1,1,1,1) - constant color alpha`
- OneMinusConstantAlpha,
-}
-
-#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
-pub enum Equation
-{
- /// The destination color and source color is added to each other in the blend
- /// function
- #[default]
- Add,
-
- /// The destination color is subtracted from the source color in the blend function
- Subtract,
-
- /// The source color is subtracted from the destination color in the blend function
- ReverseSubtract,
-
- /// The blend function will take the component-wise minimum of the destination color
- /// and the source color
- Min,
-
- /// The blend function will take the component-wise maximum of the destination color
- /// and the source color
- Max,
-}
diff --git a/engine/src/renderer/main_render_pass.rs b/engine/src/renderer/main_render_pass.rs
deleted file mode 100644
index 0926d85..0000000
--- a/engine/src/renderer/main_render_pass.rs
+++ /dev/null
@@ -1,247 +0,0 @@
-use crate::asset::Assets;
-use crate::draw_flags::{DrawFlags, NoDraw, PolygonModeConfig};
-use crate::ecs::query::term::{With, Without};
-use crate::ecs::sole::Single;
-use crate::ecs::Query;
-use crate::model::{MaterialSearchResult, Model};
-use crate::renderer::object::{Id as RendererObjectId, Store as RendererObjectStore};
-use crate::renderer::{
- BufferClearMask as RendererBufferClearMask,
- Command as RendererCommand,
- DrawMeshOptions as RendererDrawMeshOptions,
- DrawProperties as RendererDrawProperties,
- DrawPropertiesUpdateFlags as RendererDrawPropertiesUpdateFlags,
- MeshUsage as RendererMeshUsage,
- PendingShaderBindings,
- RenderPass,
- RenderPasses as RendererRenderPasses,
- SurfaceSpec,
-};
-use crate::shader::default::ASSET_LABEL as DEFAULT_SHADER_ASSET_LABEL;
-use crate::shader::{
- Context as ShaderContext,
- ModuleSource as ShaderModuleSource,
- Shader,
-};
-use crate::texture::{Texture, WHITE_1X1_ASSET_LABEL as TEXTURE_WHITE_1X1_ASSET_LABEL};
-use crate::windowing::window::Window;
-
-type RenderableEntity<'a> = (
- &'a Model,
- Option<&'a DrawFlags>,
- Option<&'a Shader>,
- Option<&'a mut PendingShaderBindings>,
-);
-
-#[tracing::instrument(skip_all)]
-pub fn add_main_render_passes(
- renderable_query: Query<RenderableEntity<'_>, (Without<NoDraw>,)>,
- window_surface_spec_query: Query<(&SurfaceSpec,), (With<Window>,)>,
- assets: Single<Assets>,
- shader_context: Single<ShaderContext>,
- mut render_passes: Single<RendererRenderPasses>,
- mut object_store: Single<RendererObjectStore>,
-)
-{
- let Some(default_shader_asset) = assets
- .get_handle_to_loaded::<ShaderModuleSource>(DEFAULT_SHADER_ASSET_LABEL.clone())
- else {
- tracing::error!("Default shader asset is not loaded");
- return;
- };
-
- let render_pass = render_passes.passes.push_front_mut(RenderPass {
- commands: Vec::with_capacity(30),
- draw_properties: RendererDrawProperties::default(),
- });
-
- for (surface_spec,) in &window_surface_spec_query {
- render_pass
- .commands
- .push(RendererCommand::MakeCurrent(surface_spec.id));
-
- let default_texture_asset = assets
- .get_handle_to_loaded::<Texture>(TEXTURE_WHITE_1X1_ASSET_LABEL.clone())
- .expect("Not possible");
-
- if !object_store.contains_maybe_pending_with_id(&RendererObjectId::Asset(
- default_texture_asset.id(),
- )) {
- object_store
- .insert_pending(RendererObjectId::Asset(default_texture_asset.id()));
-
- render_pass
- .commands
- .push(RendererCommand::CreateTexture(default_texture_asset));
- }
-
- render_pass.commands.push(RendererCommand::ClearBuffers(
- RendererBufferClearMask::COLOR | RendererBufferClearMask::DEPTH,
- ));
-
- for (model, draw_flags, shader, mut pending_shader_bindings) in &renderable_query
- {
- let shader_asset = match &shader {
- Some(shader) => &shader.asset_handle,
- None => &default_shader_asset,
- };
-
- let Some(pending_shader_bindings) = pending_shader_bindings.as_mut() else {
- continue;
- };
-
- if pending_shader_bindings.bindings.is_empty()
- && pending_shader_bindings.surface_specific_bindings.is_empty()
- {
- continue;
- }
-
- let Some(model_spec) = assets.get(&model.spec_asset) else {
- continue;
- };
-
- let Some(mesh_asset) = &model_spec.mesh_asset else {
- continue;
- };
-
- if assets.get(mesh_asset).is_none() {
- continue;
- }
-
- debug_assert!(model_spec.material_names.len() <= 1);
-
- let model_material_asset = match model_spec.find_first_material(&assets) {
- MaterialSearchResult::Found(model_material_asset) => {
- model_material_asset.clone()
- // Some(model_material_asset.clone())
- }
- MaterialSearchResult::NotFound | MaterialSearchResult::NoMaterials => {
- // MaterialSearchResult::NotFound => {
- continue;
- } // MaterialSearchResult::NoMaterials => None,
- };
-
- if !object_store.contains_maybe_pending_with_id(&RendererObjectId::Asset(
- shader_asset.id(),
- )) {
- let Some(shader_program) = shader_context.get_program(&shader_asset.id())
- else {
- tracing::error!(
- "Shader context doesn't have a program for shader asset {:?}",
- assets.get_label(&shader_asset)
- );
- continue;
- };
-
- object_store.insert_pending(RendererObjectId::Asset(shader_asset.id()));
-
- render_pass
- .commands
- .push(RendererCommand::CreateShaderProgram(
- RendererObjectId::Asset(shader_asset.id()),
- shader_program.clone(),
- ));
- }
-
- render_pass.commands.push(RendererCommand::ActivateShader(
- RendererObjectId::Asset(shader_asset.id()),
- ));
-
- let Some(model_material) = assets.get(&model_material_asset) else {
- // TODO: Handle this case since it may occur
- unreachable!();
- };
-
- for texture_asset in [
- &model_material.ambient_map,
- &model_material.diffuse_map,
- &model_material.specular_map,
- ]
- .into_iter()
- .flatten()
- {
- if !object_store.contains_maybe_pending_with_id(&RendererObjectId::Asset(
- texture_asset.id(),
- )) {
- object_store
- .insert_pending(RendererObjectId::Asset(texture_asset.id()));
-
- render_pass
- .commands
- .push(RendererCommand::CreateTexture(texture_asset.clone()));
- }
- }
-
- for (shader_binding_loc, shader_binding_val) in
- &pending_shader_bindings.bindings
- {
- render_pass.commands.push(RendererCommand::SetShaderBinding(
- shader_binding_loc.clone(),
- shader_binding_val.clone(),
- ));
- }
-
- for (shader_binding_surface_id, shader_binding_loc, shader_binding_val) in
- &pending_shader_bindings.surface_specific_bindings
- {
- if *shader_binding_surface_id != surface_spec.id {
- continue;
- }
-
- render_pass.commands.push(RendererCommand::SetShaderBinding(
- shader_binding_loc.clone(),
- shader_binding_val.clone(),
- ));
- }
-
- if let Some(draw_flags) = draw_flags.as_deref().and_then(|draw_flags| {
- if draw_flags.polygon_mode_config != PolygonModeConfig::default() {
- Some(draw_flags)
- } else {
- None
- }
- }) {
- render_pass
- .commands
- .push(RendererCommand::UpdateDrawProperties(
- RendererDrawProperties {
- polygon_mode_config: draw_flags.polygon_mode_config.clone(),
- ..Default::default()
- },
- RendererDrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG,
- ));
- }
-
- if !object_store
- .contains_maybe_pending_with_id(&RendererObjectId::Asset(mesh_asset.id()))
- {
- object_store.insert_pending(RendererObjectId::Asset(mesh_asset.id()));
-
- render_pass.commands.push(RendererCommand::CreateMesh {
- obj_id: RendererObjectId::Asset(mesh_asset.id()),
- mesh: None,
- usage: RendererMeshUsage::Static,
- });
- }
-
- render_pass.commands.push(RendererCommand::DrawMesh(
- RendererObjectId::Asset(mesh_asset.id()),
- RendererDrawMeshOptions::default(),
- ));
-
- if draw_flags.as_deref().is_some_and(|draw_flags| {
- draw_flags.polygon_mode_config != PolygonModeConfig::default()
- }) {
- render_pass
- .commands
- .push(RendererCommand::UpdateDrawProperties(
- RendererDrawProperties {
- polygon_mode_config: PolygonModeConfig::default(),
- ..Default::default()
- },
- RendererDrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG,
- ));
- }
- }
- }
-}
diff --git a/engine/src/renderer/object.rs b/engine/src/renderer/object.rs
deleted file mode 100644
index e10011d..0000000
--- a/engine/src/renderer/object.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-use std::collections::HashMap;
-use std::sync::atomic::{AtomicU64, Ordering};
-
-use crate::asset::Id as AssetId;
-use crate::ecs::Sole;
-
-pub type RawValue = u32;
-
-/// Renderer object ID.
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum Id
-{
- Asset(AssetId),
- Sequential(SequentialId),
-}
-
-impl Id
-{
- pub fn new_sequential() -> Self
- {
- static NEXT_SEQUENTIAL_ID: AtomicU64 = AtomicU64::new(0);
-
- Self::Sequential(SequentialId(
- NEXT_SEQUENTIAL_ID.fetch_add(1, Ordering::Relaxed),
- ))
- }
-
- pub fn into_asset_id(self) -> Option<AssetId>
- {
- match self {
- Self::Asset(asset_id) => Some(asset_id),
- Self::Sequential(_) => None,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct SequentialId(u64);
-
-/// Renderer object store.
-#[derive(Debug, Default, Sole)]
-pub struct Store
-{
- objects: HashMap<Id, Option<Object>>,
-}
-
-impl Store
-{
- pub fn get_obj(&self, id: &Id) -> Option<&Object>
- {
- self.objects.get(id).and_then(|obj| obj.as_ref())
- }
-
- pub fn get_texture_obj(&self, id: &Id) -> Option<&Object>
- {
- let obj = self.get_obj(id)?;
-
- if !matches!(obj.kind(), Kind::Texture) {
- return None;
- }
-
- Some(obj)
- }
-
- pub fn get_shader_program_obj(&self, id: &Id) -> Option<&Object>
- {
- let obj = self.get_obj(id)?;
-
- if !matches!(obj.kind(), Kind::ShaderProgram) {
- return None;
- }
-
- Some(obj)
- }
-
- pub fn contains_maybe_pending_with_id(&self, id: &Id) -> bool
- {
- self.objects.contains_key(id)
- }
-
- pub fn contains_non_pending_with_id(&self, id: &Id) -> bool
- {
- self.objects.get(id).and_then(|obj| obj.as_ref()).is_some()
- }
-
- pub fn insert(&mut self, id: Id, object: Object)
- {
- self.objects.insert(id, Some(object));
- }
-
- pub fn insert_pending(&mut self, id: Id)
- {
- self.objects.insert(id, None);
- }
-
- pub fn remove(&mut self, id: &Id) -> Option<Option<Object>>
- {
- self.objects.remove(id)
- }
-}
-
-/// Renderer object.
-#[derive(Debug, Clone)]
-pub struct Object
-{
- raw: RawValue,
- kind: Kind,
-}
-
-impl Object
-{
- pub fn from_raw(raw: RawValue, kind: Kind) -> Self
- {
- Self { raw, kind }
- }
-
- pub fn as_raw(&self) -> RawValue
- {
- self.raw
- }
-
- pub fn kind(&self) -> Kind
- {
- self.kind
- }
-}
-
-/// Renderer object kind.
-#[derive(Debug, Clone, Copy)]
-#[non_exhaustive]
-pub enum Kind
-{
- Texture,
- ShaderProgram,
- ImplementationSpecific,
-}
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs
deleted file mode 100644
index d77956e..0000000
--- a/engine/src/renderer/opengl.rs
+++ /dev/null
@@ -1,1445 +0,0 @@
-//! OpenGL renderer.
-
-use std::borrow::Cow;
-use std::collections::HashMap;
-
-use glutin::config::Config as GlutinConfig;
-use glutin::display::GetGlDisplay;
-use glutin::error::Error as GlutinError;
-use glutin::prelude::{GlDisplay, PossiblyCurrentGlContext};
-use glutin::surface::{
- GlSurface as _,
- Surface as GlutinSurface,
- WindowSurface as GlutinWindowSurface,
-};
-use opengl_bindings::blending::{
- configure as gl_blending_configure,
- Configuration as GlBlendingConfig,
- Equation as GlBlendingEquation,
- Factor as GlBlendingFactor,
-};
-use opengl_bindings::debug::{
- set_debug_message_callback,
- set_debug_message_control,
- MessageIdsAction,
- MessageSeverity,
- MessageSource,
- MessageType,
- SetDebugMessageControlError as GlSetDebugMessageControlError,
-};
-use opengl_bindings::misc::{
- 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,
- BufferClearMask as GlBufferClearMask,
- Capability,
-};
-use opengl_bindings::shader::{
- Error as GlShaderError,
- Kind as ShaderKind,
- Program as GlShaderProgram,
- Shader as GlShader,
- // UniformLocation as GlUniformLocation,
-};
-use opengl_bindings::texture::{
- ColorSpace as GlTextureColorSpace,
- Filtering as GlTextureFiltering,
- GenerateError as GlTextureGenerateError,
- PixelDataFormat as GlTexturePixelDataFormat,
- Texture as GlTexture,
- Wrapping as GlTextureWrapping,
-};
-use opengl_bindings::vertex_array::{
- DrawError as GlDrawError,
- PrimitiveKind,
- VertexArray,
-};
-use opengl_bindings::{
- MakeContextCurrentError as GlMakeContextCurrentError,
- MaybeCurrentContextWithFns,
-};
-use raw_window_handle::WindowHandle;
-use safer_ffi::layout::ReprC;
-use zerocopy::{Immutable, IntoBytes};
-
-use crate::asset::{Assets, Handle as AssetHandle};
-use crate::data_types::dimens::Dimens;
-use crate::ecs::actions::Actions;
-use crate::ecs::query::term::Without;
-use crate::ecs::sole::Single;
-use crate::ecs::{Component, Query, Sole};
-use crate::image::{ColorType as ImageColorType, Image};
-use crate::matrix::Matrix;
-use crate::reflection::EnumReflectionExt;
-use crate::renderer::blending::{Equation as BlendingEquation, Factor as BlendingFactor};
-use crate::renderer::object::{
- Id as RendererObjectId,
- Kind as RendererObjectKind,
- Object as RendererObject,
- RawValue as RendererObjectRawValue,
- Store as RendererObjectStore,
-};
-use crate::renderer::opengl::glutin_compat::{
- DisplayBuilder,
- Error as GlutinCompatError,
-};
-use crate::renderer::opengl::graphics_mesh::GraphicsMesh;
-use crate::renderer::{
- BufferClearMask,
- Command as RendererCommand,
- CommandQueue as RendererCommandQueue,
- DrawMeshOptions,
- DrawPropertiesUpdateFlags,
- GraphicsProperties,
- SurfaceId,
- SurfaceSpec,
- POST_RENDER_PHASE,
- RENDER_PHASE,
-};
-use crate::shader::cursor::BindingValue as ShaderBindingValue;
-use crate::shader::{
- Context as ShaderContext,
- Error as ShaderError,
- Program as ShaderProgram,
- Stage as ShaderStage,
-};
-use crate::texture::{
- Filtering as TextureFiltering,
- Properties as TextureProperties,
- Texture,
- Wrapping as TextureWrapping,
-};
-use crate::util::OptionExt;
-use crate::vector::{Vec2, Vec3};
-use crate::windowing::window::{
- Closed as WindowClosed,
- CreationAttributes as WindowCreationAttributes,
- CreationReady,
- Window,
-};
-use crate::windowing::Context as WindowingContext;
-
-mod glutin_compat;
-mod graphics_mesh;
-
-#[derive(Debug, Component)]
-struct WindowGlConfig
-{
- gl_config: GlutinConfig,
-}
-
-#[derive(Sole, Default)]
-struct GraphicsContext
-{
- gl_context: Option<MaybeCurrentContextWithFns>,
- surfaces: HashMap<SurfaceId, GraphicsContextSurface>,
- shader_uniform_buffer_objs:
- HashMap<RendererObjectId, HashMap<u32, opengl_bindings::buffer::Buffer<u8>>>,
- objects: HashMap<RendererObjectRawValue, GraphicsContextObject>,
- next_object_key: RendererObjectRawValue,
-}
-
-#[derive(Debug)]
-struct GraphicsContextSurface
-{
- window_surface: GlutinSurface<GlutinWindowSurface>,
- size: Dimens<u32>,
-}
-
-#[derive(Debug)]
-enum GraphicsContextObject
-{
- Mesh
- {
- mesh: GraphicsMesh,
- compatible_shader_program_obj_id: RendererObjectId,
- },
-}
-
-#[derive(Debug, Default)]
-#[non_exhaustive]
-pub struct Extension {}
-
-impl crate::ecs::extension::Extension for Extension
-{
- fn collect(self, mut collector: crate::ecs::extension::Collector<'_>)
- {
- collector.add_system(*RENDER_PHASE, handle_commands);
-
- collector.add_system(*POST_RENDER_PHASE, prepare_windows);
- collector.add_system(*POST_RENDER_PHASE, init_window_graphics);
-
- let _ = collector.add_sole(GraphicsContext::default());
- }
-}
-
-fn prepare_windows(
- window_query: Query<
- (Option<&Window>, &mut WindowCreationAttributes),
- (
- Without<CreationReady>,
- Without<WindowGlConfig>,
- Without<WindowClosed>,
- ),
- >,
- windowing_context: Single<WindowingContext>,
- graphics_props: Single<GraphicsProperties>,
- mut actions: Actions,
-)
-{
- let Some(display_handle) = windowing_context.display_handle() else {
- return;
- };
-
- for (window_ent_id, (window, mut window_creation_attrs)) in
- window_query.iter_with_euids()
- {
- tracing::debug!("Preparing window entity {window_ent_id} for use in rendering");
-
- let mut glutin_config_template_builder =
- glutin::config::ConfigTemplateBuilder::new();
-
- if let Some(multisampling_sample_cnt) = graphics_props.multisampling_sample_cnt {
- glutin_config_template_builder = glutin_config_template_builder
- .with_multisampling(multisampling_sample_cnt);
- }
-
- let window_handle = match window
- .as_ref()
- .map(|window| unsafe {
- windowing_context.get_window_as_handle(&window.wid())
- })
- .flatten()
- .transpose()
- {
- Ok(window_handle) => window_handle,
- Err(err) => {
- tracing::error!("Failed to get window handle: {err}");
- continue;
- }
- };
-
- let (new_window_creation_attrs, gl_config) = match DisplayBuilder::new()
- .with_window_attributes(window_creation_attrs.clone())
- .build(
- window_handle,
- &display_handle,
- glutin_config_template_builder,
- |mut cfgs| cfgs.next(),
- ) {
- Ok((new_window_creation_attrs, gl_config)) => {
- (new_window_creation_attrs, gl_config)
- }
- Err(GlutinCompatError::WindowRequired) => {
- actions.add_components(window_ent_id, (CreationReady,));
- continue;
- }
- Err(err) => {
- tracing::error!("Failed to create platform graphics display: {err}");
- continue;
- }
- };
-
- *window_creation_attrs = new_window_creation_attrs;
-
- actions.add_components(window_ent_id, (WindowGlConfig { gl_config },));
-
- if window.is_none() {
- actions.add_components(window_ent_id, (CreationReady,));
- }
- }
-}
-
-#[tracing::instrument(skip_all)]
-fn init_window_graphics(
- window_query: Query<(&Window, &WindowGlConfig), (Without<SurfaceSpec>,)>,
- windowing_context: Single<WindowingContext>,
- graphics_props: Single<GraphicsProperties>,
- mut graphics_ctx: Single<GraphicsContext>,
- mut actions: Actions,
-)
-{
- for (window_ent_id, (window, window_gl_config)) in window_query.iter_with_euids() {
- tracing::info!(
- window_entity_id=%window_ent_id,
- window_title=&*window.title,
- "Initializing graphics for window"
- );
-
- let display = window_gl_config.gl_config.display();
-
- let window_handle =
- match unsafe { windowing_context.get_window_as_handle(&window.wid()) }
- .transpose()
- {
- Ok(Some(window_handle)) => window_handle,
- Ok(None) => {
- tracing::error!(
- wid = ?window.wid(),
- entity_id = %window_ent_id,
- "Windowing context does not contain window"
- );
- continue;
- }
- Err(err) => {
- tracing::error!("Failed to get window handle: {err}");
- continue;
- }
- };
-
- let Some(window_inner_size) = window.inner_size().try_into_nonzero() else {
- tracing::error!(
- "Cannot create a surface for a window with a width/height of 0",
- );
- continue;
- };
-
- let window_surface = match unsafe {
- display.create_window_surface(
- &window_gl_config.gl_config,
- &glutin::surface::SurfaceAttributesBuilder::<
- glutin::surface::WindowSurface,
- >::new()
- .build(
- window_handle.as_raw(),
- window_inner_size.width,
- window_inner_size.height,
- ),
- )
- } {
- Ok(window_surface) => window_surface,
- Err(err) => {
- tracing::error!("Failed to create window surface: {err}");
- continue;
- }
- };
-
- let gl_context = match graphics_ctx.gl_context.get_or_try_insert_with_fn(|| {
- create_gl_context(
- &window_gl_config.gl_config,
- &graphics_props,
- window_handle,
- &window_surface,
- )
- }) {
- Ok(gl_context) => gl_context,
- Err(err) => {
- tracing::error!("Failed to create GL context: {err}");
- continue;
- }
- };
-
- if let Err(err) = gl_context.make_current(&window_surface) {
- tracing::error!("Failed to make GL context current: {err}");
- continue;
- };
-
- if let Err(err) = gl_set_viewport(
- &gl_context,
- &Vec2 { x: 0, y: 0 }.into(),
- &window.inner_size().clone().into(),
- ) {
- tracing::error!("Failed to set viewport: {err}");
- }
-
- set_enabled(
- &gl_context,
- Capability::DepthTest,
- graphics_props.depth_test,
- );
-
- set_enabled(
- &gl_context,
- Capability::MultiSample,
- graphics_props.multisampling_sample_cnt.is_some(),
- );
-
- if graphics_props.debug {
- enable(&gl_context, Capability::DebugOutput);
- enable(&gl_context, Capability::DebugOutputSynchronous);
-
- set_debug_message_callback(&gl_context, opengl_debug_message_cb);
-
- match set_debug_message_control(
- &gl_context,
- None,
- None,
- None,
- &[],
- MessageIdsAction::Disable,
- ) {
- Ok(()) => {}
- Err(GlSetDebugMessageControlError::TooManyIds {
- id_cnt: _,
- max_id_cnt: _,
- }) => {
- unreachable!() // No ids are given
- }
- }
- }
-
- let surface_id = SurfaceId::new_unique();
-
- actions.add_components(window_ent_id, (SurfaceSpec { id: surface_id },));
-
- graphics_ctx.surfaces.insert(
- surface_id,
- GraphicsContextSurface {
- window_surface,
- size: window.inner_size().clone(),
- },
- );
- }
-}
-
-#[tracing::instrument(skip_all)]
-fn handle_commands(
- mut graphics_ctx: Single<GraphicsContext>,
- mut object_store: Single<RendererObjectStore>,
- mut command_queue: Single<RendererCommandQueue>,
- assets: Single<Assets>,
- shader_context: Single<ShaderContext>,
-)
-{
- let GraphicsContext {
- ref gl_context,
- 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,
- } = *graphics_ctx;
-
- let Some(gl_context) = gl_context else {
- return;
- };
-
- let mut activated_gl_shader_program: Option<(RendererObjectId, GlShaderProgram)> =
- None;
-
- for command in command_queue.drain() {
- let tracing_span = tracing::info_span!(
- "handle_cmd",
- command = %command.get_variant_reflection().name,
- );
- 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.window_surface.is_current(gl_context.context()) {
- if let Err(err) = gl_context.context().make_not_current_in_place() {
- tracing::error!("Failed to make GL context not current: {err}");
- }
-
- if let Err(err) = gl_context.make_current_surfaceless() {
- tracing::error!("Failed to make GL context 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");
- continue;
- };
-
- if let Err(err) = gl_context.make_current(&surface.window_surface) {
- tracing::error!("Failed to make graphics context current: {err}");
- continue;
- }
-
- if let Err(err) = gl_set_viewport(
- gl_context,
- &Vec2 { x: 0, y: 0 }.into(),
- &surface.size.into(),
- ) {
- tracing::error!("Failed to set viewport: {err}");
- }
- }
- RendererCommand::SetSurfaceSize(surface_id, new_surface_size) => {
- let Some(surface) = surfaces.get_mut(&surface_id) else {
- tracing::error!(surface_id=?surface_id, "Surface does not exist");
- continue;
- };
-
- surface.size = new_surface_size;
-
- if !surface.window_surface.is_current(gl_context.context()) {
- continue;
- }
-
- if let Err(err) = gl_set_viewport(
- gl_context,
- &Vec2 { x: 0, y: 0 }.into(),
- &surface.size.into(),
- ) {
- tracing::error!("Failed to set viewport: {err}");
- }
- }
- RendererCommand::ClearBuffers(buffer_clear_mask) => {
- let mut clear_mask = GlBufferClearMask::empty();
-
- clear_mask.set(
- GlBufferClearMask::COLOR,
- buffer_clear_mask.contains(BufferClearMask::COLOR),
- );
-
- clear_mask.set(
- GlBufferClearMask::DEPTH,
- buffer_clear_mask.contains(BufferClearMask::DEPTH),
- );
-
- clear_mask.set(
- GlBufferClearMask::STENCIL,
- buffer_clear_mask.contains(BufferClearMask::STENCIL),
- );
-
- clear_buffers(gl_context, clear_mask);
- }
- RendererCommand::SwapBuffers(surface_id) => {
- let Some(surface) = surfaces.get(&surface_id) else {
- tracing::error!(surface_id=?surface_id, "Surface does not exist");
- continue;
- };
-
- if let Err(err) =
- surface.window_surface.swap_buffers(gl_context.context())
- {
- tracing::error!("Failed to swap buffers: {err}");
- }
- }
- RendererCommand::CreateShaderProgram(
- shader_program_obj_id,
- shader_program,
- ) => {
- if object_store.contains_non_pending_with_id(&shader_program_obj_id) {
- tracing::error!(
- shader_program_object_id=?shader_program_obj_id,
- shader_asset_label=?shader_program_obj_id
- .into_asset_id()
- .and_then(|asset_id| assets.get_label_by_id(asset_id)),
- "Object store already contains a object with this ID"
- );
- continue;
- }
-
- let gl_shader_program =
- match create_shader_program(gl_context, &shader_program) {
- Ok(gl_shader_program) => gl_shader_program,
- Err(err) => {
- tracing::error!("Failed to create shader program: {err}");
- continue;
- }
- };
-
- object_store.insert(
- shader_program_obj_id,
- RendererObject::from_raw(
- gl_shader_program.into_raw(),
- RendererObjectKind::ShaderProgram,
- ),
- );
- }
- RendererCommand::ActivateShader(shader_program_obj_id) => {
- let Some(shader_program_obj) =
- object_store.get_shader_program_obj(&shader_program_obj_id)
- else {
- tracing::error!("Shader object does not exist or has a wrong kind");
- continue;
- };
-
- let gl_shader_program =
- GlShaderProgram::from_raw(shader_program_obj.as_raw());
-
- gl_shader_program.activate(gl_context);
-
- activated_gl_shader_program =
- Some((shader_program_obj_id, gl_shader_program));
- }
- RendererCommand::SetShaderBinding(binding_location, binding_value) => {
- let Some((activated_gl_shader_program_obj_id, _)) =
- &activated_gl_shader_program
- else {
- tracing::error!("No shader program is activated");
- continue;
- };
-
- if let ShaderBindingValue::Texture(texture_asset) = &binding_value {
- let Some(texture_obj) = object_store
- .get_texture_obj(&RendererObjectId::Asset(texture_asset.id()))
- else {
- tracing::error!(
- "Texture {:?} does not exist in renderer object store",
- assets.get_label(texture_asset)
- );
- continue;
- };
-
- let gl_texture = GlTexture::from_raw(texture_obj.as_raw());
-
- gl_texture
- .bind_to_texture_unit(gl_context, binding_location.binding_index);
-
- // gl_shader_program.set_uniform_at_location(
- // curr_gl_ctx,
- // GlUniformLocation::from_number(
- // binding_location.binding_index as i32,
- // ),
- // &binding_location.binding_index,
- // );
-
- continue;
- }
-
- let binding_index = binding_location.binding_index;
-
- let uniform_buffer_objs = shader_uniform_buffer_objs
- .entry(*activated_gl_shader_program_obj_id)
- .or_default();
-
- let uniform_buffer =
- uniform_buffer_objs.entry(binding_index).or_insert_with(|| {
- let uniform_buf =
- opengl_bindings::buffer::Buffer::<u8>::new(gl_context);
-
- uniform_buf
- .init(
- gl_context,
- binding_location.binding_size,
- opengl_bindings::buffer::Usage::Dynamic,
- )
- .unwrap();
-
- uniform_buf
- });
-
- // The index into the uniform buffer binding target is for whatever
- // shader program is currently bound so the uniform buffer object has
- // to be re-bound so that a uniform buffer from another shader isn't
- // used
- uniform_buffer.bind_to_indexed_target(
- gl_context,
- opengl_bindings::buffer::BindingTarget::UniformBuffer,
- binding_index as u32,
- );
-
- let fvec3_value;
-
- uniform_buffer
- .store_at_byte_offset(
- gl_context,
- binding_location.byte_offset,
- match binding_value {
- ShaderBindingValue::Uint(ref value) => value.as_bytes(),
- ShaderBindingValue::Int(ref value) => value.as_bytes(),
- ShaderBindingValue::Float(ref value) => value.as_bytes(),
- ShaderBindingValue::FVec3(value) => {
- fvec3_value = CF32Vec3::from(value);
-
- fvec3_value.as_bytes()
- }
- ShaderBindingValue::FMat4x4(ref value) => {
- value.items().as_bytes()
- }
- ShaderBindingValue::Texture(_) => unreachable!(),
- },
- )
- .unwrap();
- }
- RendererCommand::CreateTexture(texture_asset) => {
- if let Err(err) = create_texture_object(
- gl_context,
- &mut object_store,
- &assets,
- &texture_asset,
- ) {
- tracing::error!("Failed to create texture object: {err}");
- }
- }
- RendererCommand::CreateMesh {
- obj_id: mesh_object_id,
- mesh,
- usage: mesh_usage,
- } => {
- if object_store.contains_non_pending_with_id(&mesh_object_id) {
- tracing::error!(
- mesh_object_id=?mesh_object_id,
- mesh_asset_label=?mesh_object_id
- .into_asset_id()
- .and_then(|asset_id| assets.get_label_by_id(asset_id)),
- "Object store already contains a object with this ID"
- );
- continue;
- }
-
- let Some((RendererObjectId::Asset(curr_shader_program_asset_id), _)) =
- &activated_gl_shader_program
- else {
- tracing::error!("No shader program is activated");
- continue;
- };
-
- let curr_shader_program_metadata = shader_context
- .get_program_metadata(curr_shader_program_asset_id)
- .expect("Not possible");
-
- let Some(vertex_desc) = &curr_shader_program_metadata.vertex_desc else {
- tracing::error!(
- "Current shader program does not have a vertex description"
- );
- continue;
- };
-
- let key = *next_graphics_ctx_object_key;
-
- let mesh = match mesh_object_id {
- RendererObjectId::Asset(mesh_asset_id) => match mesh.as_ref() {
- Some(mesh) => mesh,
- None => {
- let Some(mesh) =
- assets.get(&AssetHandle::from_id(mesh_asset_id))
- else {
- tracing::error!(
- asset_id=?mesh_asset_id,
- "Mesh asset does not exist"
- );
- continue;
- };
-
- mesh
- }
- },
- RendererObjectId::Sequential(_) => {
- let Some(mesh) = mesh.as_ref() else {
- tracing::error!(
- object_id=?mesh_object_id,
- "Object ID is sequential but no mesh data is given"
- );
- continue;
- };
-
- mesh
- }
- };
-
- let graphics_mesh = match GraphicsMesh::new(
- gl_context,
- &mesh,
- mesh_usage,
- &vertex_desc,
- ) {
- Ok(graphics_mesh) => graphics_mesh,
- Err(err) => {
- tracing::error!("Failed to create mesh: {err}");
- continue;
- }
- };
-
- graphics_ctx_objects.insert(
- key,
- GraphicsContextObject::Mesh {
- mesh: graphics_mesh,
- compatible_shader_program_obj_id: RendererObjectId::Asset(
- *curr_shader_program_asset_id,
- ),
- },
- );
-
- object_store.insert(
- mesh_object_id,
- RendererObject::from_raw(
- key,
- RendererObjectKind::ImplementationSpecific,
- ),
- );
-
- *next_graphics_ctx_object_key += 1;
- }
- RendererCommand::UpdateMesh {
- obj_id: mesh_object_id,
- mesh,
- usage: mesh_usage,
- } => {
- let Some(mesh_graphics_ctx_obj_key) = object_store
- .get_obj(&mesh_object_id)
- .map(|obj| obj.as_raw())
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- "Object store does not contain a mesh object with this ID"
- );
- continue;
- };
-
- let Some(mesh_graphics_ctx_obj) =
- graphics_ctx_objects.get_mut(&mesh_graphics_ctx_obj_key)
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- key=mesh_graphics_ctx_obj_key,
- "Graphics context does not contain a mesh object with this key"
- );
- continue;
- };
-
- #[allow(irrefutable_let_patterns)]
- let GraphicsContextObject::Mesh {
- mesh: graphics_mesh,
- compatible_shader_program_obj_id: _,
- } = mesh_graphics_ctx_obj
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- key=mesh_graphics_ctx_obj_key,
- "Graphics context object with this key is not a mesh"
- );
- continue;
- };
-
- if let Err(err) = graphics_mesh.update(gl_context, &mesh, mesh_usage) {
- tracing::error!("Failed to update mesh: {err}");
- }
- }
- RendererCommand::RemoveMesh(mesh_object_id) => {
- let Some(mesh_graphics_ctx_obj_key) = object_store
- .remove(&mesh_object_id)
- .flatten()
- .map(|obj| obj.as_raw())
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- "Object store does not contain a mesh object with this ID"
- );
- continue;
- };
-
- let Some(mesh_graphics_ctx_obj) =
- graphics_ctx_objects.remove(&mesh_graphics_ctx_obj_key)
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- key=mesh_graphics_ctx_obj_key,
- "Graphics context does not contain a mesh object with this key"
- );
- continue;
- };
-
- #[allow(irrefutable_let_patterns)]
- let GraphicsContextObject::Mesh { mesh: mut graphics_mesh, .. } =
- mesh_graphics_ctx_obj
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- key=mesh_graphics_ctx_obj_key,
- "Graphics context object with this key is not a mesh"
- );
- continue;
- };
-
- graphics_mesh.destroy(gl_context);
- }
- RendererCommand::DrawMesh(mesh_object_id, draw_mesh_opts) => {
- let Some(mesh_graphics_ctx_obj_key) = object_store
- .get_obj(&mesh_object_id)
- .map(|obj| obj.as_raw())
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- "Object store does not contain a mesh object with this ID"
- );
- continue;
- };
-
- let Some(mesh_graphics_ctx_obj) =
- graphics_ctx_objects.get(&mesh_graphics_ctx_obj_key)
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- key=mesh_graphics_ctx_obj_key,
- "Graphics context does not contain a mesh object with this key"
- );
- continue;
- };
-
- #[allow(irrefutable_let_patterns)]
- let GraphicsContextObject::Mesh {
- mesh: graphics_mesh,
- compatible_shader_program_obj_id,
- } = mesh_graphics_ctx_obj
- else {
- tracing::error!(
- object_id=?mesh_object_id,
- key=mesh_graphics_ctx_obj_key,
- "Graphics context object with this key is not a mesh"
- );
- continue;
- };
-
- if Some(compatible_shader_program_obj_id)
- != activated_gl_shader_program.as_ref().map(
- |(activated_gl_shader_program_obj_id, _)| {
- activated_gl_shader_program_obj_id
- },
- )
- {
- tracing::error!(concat!(
- "Activated shader program is not the ",
- "compatible shader program of the mesh"
- ));
- continue;
- }
-
- if let Err(err) = draw_mesh(gl_context, graphics_mesh, &draw_mesh_opts) {
- tracing::error!("Failed to draw mesh: {err}");
- };
- }
- RendererCommand::UpdateDrawProperties(
- draw_props,
- draw_props_update_flags,
- ) => {
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG)
- {
- opengl_bindings::misc::set_polygon_mode(
- gl_context,
- draw_props.polygon_mode_config.face,
- draw_props.polygon_mode_config.mode,
- );
- }
-
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::BLENDING_ENABLED)
- {
- set_enabled(
- gl_context,
- Capability::Blend,
- draw_props.blending_enabled,
- );
- }
-
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::BLENDING_CONFIG)
- {
- gl_blending_configure(
- gl_context,
- GlBlendingConfig::default()
- .with_source_factor(blending_factor_to_gl(
- draw_props.blending_config.source_factor,
- ))
- .with_destination_factor(blending_factor_to_gl(
- draw_props.blending_config.destination_factor,
- ))
- .with_equation(blending_equation_to_gl(
- draw_props.blending_config.equation,
- )),
- );
- }
-
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::DEPTH_TEST_ENABLED)
- {
- set_enabled(
- gl_context,
- Capability::DepthTest,
- draw_props.depth_test_enabled,
- );
- }
-
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::SCISSOR_TEST_ENABLED)
- {
- set_enabled(
- gl_context,
- Capability::ScissorTest,
- draw_props.scissor_test_enabled,
- );
- }
-
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::SCISSOR_BOX)
- {
- gl_define_scissor_box(
- gl_context,
- draw_props.scissor_box.lower_left_corner_pos.into(),
- draw_props
- .scissor_box
- .size
- .unwrap_or_else(|| {
- let (_, viewport_size) = gl_get_viewport(gl_context);
-
- Dimens::<u16> {
- width: viewport_size
- .width
- .try_into()
- .expect("Viewport width too large"),
- height: viewport_size
- .height
- .try_into()
- .expect("Viewport height too large"),
- }
- })
- .into(),
- );
- }
-
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::FACE_CULLING_ENABLED)
- {
- set_enabled(
- gl_context,
- Capability::CullFace,
- draw_props.face_culling_enabled,
- );
- }
- }
- }
- }
-}
-
-fn create_gl_context(
- gl_config: &GlutinConfig,
- graphics_props: &GraphicsProperties,
- window_handle: WindowHandle<'_>,
- surface: &GlutinSurface<GlutinWindowSurface>,
-) -> Result<MaybeCurrentContextWithFns, CreateGlContextError>
-{
- let display = gl_config.display();
-
- let glutin_context = unsafe {
- display.create_context(
- gl_config,
- &glutin::context::ContextAttributesBuilder::new()
- .with_debug(graphics_props.debug)
- .build(Some(window_handle.as_raw())),
- )
- }
- .map_err(CreateGlContextError::CreateGlutinContext)?;
-
- MaybeCurrentContextWithFns::new(glutin_context, &surface)
- .map_err(CreateGlContextError::MakeContextCurrent)
-}
-
-#[derive(Debug, thiserror::Error)]
-enum CreateGlContextError
-{
- #[error("Glutin context creation failed")]
- CreateGlutinContext(#[source] GlutinError),
-
- #[error("Making GL context current failed")]
- MakeContextCurrent(#[source] GlMakeContextCurrentError),
-}
-
-#[tracing::instrument(skip_all)]
-fn create_texture_object(
- curr_gl_ctx: &MaybeCurrentContextWithFns,
- renderer_object_store: &mut RendererObjectStore,
- assets: &Assets,
- texture_asset: &AssetHandle<Texture>,
-) -> Result<(), GlTextureGenerateError>
-{
- let object_id = RendererObjectId::Asset(texture_asset.id());
-
- if renderer_object_store.contains_non_pending_with_id(&object_id) {
- tracing::error!(
- texture_object_id=?object_id,
- texture_asset_label=?assets.get_label(texture_asset),
- "Renderer object store already contains object with this ID"
- );
- return Ok(());
- }
-
- let Some(texture) = assets.get(&texture_asset) else {
- tracing::error!("Texture asset is not loaded",);
- return Ok(());
- };
-
- let texture_image = match texture.image.color_type() {
- ImageColorType::Rgb8 if (texture.image.dimensions().width * 3) % 4 != 0 => {
- // The texture will be corrupted if the alignment of each horizontal line of
- // the texture pixel array is not multiple of 4.
- //
- // Read more about this at
- // wikis.khronos.org/opengl/Common_Mistakes#Texture_upload_and_pixel_reads
- //
- // To prevent this, the image is converted to RGBA8. RGBA8 images have a pixel
- // size of 4 bytes so they cannot have any alignment problems
-
- tracing::warn!(
- texture_asset = %assets
- .get_label(&texture_asset)
- .expect("Not possible"),
- concat!(
- "Converting texture image from RGB8 to RGBA8 to prevent alignment ",
- "problems. This conversion may be slow. Consider changing the ",
- "texture image's pixel format to RGBA8"
- )
- );
-
- &texture.image.to_rgba8()
- }
- _ => &texture.image,
- };
-
- renderer_object_store.insert(
- object_id,
- RendererObject::from_raw(
- create_gl_texture(curr_gl_ctx, texture_image, &texture.properties)?
- .into_raw(),
- RendererObjectKind::Texture,
- ),
- );
-
- Ok(())
-}
-
-fn draw_mesh(
- current_context: &MaybeCurrentContextWithFns,
- graphics_mesh: &GraphicsMesh,
- opts: &DrawMeshOptions,
-) -> Result<(), GlDrawError>
-{
- graphics_mesh.vertex_arr.bind(current_context);
-
- if graphics_mesh.index_buffer.is_some() {
- VertexArray::draw_elements(
- current_context,
- opengl_bindings::vertex_array::DrawElementsOptions {
- primitive_kind: PrimitiveKind::Triangles,
- element_offset: opts.element_offset,
- element_cnt: opts.element_cnt.unwrap_or(graphics_mesh.element_cnt),
- vertex_offset: opts.vertex_offset,
- },
- )?;
- } else {
- VertexArray::draw_arrays(
- current_context,
- PrimitiveKind::Triangles,
- opts.vertex_offset,
- opts.element_cnt.unwrap_or(graphics_mesh.element_cnt),
- )?;
- }
-
- Ok(())
-}
-
-fn create_gl_texture(
- current_context: &MaybeCurrentContextWithFns,
- image: &Image,
- texture_properties: &TextureProperties,
-) -> Result<GlTexture, GlTextureGenerateError>
-{
- let gl_texture = GlTexture::new(current_context);
-
- gl_texture.generate(
- current_context,
- &image.dimensions().into(),
- image.as_bytes(),
- match image.color_type() {
- ImageColorType::Rgb8 => GlTexturePixelDataFormat::Rgb8,
- ImageColorType::Rgba8 => GlTexturePixelDataFormat::Rgba8,
- _ => {
- unimplemented!();
- }
- },
- if image.color_space_is_srgb() {
- GlTextureColorSpace::Srgb
- } else {
- GlTextureColorSpace::Linear
- },
- )?;
-
- gl_texture.set_wrap(
- current_context,
- texture_wrapping_to_gl(texture_properties.wrap),
- );
-
- gl_texture.set_magnifying_filter(
- current_context,
- texture_filtering_to_gl(texture_properties.magnifying_filter),
- );
-
- gl_texture.set_minifying_filter(
- current_context,
- texture_filtering_to_gl(texture_properties.minifying_filter),
- );
-
- Ok(gl_texture)
-}
-
-fn create_shader_program(
- current_context: &MaybeCurrentContextWithFns,
- shader_program: &ShaderProgram,
-) -> Result<GlShaderProgram, CreateShaderError>
-{
- let shader_program_reflection = shader_program.reflection(0).expect("Not possible");
-
- let (vs_entry_point_index, vs_entry_point_reflection) = shader_program_reflection
- .entry_points()
- .enumerate()
- .find(|(_, entry_point)| entry_point.stage() == ShaderStage::Vertex)
- .ok_or_else(|| {
- CreateShaderError::NoShaderStageEntrypointFound(ShaderStage::Vertex)
- })?;
-
- let vertex_shader_entry_point_code = shader_program
- .get_entry_point_code(vs_entry_point_index.try_into().expect(
- "Vertex shader entry point index does not fit in 32-bit unsigned int",
- ))
- .map_err(|err| CreateShaderError::GetShaderEntryPointCodeFailed {
- err,
- stage: ShaderStage::Vertex,
- entrypoint: vs_entry_point_reflection
- .name()
- .map(|name| name.to_string().into())
- .unwrap_or("(none)".into()),
- })?;
-
- let (fs_entry_point_index, fs_entry_point_reflection) = shader_program_reflection
- .entry_points()
- .enumerate()
- .find(|(_, entry_point)| entry_point.stage() == ShaderStage::Fragment)
- .ok_or_else(|| {
- CreateShaderError::NoShaderStageEntrypointFound(ShaderStage::Fragment)
- })?;
-
- let fragment_shader_entry_point_code = shader_program
- .get_entry_point_code(fs_entry_point_index.try_into().expect(
- "Fragment shader entry point index does not fit in 32-bit unsigned int",
- ))
- .map_err(|err| CreateShaderError::GetShaderEntryPointCodeFailed {
- err,
- stage: ShaderStage::Fragment,
- entrypoint: fs_entry_point_reflection
- .name()
- .map(|name| name.to_string().into())
- .unwrap_or("(none)".into()),
- })?;
-
- let vertex_shader = GlShader::new(current_context, ShaderKind::Vertex);
-
- vertex_shader.set_source(
- current_context,
- &vertex_shader_entry_point_code.as_str().unwrap(),
- )?;
-
- vertex_shader.compile(current_context)?;
-
- let fragment_shader = GlShader::new(current_context, ShaderKind::Fragment);
-
- fragment_shader.set_source(
- current_context,
- &fragment_shader_entry_point_code.as_str().unwrap(),
- )?;
-
- fragment_shader.compile(current_context)?;
-
- let gl_shader_program = GlShaderProgram::new(current_context);
-
- gl_shader_program.attach(current_context, &vertex_shader);
- gl_shader_program.attach(current_context, &fragment_shader);
-
- gl_shader_program.link(current_context)?;
-
- Ok(gl_shader_program)
-}
-
-#[derive(Debug, thiserror::Error)]
-enum CreateShaderError
-{
- #[error(
- "Failed to get code of shader program entry point {entrypoint} of stage {stage:?}"
- )]
- GetShaderEntryPointCodeFailed
- {
- #[source]
- err: ShaderError,
- stage: ShaderStage,
- entrypoint: Cow<'static, str>,
- },
-
- #[error("No entrypoint was found for shader stage {0:?}")]
- NoShaderStageEntrypointFound(ShaderStage),
-
- #[error(transparent)]
- ShaderError(#[from] GlShaderError),
-}
-
-#[tracing::instrument(skip_all)]
-fn opengl_debug_message_cb(
- source: MessageSource,
- ty: MessageType,
- id: u32,
- severity: MessageSeverity,
- message: &str,
-)
-{
- use std::backtrace::{Backtrace, BacktraceStatus};
-
- use tracing::{event, Level};
-
- macro_rules! create_event {
- ($level: expr) => {
- event!($level, ?source, ?ty, id, ?severity, message);
- };
- }
-
- if matches!(severity, MessageSeverity::Notification) {
- return;
- }
-
- match ty {
- MessageType::Error => {
- create_event!(Level::ERROR);
-
- let backtrace = Backtrace::capture();
-
- if matches!(backtrace.status(), BacktraceStatus::Captured) {
- tracing::error!("{backtrace}");
- // event!(Level::TRACE, "{backtrace}");
- }
- }
- MessageType::Other => {
- create_event!(Level::INFO);
- }
- _ => {
- create_event!(Level::WARN);
- }
- };
-}
-
-#[inline]
-fn texture_wrapping_to_gl(texture_wrapping: TextureWrapping) -> GlTextureWrapping
-{
- match texture_wrapping {
- TextureWrapping::Repeat => GlTextureWrapping::Repeat,
- TextureWrapping::MirroredRepeat => GlTextureWrapping::MirroredRepeat,
- TextureWrapping::ClampToEdge => GlTextureWrapping::ClampToEdge,
- TextureWrapping::ClampToBorder => GlTextureWrapping::ClampToBorder,
- }
-}
-
-#[inline]
-fn texture_filtering_to_gl(texture_filtering: TextureFiltering) -> GlTextureFiltering
-{
- match texture_filtering {
- TextureFiltering::Linear => GlTextureFiltering::Linear,
- TextureFiltering::Nearest => GlTextureFiltering::Nearest,
- }
-}
-
-impl<Value: ReprC + Copy> From<Vec2<Value>> for opengl_bindings::data_types::Vec2<Value>
-{
- fn from(vec2: Vec2<Value>) -> Self
- {
- Self { x: vec2.x, y: vec2.y }
- }
-}
-
-impl<Value: ReprC + IntoBytes + Copy> From<Vec3<Value>>
- for opengl_bindings::data_types::Vec3<Value>
-{
- fn from(vec3: Vec3<Value>) -> Self
- {
- Self { x: vec3.x, y: vec3.y, z: vec3.z }
- }
-}
-
-impl<Value: ReprC + Copy> From<Matrix<Value, 4, 4>>
- for opengl_bindings::data_types::Matrix<Value, 4, 4>
-{
- fn from(matrix: Matrix<Value, 4, 4>) -> Self
- {
- Self { items: matrix.items }
- }
-}
-
-impl<Value: Copy> From<Dimens<Value>> for opengl_bindings::data_types::Dimens<Value>
-{
- fn from(dimens: Dimens<Value>) -> Self
- {
- Self {
- width: dimens.width,
- height: dimens.height,
- }
- }
-}
-
-impl From<crate::draw_flags::PolygonMode> for opengl_bindings::misc::PolygonMode
-{
- fn from(mode: crate::draw_flags::PolygonMode) -> Self
- {
- match mode {
- crate::draw_flags::PolygonMode::Point => Self::Point,
- crate::draw_flags::PolygonMode::Fill => Self::Fill,
- crate::draw_flags::PolygonMode::Line => Self::Line,
- }
- }
-}
-
-impl From<crate::draw_flags::PolygonModeFace> for opengl_bindings::misc::PolygonModeFace
-{
- fn from(face: crate::draw_flags::PolygonModeFace) -> Self
- {
- match face {
- crate::draw_flags::PolygonModeFace::Front => Self::Front,
- crate::draw_flags::PolygonModeFace::Back => Self::Back,
- crate::draw_flags::PolygonModeFace::FrontAndBack => Self::FrontAndBack,
- }
- }
-}
-
-#[derive(Debug, IntoBytes, Immutable)]
-#[repr(C)]
-pub struct CF32Vec3
-{
- x: f32,
- y: f32,
- z: f32,
-}
-
-impl From<Vec3<f32>> for CF32Vec3
-{
- fn from(src: Vec3<f32>) -> Self
- {
- Self { x: src.x, y: src.y, z: src.z }
- }
-}
-
-fn blending_factor_to_gl(blending_factor: BlendingFactor) -> GlBlendingFactor
-{
- match blending_factor {
- BlendingFactor::Zero => GlBlendingFactor::Zero,
- BlendingFactor::One => GlBlendingFactor::One,
- BlendingFactor::SrcColor => GlBlendingFactor::SrcColor,
- BlendingFactor::OneMinusSrcColor => GlBlendingFactor::OneMinusSrcColor,
- BlendingFactor::DstColor => GlBlendingFactor::DstColor,
- BlendingFactor::OneMinusDstColor => GlBlendingFactor::OneMinusDstColor,
- BlendingFactor::SrcAlpha => GlBlendingFactor::SrcAlpha,
- BlendingFactor::OneMinusSrcAlpha => GlBlendingFactor::OneMinusSrcAlpha,
- BlendingFactor::DstAlpha => GlBlendingFactor::DstAlpha,
- BlendingFactor::OneMinusDstAlpha => GlBlendingFactor::OneMinusDstAlpha,
- BlendingFactor::ConstantColor => GlBlendingFactor::ConstantColor,
- BlendingFactor::OneMinusConstantColor => GlBlendingFactor::OneMinusConstantColor,
- BlendingFactor::ConstantAlpha => GlBlendingFactor::ConstantAlpha,
- BlendingFactor::OneMinusConstantAlpha => GlBlendingFactor::OneMinusConstantAlpha,
- }
-}
-
-fn blending_equation_to_gl(blending_equation: BlendingEquation) -> GlBlendingEquation
-{
- match blending_equation {
- BlendingEquation::Add => GlBlendingEquation::Add,
- BlendingEquation::Subtract => GlBlendingEquation::Subtract,
- BlendingEquation::ReverseSubtract => GlBlendingEquation::ReverseSubtract,
- BlendingEquation::Min => GlBlendingEquation::Min,
- BlendingEquation::Max => GlBlendingEquation::Max,
- }
-}
diff --git a/engine/src/renderer/opengl/glutin_compat.rs b/engine/src/renderer/opengl/glutin_compat.rs
deleted file mode 100644
index cfd6ea7..0000000
--- a/engine/src/renderer/opengl/glutin_compat.rs
+++ /dev/null
@@ -1,268 +0,0 @@
-// Original file:
-// https://github.com/rust-windowing/glutin/blob/
-// 0433af9018febe0696c485ed9d66c40dad41f2d4/glutin-winit/src/lib.rs
-//
-// Copyright © 2022 Kirill Chibisov
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the “Software”), to deal
-// in the Software without restriction, including without limitation the rights to
-// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-// of the Software, and to permit persons to whom the Software is furnished to do
-// so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in all
-// copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
-// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-// SOFTWARE.
-
-//! This library provides helpers for cross-platform [`glutin`] bootstrapping
-//! with [`winit`].
-
-#![deny(rust_2018_idioms)]
-#![deny(rustdoc::broken_intra_doc_links)]
-#![deny(clippy::all)]
-#![deny(missing_debug_implementations)]
-#![deny(missing_docs)]
-#![cfg_attr(clippy, deny(warnings))]
-
-use glutin::config::{Config, ConfigTemplateBuilder};
-use glutin::display::{Display, DisplayApiPreference};
-use glutin::error::Error as GlutinError;
-#[cfg(x11_platform)]
-use glutin::platform::x11::X11GlConfigExt;
-use glutin::prelude::*;
-use raw_window_handle::{DisplayHandle, RawWindowHandle, WindowHandle};
-
-use crate::windowing::window::CreationAttributes as WindowCreationAttributes;
-
-#[cfg(all(not(egl_backend), not(glx_backend), not(wgl_backend), not(cgl_backend)))]
-compile_error!("Please select at least one api backend");
-
-/// The helper to perform [`Display`] creation and OpenGL platform
-/// bootstrapping with the help of [`winit`] with little to no platform specific
-/// code.
-///
-/// This is only required for the initial setup. If you want to create
-/// additional windows just use the [`finalize_window`] function and the
-/// configuration you've used either for the original window or picked with the
-/// existing [`Display`].
-///
-/// [`winit`]: winit
-/// [`Display`]: glutin::display::Display
-#[derive(Default, Debug, Clone)]
-pub struct DisplayBuilder
-{
- preference: ApiPreference,
- window_attributes: WindowCreationAttributes,
-}
-
-impl DisplayBuilder
-{
- /// Create new display builder.
- pub fn new() -> Self
- {
- Default::default()
- }
-
- /// The preference in picking the configuration.
- #[allow(dead_code)]
- pub fn with_preference(mut self, preference: ApiPreference) -> Self
- {
- self.preference = preference;
- self
- }
-
- /// The window attributes to use when building a window.
- ///
- /// By default no window is created.
- pub fn with_window_attributes(
- mut self,
- window_creation_attrs: WindowCreationAttributes,
- ) -> Self
- {
- self.window_attributes = window_creation_attrs;
- self
- }
-
- /// Initialize the OpenGL platform and create a compatible window to use
- /// with it when the [`WindowAttributes`] was passed with
- /// [`Self::with_window_attributes()`]. It's optional, since on some
- /// platforms like `Android` it is not available early on, so you want to
- /// find configuration and later use it with the [`finalize_window`].
- /// But if you don't care about such platform you can always pass
- /// [`WindowAttributes`].
- ///
- /// # Api-specific
- ///
- /// **WGL:** - [`WindowAttributes`] **must** be passed in
- /// [`Self::with_window_attributes()`] if modern OpenGL(ES) is desired,
- /// otherwise only builtin functions like `glClear` will be available.
- pub fn build<ConfigPickerFn>(
- self,
- window_handle: Option<WindowHandle<'_>>,
- display_handle: &DisplayHandle<'_>,
- template_builder: ConfigTemplateBuilder,
- config_picker_fn: ConfigPickerFn,
- ) -> Result<(WindowCreationAttributes, Config), Error>
- where
- ConfigPickerFn: FnOnce(Box<dyn Iterator<Item = Config> + '_>) -> Option<Config>,
- {
- // XXX with WGL backend window should be created first.
- let raw_window_handle = if cfg!(wgl_backend) {
- let Some(window_handle) = window_handle else {
- return Err(Error::WindowRequired);
- };
-
- Some(window_handle.as_raw())
- } else {
- None
- };
-
- let gl_display =
- create_display(display_handle, self.preference, raw_window_handle)
- .map_err(Error::CreateDisplayFailed)?;
-
- // XXX the native window must be passed to config picker when WGL is used
- // otherwise very limited OpenGL features will be supported.
- #[cfg(wgl_backend)]
- let template_builder = if let Some(raw_window_handle) = raw_window_handle {
- template_builder.compatible_with_native_window(raw_window_handle)
- } else {
- template_builder
- };
-
- let template = template_builder.build();
-
- // SAFETY: The RawWindowHandle passed on the config template
- // (when cfg(wgl_backend)) will always point to a valid object since it is
- // derived from the window_handle argument which when Some is a WindowHandle and
- // WindowHandles always point to a valid object
- let gl_configs = unsafe { gl_display.find_configs(template) }
- .map_err(Error::FindConfigsFailed)?;
-
- let picked_gl_config =
- config_picker_fn(gl_configs).ok_or(Error::NoConfigPicked)?;
-
- #[cfg(not(wgl_backend))]
- let window_attrs =
- { finalize_window_creation_attrs(self.window_attributes, &picked_gl_config) };
-
- #[cfg(wgl_backend)]
- let window_attrs = self.window_attributes;
-
- Ok((window_attrs, picked_gl_config))
- }
-}
-
-#[derive(Debug, thiserror::Error)]
-pub enum Error
-{
- #[error("Failed to create display")]
- CreateDisplayFailed(#[source] GlutinError),
-
- #[error("Failed to find configs")]
- FindConfigsFailed(#[source] GlutinError),
-
- #[error("No config was picked by config picker function")]
- NoConfigPicked,
-
- #[error("Window required for building display on current platform")]
- WindowRequired,
-}
-
-fn create_display(
- display_handle: &DisplayHandle<'_>,
- _api_preference: ApiPreference,
- _raw_window_handle: Option<RawWindowHandle>,
-) -> Result<Display, GlutinError>
-{
- #[cfg(egl_backend)]
- let _preference = DisplayApiPreference::Egl;
-
- #[cfg(glx_backend)]
- let _preference = DisplayApiPreference::Glx(Box::new(
- crate::windowing::window::platform::x11::register_xlib_error_hook,
- ));
-
- #[cfg(cgl_backend)]
- let _preference = DisplayApiPreference::Cgl;
-
- #[cfg(wgl_backend)]
- let _preference = DisplayApiPreference::Wgl(_raw_window_handle);
-
- #[cfg(all(egl_backend, glx_backend))]
- let _preference = match _api_preference {
- ApiPreference::PreferEgl => DisplayApiPreference::EglThenGlx(Box::new(
- crate::windowing::window::platform::x11::register_xlib_error_hook,
- )),
- ApiPreference::FallbackEgl => DisplayApiPreference::GlxThenEgl(Box::new(
- crate::windowing::window::platform::x11::register_xlib_error_hook,
- )),
- };
-
- #[cfg(all(wgl_backend, egl_backend))]
- let _preference = match _api_preference {
- ApiPreference::PreferEgl => DisplayApiPreference::EglThenWgl(_raw_window_handle),
- ApiPreference::FallbackEgl => {
- DisplayApiPreference::WglThenEgl(_raw_window_handle)
- }
- };
-
- let handle = display_handle.as_raw();
- unsafe { Ok(Display::new(handle, _preference)?) }
-}
-
-/// Finalize [`Window`] creation by applying the options from the [`Config`], be
-/// aware that it could remove incompatible options from the window builder like
-/// `transparency`, when the provided config doesn't support it.
-///
-/// [`Window`]: winit::window::Window
-/// [`Config`]: glutin::config::Config
-#[cfg(not(wgl_backend))]
-fn finalize_window_creation_attrs(
- mut attributes: WindowCreationAttributes,
- gl_config: &Config,
-) -> WindowCreationAttributes
-{
- // Disable transparency if the end config doesn't support it.
- if gl_config.supports_transparency() == Some(false) {
- attributes = attributes.with_transparent(false);
- }
-
- #[cfg(x11_platform)]
- let attributes = if let Some(x11_visual) = gl_config.x11_visual() {
- attributes.with_x11_visual(x11_visual.visual_id() as _)
- } else {
- attributes
- };
-
- attributes
-}
-
-/// Simplified version of the [`DisplayApiPreference`] which is used to simplify
-/// cross platform window creation.
-///
-/// To learn about platform differences the [`DisplayApiPreference`] variants.
-///
-/// [`DisplayApiPreference`]: glutin::display::DisplayApiPreference
-#[allow(dead_code)]
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
-pub enum ApiPreference
-{
- /// Prefer `EGL` over system provider like `GLX` and `WGL`.
- PreferEgl,
-
- /// Fallback to `EGL` when failed to create the system profile.
- ///
- /// This behavior is used by default. However consider using
- /// [`Self::PreferEgl`] if you don't care about missing EGL features.
- #[default]
- FallbackEgl,
-}
diff --git a/engine/src/renderer/opengl/graphics_mesh.rs b/engine/src/renderer/opengl/graphics_mesh.rs
deleted file mode 100644
index 78de80c..0000000
--- a/engine/src/renderer/opengl/graphics_mesh.rs
+++ /dev/null
@@ -1,216 +0,0 @@
-use opengl_bindings::buffer::{Buffer as GlBuffer, Usage as GlBufferUsage};
-use opengl_bindings::vertex_array::{
- AttributeFormat as GlVertexArrayAttributeFormat,
- BindVertexBufferError as GlVertexArrayBindVertexBufferError,
- DataType as GlVertexArrayDataType,
- VertexArray as GlVertexArray,
- VertexBufferSpec as GlVertexArrayVertexBufferSpec,
-};
-use opengl_bindings::MaybeCurrentContextWithFns as GlCurrentContextWithFns;
-
-use crate::mesh::{Mesh, VertexAttrType};
-use crate::renderer::MeshUsage;
-use crate::shader::VertexDescription as ShaderVertexDescription;
-
-#[derive(Debug)]
-pub struct GraphicsMesh
-{
- /// Vertex and index buffer has to live as long as the vertex array
- vertex_buffer: GlBuffer<u8>,
- pub index_buffer: Option<GlBuffer<u32>>,
- pub element_cnt: u32,
- pub vertex_arr: GlVertexArray,
-}
-
-impl GraphicsMesh
-{
- #[tracing::instrument(skip_all)]
- pub fn new(
- current_context: &GlCurrentContextWithFns,
- mesh: &Mesh,
- mesh_usage: MeshUsage,
- vertex_desc: &ShaderVertexDescription,
- ) -> Result<Self, Error>
- {
- let buffer_usage = mesh_usage_to_gl_buffer_usage(mesh_usage);
-
- let vertex_arr = GlVertexArray::new(current_context);
- let vertex_buffer = GlBuffer::new(current_context);
-
- vertex_buffer
- .store(current_context, mesh.vertex_buf().as_bytes(), buffer_usage)
- .map_err(Error::StoreVerticesFailed)?;
-
- let vertex_buf_binding_index = 0;
-
- if let Err(err) = vertex_arr.bind_vertex_buffer(
- current_context,
- vertex_buf_binding_index,
- &vertex_buffer,
- GlVertexArrayVertexBufferSpec {
- offset: 0,
- vertex_size: mesh.vertex_buf().vertex_size(),
- },
- ) {
- match err {
- GlVertexArrayBindVertexBufferError::OffsetValueTooLarge {
- value: _,
- max_value: _,
- } => unreachable!(),
- GlVertexArrayBindVertexBufferError::VertexSizeValueTooLarge {
- value,
- max_value,
- } => {
- panic!(
- "Size of vertex ({}) is too large. Must be less than {max_value}",
- value
- );
- }
- }
- }
-
- for vertex_attr_props in mesh.vertex_buf().vertex_attr_props() {
- let vertex_field_desc = vertex_desc
- .fields
- .iter()
- .find(|vertex_field_desc| {
- *vertex_field_desc.name == vertex_attr_props.name
- })
- .unwrap();
-
- let attrib_index: u32 =
- vertex_field_desc.varying_input_offset.try_into().unwrap();
-
- vertex_arr.enable_attrib(current_context, attrib_index);
-
- vertex_arr.set_attrib_format(
- current_context,
- attrib_index,
- match &vertex_attr_props.ty {
- VertexAttrType::Float32 => GlVertexArrayAttributeFormat {
- data_type: GlVertexArrayDataType::Float,
- count: 1,
- normalized: false,
- offset: vertex_attr_props.byte_offset.try_into().unwrap(),
- },
- VertexAttrType::Float32Array { length } => {
- GlVertexArrayAttributeFormat {
- data_type: GlVertexArrayDataType::Float,
- count: (*length).try_into().unwrap(),
- normalized: false,
- offset: vertex_attr_props.byte_offset.try_into().unwrap(),
- }
- }
- },
- );
-
- vertex_arr.set_attrib_vertex_buf_binding(
- current_context,
- attrib_index,
- vertex_buf_binding_index,
- );
- }
-
- if let Some(indices) = mesh.indices() {
- let index_buffer = GlBuffer::new(current_context);
-
- index_buffer
- .store(current_context, indices, buffer_usage)
- .map_err(Error::StoreIndicesFailed)?;
-
- vertex_arr.bind_element_buffer(current_context, &index_buffer);
-
- return Ok(Self {
- vertex_buffer: vertex_buffer,
- index_buffer: Some(index_buffer),
- element_cnt: indices
- .len()
- .try_into()
- .expect("Mesh index count does not fit into a 32-bit unsigned int"),
- vertex_arr,
- });
- }
-
- Ok(Self {
- vertex_buffer: vertex_buffer,
- index_buffer: None,
- element_cnt: mesh
- .vertex_buf()
- .len()
- .try_into()
- .expect("Mesh vertex count does not fit into a 32-bit unsigned int"),
- vertex_arr,
- })
- }
-
- pub fn update(
- &mut self,
- current_context: &GlCurrentContextWithFns,
- mesh: &Mesh,
- mesh_usage: MeshUsage,
- ) -> Result<(), Error>
- {
- let buffer_usage = mesh_usage_to_gl_buffer_usage(mesh_usage);
-
- self.vertex_buffer
- .store(current_context, mesh.vertex_buf().as_bytes(), buffer_usage)
- .map_err(Error::StoreVerticesFailed)?;
-
- if let Some(indices) = mesh.indices() {
- let index_buffer = self
- .index_buffer
- .get_or_insert_with(|| GlBuffer::new(current_context));
-
- index_buffer
- .store(current_context, indices, buffer_usage)
- .map_err(Error::StoreIndicesFailed)?;
-
- self.vertex_arr
- .bind_element_buffer(current_context, &index_buffer);
-
- self.element_cnt = indices
- .len()
- .try_into()
- .expect("Mesh index count does not fit into a 32-bit unsigned int");
-
- return Ok(());
- }
-
- self.element_cnt = mesh
- .vertex_buf()
- .len()
- .try_into()
- .expect("Mesh vertex count does not fit into a 32-bit unsigned int");
-
- Ok(())
- }
-
- pub fn destroy(&mut self, curr_gl_ctx: &GlCurrentContextWithFns)
- {
- self.vertex_arr.delete(curr_gl_ctx);
- self.vertex_buffer.delete(curr_gl_ctx);
-
- if let Some(index_buffer) = &self.index_buffer {
- index_buffer.delete(curr_gl_ctx);
- }
- }
-}
-
-#[derive(Debug, thiserror::Error)]
-pub enum Error
-{
- #[error("Failed to store vertices in vertex buffer")]
- StoreVerticesFailed(#[source] opengl_bindings::buffer::Error),
-
- #[error("Failed to store indices in index buffer")]
- StoreIndicesFailed(#[source] opengl_bindings::buffer::Error),
-}
-
-fn mesh_usage_to_gl_buffer_usage(mesh_usage: MeshUsage) -> GlBufferUsage
-{
- match mesh_usage {
- MeshUsage::Stream => GlBufferUsage::Stream,
- MeshUsage::Static => GlBufferUsage::Static,
- MeshUsage::Dynamic => GlBufferUsage::Dynamic,
- }
-}