diff options
Diffstat (limited to 'adapters/fparkan-render-gl')
| -rw-r--r-- | adapters/fparkan-render-gl/Cargo.toml | 12 | ||||
| -rw-r--r-- | adapters/fparkan-render-gl/src/lib.rs | 242 |
2 files changed, 0 insertions, 254 deletions
diff --git a/adapters/fparkan-render-gl/Cargo.toml b/adapters/fparkan-render-gl/Cargo.toml deleted file mode 100644 index 4fcf403..0000000 --- a/adapters/fparkan-render-gl/Cargo.toml +++ /dev/null @@ -1,12 +0,0 @@ -[package] -name = "fparkan-render-gl" -version.workspace = true -edition.workspace = true -license.workspace = true -repository.workspace = true - -[dependencies] -fparkan-render = { path = "../../crates/fparkan-render" } - -[lints] -workspace = true diff --git a/adapters/fparkan-render-gl/src/lib.rs b/adapters/fparkan-render-gl/src/lib.rs deleted file mode 100644 index 94bf761..0000000 --- a/adapters/fparkan-render-gl/src/lib.rs +++ /dev/null @@ -1,242 +0,0 @@ -#![forbid(unsafe_code)] -//! OpenGL render adapter boundary stubs behind safe `FParkan` render ports. - -use fparkan_render::{ - canonical_capture, FrameOutput, RenderBackend, RenderCommandList, RenderError, -}; - -/// Portable OpenGL profile requested by the game composition root. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum GlProfile { - /// Desktop OpenGL 3.3 Core. - DesktopCore33, - /// OpenGL ES 2.0 portable baseline. - Gles2, -} - -/// Shader stage used in diagnostics. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum ShaderStage { - /// Vertex shader. - Vertex, - /// Fragment shader. - Fragment, -} - -/// Shader compilation diagnostic surfaced by the adapter. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct ShaderCompileError { - /// Requested GL profile. - pub profile: GlProfile, - /// Shader stage. - pub stage: ShaderStage, - /// Backend compiler log. - pub log: String, -} - -impl std::fmt::Display for ShaderCompileError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!( - f, - "{:?} {:?} shader compile failed: {}", - self.profile, self.stage, self.log - ) - } -} - -impl std::error::Error for ShaderCompileError {} - -/// Adapter capabilities compiled into this package. -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct GlAdapterCapabilities { - /// Supported profiles in preference order. - pub profiles: Vec<GlProfile>, - /// Whether adapter-owned code is free of `unsafe`. - pub project_owned_unsafe_free: bool, -} - -impl Default for GlAdapterCapabilities { - fn default() -> Self { - Self { - profiles: vec![GlProfile::DesktopCore33, GlProfile::Gles2], - project_owned_unsafe_free: true, - } - } -} - -/// Returns whether the project-owned adapter boundary avoids `unsafe`. -#[must_use] -pub fn project_owned_layer_unsafe_free() -> bool { - GlAdapterCapabilities::default().project_owned_unsafe_free -} - -/// Validates shader source through the adapter diagnostic contract. -/// -/// # Errors -/// -/// Returns [`ShaderCompileError`] when the source is empty or contains a -/// deterministic synthetic failure marker. -pub fn compile_shader_source( - profile: GlProfile, - stage: ShaderStage, - source: &str, -) -> Result<(), ShaderCompileError> { - if source.trim().is_empty() { - return Err(ShaderCompileError { - profile, - stage, - log: "empty shader source".to_string(), - }); - } - if source.contains("#error") { - return Err(ShaderCompileError { - profile, - stage, - log: "synthetic compiler failure marker".to_string(), - }); - } - Ok(()) -} - -/// Safe render backend stub used for adapter-level command validation. -/// -/// A concrete OpenGL implementation can be injected behind the same -/// [`RenderBackend`] port once an audited safe GL facade is selected. This type -/// keeps the project-owned adapter API executable without introducing local FFI. -#[derive(Clone, Debug)] -pub struct SafeGlCommandBackend { - profile: GlProfile, - captures: Vec<Vec<u8>>, -} - -impl SafeGlCommandBackend { - /// Creates a backend proof for a requested GL profile. - #[must_use] - pub fn new(profile: GlProfile) -> Self { - Self { - profile, - captures: Vec::new(), - } - } - - /// Active GL profile. - #[must_use] - pub fn profile(&self) -> GlProfile { - self.profile - } - - /// Deterministic command captures produced by executed frames. - #[must_use] - pub fn captures(&self) -> &[Vec<u8>] { - &self.captures - } -} - -impl RenderBackend for SafeGlCommandBackend { - fn execute(&mut self, commands: &RenderCommandList) -> Result<FrameOutput, RenderError> { - self.captures.push(canonical_capture(commands)?); - Ok(FrameOutput) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use fparkan_render::{ - DrawCommand, DrawId, GpuMaterialId, GpuMeshId, IndexRange, RenderCommand, RenderPhase, - }; - - #[test] - fn adapter_boundary_is_project_owned_unsafe_free() { - assert!(project_owned_layer_unsafe_free()); - assert_eq!(GlAdapterCapabilities::default().profiles.len(), 2); - } - - #[test] - fn backend_executes_and_captures_commands() -> Result<(), RenderError> { - let mut backend = SafeGlCommandBackend::new(GlProfile::Gles2); - let commands = RenderCommandList { - commands: vec![ - RenderCommand::BeginFrame, - RenderCommand::Draw(DrawCommand { - id: DrawId(7), - phase: RenderPhase::Opaque, - object_id: None, - mesh: GpuMeshId(11), - material: GpuMaterialId(13), - transform: [0.0; 16], - range: IndexRange { start: 0, count: 3 }, - stable_order: 17, - }), - RenderCommand::EndFrame, - ], - }; - - backend.execute(&commands)?; - - assert_eq!(backend.profile(), GlProfile::Gles2); - assert_eq!(backend.captures().len(), 1); - Ok(()) - } - - #[test] - fn desktop_gl33_triangle_command_capture() -> Result<(), RenderError> { - let mut backend = SafeGlCommandBackend::new(GlProfile::DesktopCore33); - let commands = triangle_commands(); - - backend.execute(&commands)?; - - assert_eq!(backend.profile(), GlProfile::DesktopCore33); - assert_eq!( - backend.captures(), - &[b"B\nD,Opaque,7,11,13,17\nE\n".to_vec()] - ); - Ok(()) - } - - #[test] - fn gles2_triangle_command_capture() -> Result<(), RenderError> { - let mut backend = SafeGlCommandBackend::new(GlProfile::Gles2); - let commands = triangle_commands(); - - backend.execute(&commands)?; - - assert_eq!(backend.profile(), GlProfile::Gles2); - assert_eq!( - backend.captures(), - &[b"B\nD,Opaque,7,11,13,17\nE\n".to_vec()] - ); - Ok(()) - } - - #[test] - fn shader_compile_failure_diagnostic_contains_profile_and_log() { - let err = compile_shader_source(GlProfile::Gles2, ShaderStage::Fragment, "#error") - .expect_err("shader failure"); - - assert_eq!(err.profile, GlProfile::Gles2); - assert_eq!(err.stage, ShaderStage::Fragment); - assert!(err.log.contains("synthetic compiler failure")); - assert!(err.to_string().contains("Gles2")); - assert!(err.to_string().contains("synthetic compiler failure")); - } - - fn triangle_commands() -> RenderCommandList { - RenderCommandList { - commands: vec![ - RenderCommand::BeginFrame, - RenderCommand::Draw(DrawCommand { - id: DrawId(7), - phase: RenderPhase::Opaque, - object_id: None, - mesh: GpuMeshId(11), - material: GpuMaterialId(13), - transform: [0.0; 16], - range: IndexRange { start: 0, count: 3 }, - stable_order: 17, - }), - RenderCommand::EndFrame, - ], - } - } -} |
