summaryrefslogtreecommitdiff
path: root/engine/src/rendering/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/rendering/opengl')
-rw-r--r--engine/src/rendering/opengl/glutin_compat.rs268
-rw-r--r--engine/src/rendering/opengl/graphics_mesh.rs216
2 files changed, 0 insertions, 484 deletions
diff --git a/engine/src/rendering/opengl/glutin_compat.rs b/engine/src/rendering/opengl/glutin_compat.rs
deleted file mode 100644
index cfd6ea7..0000000
--- a/engine/src/rendering/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/rendering/opengl/graphics_mesh.rs b/engine/src/rendering/opengl/graphics_mesh.rs
deleted file mode 100644
index 4933197..0000000
--- a/engine/src/rendering/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::rendering::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,
- }
-}