capi: get rid of Box and use NonNull pointers

This commit is contained in:
chyyran 2022-12-03 19:55:27 -05:00
parent 4946bfc0dd
commit a00c4e1d88
6 changed files with 68 additions and 36 deletions

View file

@ -109,7 +109,7 @@ libra_error_t libra_preset_get_runtime_param_names(libra_shader_preset_t *preset
* Initialize the OpenGL Context for librashader. * Initialize the OpenGL Context for librashader.
* *
* ## Safety * ## 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 * Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
* chain objects, and drawing with them causes immediate undefined behaviour. * 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. * - `options` must be either null, or valid and aligned.
* - `out` may be either null or uninitialized, but must be 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, const struct filter_chain_gl_opt_t *options,
libra_gl_filter_chain_t *out); 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, struct libra_draw_framebuffer_gl_t out,
const float *mvp); const float *mvp);
libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif // __cplusplus #endif // __cplusplus

View file

@ -1,12 +1,12 @@
use std::mem::ManuallyDrop; use std::ptr::NonNull;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use crate::error::LibrashaderError; use crate::error::LibrashaderError;
pub type libra_shader_preset_t = ManuallyDrop<Option<Box<ShaderPreset>>>; pub type libra_shader_preset_t = Option<NonNull<ShaderPreset>>;
pub type libra_error_t = *const LibrashaderError; pub type libra_error_t = *const LibrashaderError;
// #[cfg(feature = "runtime-opengl")] // #[cfg(feature = "runtime-opengl")]
pub type libra_gl_filter_chain_t = ManuallyDrop<Option<Box<librashader::runtime::gl::FilterChainGL>>>; pub type libra_gl_filter_chain_t = Option<NonNull<librashader::runtime::gl::FilterChainGL>>;
#[repr(C)] #[repr(C)]
pub struct libra_viewport_t { pub struct libra_viewport_t {

View file

@ -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_non_null;
pub(crate) use assert_some; pub(crate) use assert_some;
pub(crate) use assert_some_ptr;
use crate::ctypes::libra_error_t; use crate::ctypes::libra_error_t;

View file

@ -1,14 +1,14 @@
use std::ffi::{c_char, CStr, CString, OsStr}; use std::ffi::{c_char, CStr, CString};
use std::mem::{ManuallyDrop, MaybeUninit}; use std::mem::{MaybeUninit};
use std::panic::catch_unwind;
use std::path::Path;
use librashader::presets::ShaderPreset; use librashader::presets::ShaderPreset;
use crate::ffi::ffi_body; use crate::ffi::ffi_body;
use crate::ctypes::{libra_error_t, libra_shader_preset_t}; use crate::ctypes::{libra_error_t, libra_shader_preset_t};
use crate::error::{assert_non_null, assert_some, LibrashaderError}; use crate::error::{assert_non_null, assert_some, assert_some_ptr, LibrashaderError};
use safer_ffi::prelude::*; use std::ptr::NonNull;
use safer_ffi::ffi_export;
use safer_ffi::char_p::char_p_ref as CStrRef; // use safer_ffi::prelude::*;
// use safer_ffi::ffi_export;
// use safer_ffi::char_p::char_p_ref as CStrRef;
// extern_fn! { // extern_fn! {
// /// SAFETY: // /// 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)?; let preset = ShaderPreset::try_parse(filename)?;
unsafe { 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); assert_non_null!(preset);
unsafe { unsafe {
let preset_ptr = &mut *preset; let preset_ptr = &mut *preset;
ManuallyDrop::drop(preset_ptr); let preset = preset_ptr.take();
preset.write(ManuallyDrop::new(None)); 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()?; let name = name.to_str()?;
assert_some!(preset); assert_some_ptr!(mut preset);
let preset = preset.as_mut().unwrap();
if let Some(param) = preset.parameters.iter_mut().find(|c| c.name == name) { if let Some(param) = preset.parameters.iter_mut().find(|c| c.name == name) {
param.value = value 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()?; let name = name.to_str()?;
assert_some!(preset); assert_some_ptr!(preset);
let preset = preset.as_ref().unwrap();
if let Some(param) = preset.parameters.iter().find(|c| c.name == name) { if let Some(param) = preset.parameters.iter().find(|c| c.name == name) {
unsafe { unsafe {
@ -133,8 +131,7 @@ pub type PFN_lbr_preset_get_runtime_param_names = unsafe extern "C" fn (*mut lib
#[no_mangle] #[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 { 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 | { ffi_body!(|preset | {
assert_some!(preset); assert_some_ptr!(preset);
let preset = preset.as_ref().unwrap();
let iter = librashader::presets::get_parameter_meta(preset)?; let iter = librashader::presets::get_parameter_meta(preset)?;
let mut c_strings = Vec::new(); let mut c_strings = Vec::new();

View file

@ -1,12 +1,11 @@
use std::ffi::{c_char, c_void, CString}; use std::ffi::{c_char, c_void, CString};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use crate::ctypes::{libra_error_t, libra_gl_filter_chain_t, libra_shader_preset_t, libra_viewport_t}; 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 crate::ffi::ffi_body;
use std::mem::ManuallyDrop; use std::ptr::NonNull;
use std::panic::catch_unwind;
use librashader::runtime::FilterChain; use librashader::runtime::FilterChain;
use librashader::runtime::gl::{Framebuffer, GLImage, Viewport}; use librashader::runtime::gl::{GLImage, Viewport};
pub use librashader::runtime::gl::options::FilterChainOptionsGL; pub use librashader::runtime::gl::options::FilterChainOptionsGL;
use librashader::Size; 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. /// - `options` must be either null, or valid and aligned.
/// - `out` may be either null or uninitialized, but must be aligned. /// - `out` may be either null or uninitialized, but must be aligned.
#[no_mangle] #[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, options: *const FilterChainOptionsGL,
out: *mut MaybeUninit<libra_gl_filter_chain_t>) -> libra_error_t { out: *mut MaybeUninit<libra_gl_filter_chain_t>) -> libra_error_t {
ffi_body!({ ffi_body!({
assert_non_null!(preset); assert_non_null!(preset);
let preset_ptr = unsafe { let preset = unsafe {
&mut *preset 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() { let options = if options.is_null() {
None None
} else { } else {
Some(unsafe { &*options }) Some(unsafe { &*options })
}; };
let chain = librashader::runtime::gl::FilterChainGL::load_from_preset(*preset, options)?; let chain = librashader::runtime::gl::FilterChainGL::load_from_preset(*preset, options)?;
unsafe { 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 { ) -> libra_error_t {
ffi_body!(mut |chain| { ffi_body!(mut |chain| {
assert_some!(chain); assert_some_ptr!(mut chain);
let chain = chain.as_mut().unwrap();
let image: GLImage = image.into(); let image: GLImage = image.into();
let viewport = Viewport { 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()))
};
})
}

View file

@ -11,10 +11,15 @@ int main()
std::cout << std::filesystem::current_path() << std::endl; std::cout << std::filesystem::current_path() << std::endl;
libra_shader_preset_t preset; libra_shader_preset_t preset;
auto error = libra_load_preset("../../../slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp", &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_preset_print(&preset);
libra_gl_filter_chain_t chain; 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; return 0;
} }