use crate::error::{FilterChainError, Result};
use crate::filter_chain::chain::FilterChainImpl;
use crate::filter_chain::inner::FilterChainDispatch;
use crate::options::{FilterChainOptionsGL, FrameOptionsGL};
use crate::GLImage;
use librashader_presets::{ShaderFeatures, ShaderPreset};
use std::panic::catch_unwind;
use std::path::Path;
use std::sync::Arc;
mod chain;
mod inner;
mod parameters;
pub(crate) use chain::{FilterCommon, GLCaps};
use librashader_common::Viewport;
use librashader_pack::ShaderPresetPack;
use librashader_presets::context::VideoDriver;
pub struct FilterChainGL {
pub(in crate::filter_chain) filter: FilterChainDispatch,
}
impl FilterChainGL {
pub unsafe fn load_from_preset(
preset: ShaderPreset,
ctx: Arc<glow::Context>,
options: Option<&FilterChainOptionsGL>,
) -> Result<Self> {
let preset = ShaderPresetPack::load_from_preset::<FilterChainError>(preset)?;
unsafe { Self::load_from_pack(preset, ctx, options) }
}
pub unsafe fn load_from_pack(
preset: ShaderPresetPack,
ctx: Arc<glow::Context>,
options: Option<&FilterChainOptionsGL>,
) -> Result<Self> {
let result = catch_unwind(|| {
if options.is_some_and(|options| options.use_dsa) {
return Ok(Self {
filter: FilterChainDispatch::DirectStateAccess(unsafe {
FilterChainImpl::load_from_pack(preset, ctx, options)?
}),
});
}
Ok(Self {
filter: FilterChainDispatch::Compatibility(unsafe {
FilterChainImpl::load_from_pack(preset, ctx, options)?
}),
})
});
result.unwrap_or_else(|_| Err(FilterChainError::GLLoadError))
}
pub unsafe fn load_from_path(
path: impl AsRef<Path>,
features: ShaderFeatures,
ctx: Arc<glow::Context>,
options: Option<&FilterChainOptionsGL>,
) -> Result<Self> {
let preset =
ShaderPreset::try_parse_with_driver_context(path, features, VideoDriver::GlCore)?;
unsafe { Self::load_from_preset(preset, ctx, options) }
}
pub unsafe fn frame(
&mut self,
input: &GLImage,
viewport: &Viewport<&GLImage>,
frame_count: usize,
options: Option<&FrameOptionsGL>,
) -> Result<()> {
match &mut self.filter {
FilterChainDispatch::DirectStateAccess(p) => unsafe {
p.frame(frame_count, viewport, input, options)
},
FilterChainDispatch::Compatibility(p) => unsafe {
p.frame(frame_count, viewport, input, options)
},
}
}
pub fn get_context(&self) -> &Arc<glow::Context> {
match &self.filter {
FilterChainDispatch::DirectStateAccess(p) => &p.common.context,
FilterChainDispatch::Compatibility(p) => &p.common.context,
}
}
}