diff --git a/include/librashader.h b/include/librashader.h index 38187d2..e38c054 100644 --- a/include/librashader.h +++ b/include/librashader.h @@ -644,16 +644,11 @@ typedef int32_t (*PFN_libra_error_write)(libra_error_t error, char **out); /// Function pointer definition for libra_error_free_string typedef int32_t (*PFN_libra_error_free_string)(char **out); -#if defined(LIBRA_RUNTIME_OPENGL) -/// Function pointer definition for -///libra_gl_init_context -typedef libra_error_t (*PFN_libra_gl_init_context)(libra_gl_loader_t loader); -#endif - #if defined(LIBRA_RUNTIME_OPENGL) /// Function pointer definition for ///libra_gl_filter_chain_create typedef libra_error_t (*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t *preset, + libra_gl_loader_t loader, const struct filter_chain_gl_opt_t *options, libra_gl_filter_chain_t *out); #endif @@ -1197,20 +1192,6 @@ libra_error_t libra_preset_get_runtime_params(libra_shader_preset_t *preset, /// in undefined behaviour. libra_error_t libra_preset_free_runtime_params(struct libra_preset_param_list_t preset); -#if defined(LIBRA_RUNTIME_OPENGL) -/// Initialize the OpenGL Context for librashader. -/// -/// This only has to be done once throughout the lifetime of the application, -/// unless for whatever reason you switch OpenGL loaders mid-flight. -/// -/// ## Safety -/// Attempting to create a filter chain will fail if the GL context is not initialized. -/// -/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter -/// chain objects, and drawing with them causes immediate undefined behaviour. -libra_error_t libra_gl_init_context(libra_gl_loader_t loader); -#endif - #if defined(LIBRA_RUNTIME_OPENGL) /// Create the filter chain given the shader preset. /// @@ -1222,6 +1203,7 @@ libra_error_t libra_gl_init_context(libra_gl_loader_t loader); /// - `options` must be either null, or valid and aligned. /// - `out` must be aligned, but may be null, invalid, or uninitialized. libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset, + libra_gl_loader_t loader, const struct filter_chain_gl_opt_t *options, libra_gl_filter_chain_t *out); #endif diff --git a/include/librashader_ld.h b/include/librashader_ld.h index 6d42635..dcf1fd2 100644 --- a/include/librashader_ld.h +++ b/include/librashader_ld.h @@ -194,12 +194,9 @@ libra_error_t __librashader__noop_preset_free_runtime_params( return NULL; } #if defined(LIBRA_RUNTIME_OPENGL) -libra_error_t __librashader__noop_gl_init_context(libra_gl_loader_t loader) { - return NULL; -} - libra_error_t __librashader__noop_gl_filter_chain_create( - libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options, + libra_shader_preset_t *preset, libra_gl_loader_t loader, + const struct filter_chain_gl_opt_t *options, libra_gl_filter_chain_t *out) { *out = NULL; return NULL; @@ -799,17 +796,6 @@ typedef struct libra_instance_t { PFN_libra_error_free_string error_free_string; #if defined(LIBRA_RUNTIME_OPENGL) - /// Initialize the OpenGL Context for librashader. - /// - /// ## Safety - /// Attempting to create a filter chain will fail if the context is not - /// initialized. - /// - /// Reinitializing the OpenGL context with a different loader immediately - /// invalidates previous filter chain objects, and drawing with them causes - /// immediate undefined behaviour. - PFN_libra_gl_init_context gl_init_context; - /// Create the filter chain given the shader preset. /// /// The shader preset is immediately invalidated and must be recreated after @@ -1445,7 +1431,6 @@ libra_instance_t __librashader_make_null_instance(void) { instance.error_free_string = __librashader__noop_error_free_string; #if defined(LIBRA_RUNTIME_OPENGL) - instance.gl_init_context = __librashader__noop_gl_init_context; instance.gl_filter_chain_create = __librashader__noop_gl_filter_chain_create; instance.gl_filter_chain_frame = __librashader__noop_gl_filter_chain_frame; @@ -1620,7 +1605,6 @@ libra_instance_t librashader_load_instance(void) { _LIBRASHADER_ASSIGN(librashader, instance, error_free_string); #if defined(LIBRA_RUNTIME_OPENGL) - _LIBRASHADER_ASSIGN(librashader, instance, gl_init_context); _LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_create); _LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_frame); _LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_free); diff --git a/librashader-capi/src/runtime/gl/filter_chain.rs b/librashader-capi/src/runtime/gl/filter_chain.rs index 3ad895d..6f1cfec 100644 --- a/librashader-capi/src/runtime/gl/filter_chain.rs +++ b/librashader-capi/src/runtime/gl/filter_chain.rs @@ -7,12 +7,14 @@ use librashader::runtime::gl::{ FilterChain, FilterChainOptions, FrameOptions, GLFramebuffer, GLImage, }; use std::ffi::CStr; -use std::ffi::{c_char, c_void, CString}; +use std::ffi::{c_char, c_void}; use std::mem::MaybeUninit; +use std::num::NonZeroU32; use std::ptr::NonNull; use std::slice; - +use std::sync::Arc; use crate::LIBRASHADER_API_VERSION; +use librashader::runtime::gl::error::FilterChainError; use librashader::runtime::FilterChainParameters; use librashader::runtime::{Size, Viewport}; @@ -49,8 +51,12 @@ pub struct libra_output_framebuffer_gl_t { impl From for GLImage { fn from(value: libra_source_image_gl_t) -> Self { + let handle = NonZeroU32::try_from(value.handle) + .ok() + .map(glow::NativeTexture); + GLImage { - handle: value.handle, + handle, format: value.format, size: Size::new(value.width, value.height), } @@ -108,27 +114,6 @@ config_struct! { } } -extern_fn! { - /// Initialize the OpenGL Context for librashader. - /// - /// This only has to be done once throughout the lifetime of the application, - /// unless for whatever reason you switch OpenGL loaders mid-flight. - /// - /// ## Safety - /// Attempting to create a filter chain will fail if the GL context is not initialized. - /// - /// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter - /// chain objects, and drawing with them causes immediate undefined behaviour. - raw fn libra_gl_init_context(loader: libra_gl_loader_t) { - gl::load_with(|s| unsafe { - let proc_name = CString::new(s).unwrap_unchecked(); - loader(proc_name.as_ptr()) - }); - - LibrashaderError::ok() - } -} - extern_fn! { /// Create the filter chain given the shader preset. /// @@ -141,6 +126,7 @@ extern_fn! { /// - `out` must be aligned, but may be null, invalid, or uninitialized. fn libra_gl_filter_chain_create( preset: *mut libra_shader_preset_t, + loader: libra_gl_loader_t, options: *const MaybeUninit, out: *mut MaybeUninit ) { @@ -160,7 +146,11 @@ extern_fn! { let options = options.map(FromUninit::from_uninit); unsafe { - let chain = FilterChain::load_from_preset(*preset, options.as_ref())?; + let context = glow::Context::from_loader_function_cstr( + |proc_name| loader(proc_name.as_ptr())); + + let chain = FilterChain::load_from_preset(Arc::new(context), + *preset, options.as_ref())?; out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( chain, @@ -206,8 +196,19 @@ extern_fn! { }; let opt = opt.map(FromUninit::from_uninit); - let framebuffer = GLFramebuffer::new_from_raw(out.texture, out.fbo, out.format, - Size::new(out.width, out.height), 1); + + let texture = NonZeroU32::try_from(out.texture) + .ok() + .map(glow::NativeTexture); + + let fbo = NonZeroU32::try_from(out.fbo) + .ok() + .map(glow::NativeFramebuffer) + .ok_or(FilterChainError::GlInvalidFramebuffer)?; + + let framebuffer = GLFramebuffer::new_from_raw(Arc::clone(chain.get_context()), + texture, fbo, out.format, Size::new(out.width, out.height), 1); + let viewport = Viewport { x: viewport.x, y: viewport.y, diff --git a/librashader-capi/src/version.rs b/librashader-capi/src/version.rs index bcc0745..072a5dc 100644 --- a/librashader-capi/src/version.rs +++ b/librashader-capi/src/version.rs @@ -31,7 +31,8 @@ pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 1; /// ## ABI Versions /// - ABI version 0: null instance (unloaded) /// - ABI version 1: 0.1.0 -pub const LIBRASHADER_CURRENT_ABI: LIBRASHADER_ABI_VERSION = 1; +/// - ABI version 2: 0.4.0 +pub const LIBRASHADER_CURRENT_ABI: LIBRASHADER_ABI_VERSION = 2; /// Function pointer definition for libra_abi_version pub type PFN_libra_instance_abi_version = extern "C" fn() -> LIBRASHADER_ABI_VERSION; diff --git a/librashader-runtime-gl/src/error.rs b/librashader-runtime-gl/src/error.rs index 829bbbf..be4ed8d 100644 --- a/librashader-runtime-gl/src/error.rs +++ b/librashader-runtime-gl/src/error.rs @@ -34,6 +34,8 @@ pub enum FilterChainError { GlSamplerError, #[error("opengl could not create samplers")] GlProgramError, + #[error("an invalid framebuffer was provided to frame")] + GlInvalidFramebuffer, #[error("opengl error: {0}")] GlError(String), } diff --git a/librashader-runtime-gl/src/filter_chain/chain.rs b/librashader-runtime-gl/src/filter_chain/chain.rs index 3b066cb..c107235 100644 --- a/librashader-runtime-gl/src/filter_chain/chain.rs +++ b/librashader-runtime-gl/src/filter_chain/chain.rs @@ -132,7 +132,7 @@ impl FilterChainImpl { /// Load a filter chain from a pre-parsed `ShaderPreset`. pub(crate) unsafe fn load_from_preset( preset: ShaderPreset, - context: glow::Context, + context: Arc, options: Option<&FilterChainOptionsGL>, ) -> error::Result { let disable_cache = options.map_or(false, |o| o.disable_cache); @@ -156,7 +156,6 @@ impl FilterChainImpl { // load luts let luts = T::LoadLut::load_luts(&context, &preset.textures)?; - let context = Arc::new(context); let framebuffer_gen = || T::FramebufferInterface::new(&context, 1); let input_gen = || InputTexture { image: Default::default(), diff --git a/librashader-runtime-gl/src/filter_chain/mod.rs b/librashader-runtime-gl/src/filter_chain/mod.rs index 2ca8cf0..cc477cd 100644 --- a/librashader-runtime-gl/src/filter_chain/mod.rs +++ b/librashader-runtime-gl/src/filter_chain/mod.rs @@ -24,7 +24,7 @@ pub struct FilterChainGL { impl FilterChainGL { /// Load a filter chain from a pre-parsed `ShaderPreset`. pub unsafe fn load_from_preset( - ctx: glow::Context, + ctx: Arc, preset: ShaderPreset, options: Option<&FilterChainOptionsGL>, ) -> Result { @@ -47,7 +47,7 @@ impl FilterChainGL { /// Load the shader preset at the given path into a filter chain. pub unsafe fn load_from_path( - ctx: glow::Context, + ctx: Arc, path: impl AsRef, options: Option<&FilterChainOptionsGL>, ) -> Result {