diff --git a/librashader-capi/librashader.h b/librashader-capi/librashader.h index 13f6653..ba8dcb2 100644 --- a/librashader-capi/librashader.h +++ b/librashader-capi/librashader.h @@ -109,7 +109,7 @@ libra_error_t libra_preset_get_runtime_param_names(libra_shader_preset_t *preset * Initialize the OpenGL Context for librashader. * * ## Safety - * Attempting to create a filter chain before initializing the GL context is undefined behaviour. + * Attempting to create a filter chain will fail. * * Reinitializing the OpenGL context with a different loader immediately invalidates previous filter * chain objects, and drawing with them causes immediate undefined behaviour. @@ -127,7 +127,7 @@ libra_error_t libra_gl_init_context(gl_loader_t loader); * - `options` must be either null, or valid and aligned. * - `out` may be either null or uninitialized, but must be aligned. */ -libra_error_t libra_gl_create_filter_chain(libra_shader_preset_t *preset, +libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options, libra_gl_filter_chain_t *out); @@ -138,6 +138,8 @@ libra_error_t libra_gl_filter_chain_frame(libra_gl_filter_chain_t *chain, struct libra_draw_framebuffer_gl_t out, const float *mvp); +libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/librashader-capi/src/ctypes.rs b/librashader-capi/src/ctypes.rs index 485f60c..de49a19 100644 --- a/librashader-capi/src/ctypes.rs +++ b/librashader-capi/src/ctypes.rs @@ -1,12 +1,12 @@ -use std::mem::ManuallyDrop; +use std::ptr::NonNull; use librashader::presets::ShaderPreset; use crate::error::LibrashaderError; -pub type libra_shader_preset_t = ManuallyDrop>>; +pub type libra_shader_preset_t = Option>; pub type libra_error_t = *const LibrashaderError; // #[cfg(feature = "runtime-opengl")] -pub type libra_gl_filter_chain_t = ManuallyDrop>>; +pub type libra_gl_filter_chain_t = Option>; #[repr(C)] pub struct libra_viewport_t { diff --git a/librashader-capi/src/error.rs b/librashader-capi/src/error.rs index 927f431..77a28c2 100644 --- a/librashader-capi/src/error.rs +++ b/librashader-capi/src/error.rs @@ -49,6 +49,24 @@ macro_rules! assert_some { } } +macro_rules! assert_some_ptr { + ($value:ident) => { + if $value.is_none() { + return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export() + } + + let $value = unsafe { $value.as_ref().unwrap().as_ref() }; + }; + (mut $value:ident) => { + if $value.is_none() { + return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export() + } + + let $value = unsafe { $value.as_mut().unwrap().as_mut() }; + } +} + pub(crate) use assert_non_null; pub(crate) use assert_some; +pub(crate) use assert_some_ptr; use crate::ctypes::libra_error_t; \ No newline at end of file diff --git a/librashader-capi/src/presets.rs b/librashader-capi/src/presets.rs index 480d23a..4901ccf 100644 --- a/librashader-capi/src/presets.rs +++ b/librashader-capi/src/presets.rs @@ -1,14 +1,14 @@ -use std::ffi::{c_char, CStr, CString, OsStr}; -use std::mem::{ManuallyDrop, MaybeUninit}; -use std::panic::catch_unwind; -use std::path::Path; +use std::ffi::{c_char, CStr, CString}; +use std::mem::{MaybeUninit}; use librashader::presets::ShaderPreset; use crate::ffi::ffi_body; use crate::ctypes::{libra_error_t, libra_shader_preset_t}; -use crate::error::{assert_non_null, assert_some, LibrashaderError}; -use safer_ffi::prelude::*; -use safer_ffi::ffi_export; -use safer_ffi::char_p::char_p_ref as CStrRef; +use crate::error::{assert_non_null, assert_some, assert_some_ptr, LibrashaderError}; +use std::ptr::NonNull; + +// use safer_ffi::prelude::*; +// use safer_ffi::ffi_export; +// use safer_ffi::char_p::char_p_ref as CStrRef; // extern_fn! { // /// SAFETY: @@ -50,7 +50,7 @@ pub unsafe extern "C" fn libra_load_preset(filename: *const c_char, out: *mut Ma let preset = ShaderPreset::try_parse(filename)?; unsafe { - out.write(MaybeUninit::new(ManuallyDrop::new(Some(Box::new(preset))))) + out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(preset))))) } }) } @@ -64,8 +64,8 @@ pub unsafe extern "C" fn libra_preset_free(preset: *mut libra_shader_preset_t) - assert_non_null!(preset); unsafe { let preset_ptr = &mut *preset; - ManuallyDrop::drop(preset_ptr); - preset.write(ManuallyDrop::new(None)); + let preset = preset_ptr.take(); + drop(Box::from_raw(preset.unwrap().as_ptr())); } }) } @@ -81,8 +81,7 @@ pub unsafe extern "C" fn libra_preset_set_param(preset: *mut libra_shader_preset }; let name = name.to_str()?; - assert_some!(preset); - let preset = preset.as_mut().unwrap(); + assert_some_ptr!(mut preset); if let Some(param) = preset.parameters.iter_mut().find(|c| c.name == name) { param.value = value @@ -102,8 +101,7 @@ pub unsafe extern "C" fn libra_preset_get_param(preset: *mut libra_shader_preset }; let name = name.to_str()?; - assert_some!(preset); - let preset = preset.as_ref().unwrap(); + assert_some_ptr!(preset); if let Some(param) = preset.parameters.iter().find(|c| c.name == name) { unsafe { @@ -133,8 +131,7 @@ pub type PFN_lbr_preset_get_runtime_param_names = unsafe extern "C" fn (*mut lib #[no_mangle] pub unsafe extern "C" fn libra_preset_get_runtime_param_names(preset: *mut libra_shader_preset_t, mut value: MaybeUninit<*mut *const c_char>) -> libra_error_t { ffi_body!(|preset | { - assert_some!(preset); - let preset = preset.as_ref().unwrap(); + assert_some_ptr!(preset); let iter = librashader::presets::get_parameter_meta(preset)?; let mut c_strings = Vec::new(); diff --git a/librashader-capi/src/runtime/gl.rs b/librashader-capi/src/runtime/gl.rs index 202ec84..40db655 100644 --- a/librashader-capi/src/runtime/gl.rs +++ b/librashader-capi/src/runtime/gl.rs @@ -1,12 +1,11 @@ use std::ffi::{c_char, c_void, CString}; use std::mem::MaybeUninit; use crate::ctypes::{libra_error_t, libra_gl_filter_chain_t, libra_shader_preset_t, libra_viewport_t}; -use crate::error::{assert_non_null, assert_some, LibrashaderError}; +use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::ffi::ffi_body; -use std::mem::ManuallyDrop; -use std::panic::catch_unwind; +use std::ptr::NonNull; use librashader::runtime::FilterChain; -use librashader::runtime::gl::{Framebuffer, GLImage, Viewport}; +use librashader::runtime::gl::{GLImage, Viewport}; pub use librashader::runtime::gl::options::FilterChainOptionsGL; use librashader::Size; @@ -41,27 +40,28 @@ pub unsafe extern "C" fn libra_gl_init_context(loader: gl_loader_t) -> libra_err /// - `options` must be either null, or valid and aligned. /// - `out` may be either null or uninitialized, but must be aligned. #[no_mangle] -pub unsafe extern "C" fn libra_gl_create_filter_chain(preset: *mut libra_shader_preset_t, +pub unsafe extern "C" fn libra_gl_filter_chain_create(preset: *mut libra_shader_preset_t, options: *const FilterChainOptionsGL, out: *mut MaybeUninit) -> libra_error_t { ffi_body!({ assert_non_null!(preset); - let preset_ptr = unsafe { - &mut *preset + let preset = unsafe { + let preset_ptr = &mut *preset; + let preset = preset_ptr.take(); + Box::from_raw(preset.unwrap().as_ptr()) }; - assert_some!(preset_ptr); - let preset = preset_ptr.take().unwrap(); let options = if options.is_null() { None } else { Some(unsafe { &*options }) }; + let chain = librashader::runtime::gl::FilterChainGL::load_from_preset(*preset, options)?; unsafe { - out.write(MaybeUninit::new(ManuallyDrop::new(Some(Box::new(chain))))) + out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(chain))))) } }) } @@ -104,8 +104,7 @@ pub unsafe extern "C" fn libra_gl_filter_chain_frame(chain: *mut libra_gl_filter ) -> libra_error_t { ffi_body!(mut |chain| { - assert_some!(chain); - let chain = chain.as_mut().unwrap(); + assert_some_ptr!(mut chain); let image: GLImage = image.into(); let viewport = Viewport { @@ -119,3 +118,14 @@ pub unsafe extern "C" fn libra_gl_filter_chain_frame(chain: *mut libra_gl_filter } +#[no_mangle] +pub unsafe extern "C" fn libra_gl_filter_chain_free(chain: *mut libra_gl_filter_chain_t) -> libra_error_t { + ffi_body!({ + assert_non_null!(chain); + unsafe { + let chain_ptr = &mut *chain; + let chain = chain_ptr.take(); + drop(Box::from_raw(chain.unwrap().as_ptr())) + }; + }) +} \ No newline at end of file diff --git a/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp b/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp index 0b9c1fa..8dc210a 100644 --- a/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp +++ b/test/capi-tests/librashader-capi-tests/librashader-capi-tests/librashader-capi-tests.cpp @@ -11,10 +11,15 @@ int main() std::cout << std::filesystem::current_path() << std::endl; libra_shader_preset_t preset; auto error = libra_load_preset("../../../slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp", &preset); - + if (error != NULL) { + std::cout << "error happened\n"; + } libra_preset_print(&preset); libra_gl_filter_chain_t chain; - libra_gl_create_filter_chain(&preset, NULL, &chain); + error = libra_gl_create_filter_chain(&preset, NULL, &chain); + if (error != NULL) { + std::cout << "error happened\n"; + } return 0; }