capi: make function pointer types for everything

This commit is contained in:
chyyran 2022-12-05 00:06:37 -05:00
parent ebe889df2f
commit 2cce27ecb9
14 changed files with 290 additions and 252 deletions

77
Cargo.lock generated
View file

@ -213,16 +213,6 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "ctor"
version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
dependencies = [
"quote",
"syn",
]
[[package]] [[package]]
name = "cty" name = "cty"
version = "0.2.2" version = "0.2.2"
@ -331,17 +321,6 @@ dependencies = [
"auto_ops", "auto_ops",
] ]
[[package]]
name = "ghost"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb19fe8de3ea0920d282f7b77dd4227aea6b8b999b42cdf0ca41b2472b14443a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "gif" name = "gif"
version = "0.11.4" version = "0.11.4"
@ -462,28 +441,6 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "inventory"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb5160c60ba1e809707918ee329adb99d222888155835c6feedba19f6c3fd4"
dependencies = [
"ctor",
"ghost",
"inventory-impl",
]
[[package]]
name = "inventory-impl"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e41b53715c6f0c4be49510bb82dee2c1e51c8586d885abe65396e82ed518548"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.4" version = "1.0.4"
@ -556,7 +513,6 @@ dependencies = [
"gl", "gl",
"librashader", "librashader",
"paste", "paste",
"safer-ffi",
"thiserror", "thiserror",
"windows", "windows",
] ]
@ -697,21 +653,6 @@ dependencies = [
"autocfg", "autocfg",
] ]
[[package]]
name = "mini_paste"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2499b7bd9834270bf24cfc4dd96be59020ba6fd7f3276b772aee2de66e82b63"
dependencies = [
"mini_paste-proc_macro",
]
[[package]]
name = "mini_paste-proc_macro"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c5f1f52e39b728e73af4b454f1b29173d4544607bd395dafe1918fd149db67"
[[package]] [[package]]
name = "minimal-lexical" name = "minimal-lexical"
version = "0.2.1" version = "0.2.1"
@ -1012,24 +953,6 @@ version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "safer-ffi"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c710243617290d86a49a30564d94d0b646eacf6d7b67035e20d6e8a21f1193"
dependencies = [
"inventory",
"libc",
"mini_paste",
"safer_ffi-proc_macro",
]
[[package]]
name = "safer_ffi-proc_macro"
version = "0.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc02dc034daa0944eb133b448f261ef7422ccae768e30f30ce5cdeb4ae4e506c"
[[package]] [[package]]
name = "scoped_threadpool" name = "scoped_threadpool"
version = "0.1.9" version = "0.1.9"

View file

@ -4,7 +4,7 @@ include_guard = "__LIBRASHADER_H__"
pragma_once = true pragma_once = true
usize_is_size_t = true usize_is_size_t = true
documentation_style = "c++" documentation_style = "c++"
header = "#ifdef _WIN32\n#include <d3d11.h>\n#else\ntypedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;\n#endif" after_includes = "#ifdef _WIN32\n#include <d3d11.h>\n#else\ntypedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;\n#endif"
[parse] [parse]
parse_deps = true parse_deps = true
include = ["librashader", include = ["librashader",
@ -33,7 +33,22 @@ include = [
"PFN_lbr_preset_get_runtime_param_names", "PFN_lbr_preset_get_runtime_param_names",
# error # error
"PFN_lbr_error_code", "PFN_lbr_error_errno",
"PFN_lbr_error_print",
"PFN_lbr_error_free",
"PFN_lbr_error_write",
"PFN_lbr_error_free_string",
# gl
"PFN_lbr_gl_init_context",
"PFN_lbr_gl_filter_chain_create",
"PFN_lbr_gl_filter_chain_frame",
"PFN_lbr_gl_filter_chain_free",
# d3d11
"PFN_lbr_d3d11_filter_chain_create",
"PFN_lbr_d3d11_filter_chain_frame",
"PFN_lbr_d3d11_filter_chain_free"
] ]

View file

@ -1,9 +1,3 @@
#ifdef _WIN32
#include <d3d11.h>
#else
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;
#endif
#ifndef __LIBRASHADER_H__ #ifndef __LIBRASHADER_H__
#define __LIBRASHADER_H__ #define __LIBRASHADER_H__
@ -14,6 +8,11 @@ typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#ifdef _WIN32
#include <d3d11.h>
#else
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;
#endif
/// Error codes for librashader error types. /// Error codes for librashader error types.
enum LIBRA_ERRNO enum LIBRA_ERRNO
@ -129,20 +128,83 @@ typedef struct frame_d3d11_opt_t {
int32_t frame_direction; int32_t frame_direction;
} frame_d3d11_opt_t; } frame_d3d11_opt_t;
typedef libra_error_t (*PFN_lbr_preset_free)(libra_shader_preset_t*); typedef libra_error_t (*PFN_lbr_preset_free)(libra_shader_preset_t *preset);
typedef libra_error_t (*PFN_lbr_preset_set_param)(libra_shader_preset_t*, const char*, float); typedef libra_error_t (*PFN_lbr_preset_set_param)(libra_shader_preset_t *preset, const char *name, float value);
typedef libra_error_t (*PFN_lbr_preset_get_param)(libra_shader_preset_t*, const char*, float*); typedef libra_error_t (*PFN_lbr_preset_get_param)(libra_shader_preset_t *preset, const char *name, float *value);
typedef libra_error_t (*PFN_lbr_preset_print)(libra_shader_preset_t*); typedef libra_error_t (*PFN_lbr_preset_print)(libra_shader_preset_t *preset);
typedef libra_error_t (*PFN_lbr_preset_get_runtime_param_names)(libra_shader_preset_t*, float*); typedef libra_error_t (*PFN_lbr_preset_get_runtime_param_names)(libra_shader_preset_t *preset, const char **value);
typedef LIBRA_ERRNO (*PFN_lbr_error_errno)(libra_error_t error);
typedef int32_t (*PFN_lbr_error_print)(libra_error_t error);
typedef int32_t (*PFN_lbr_error_free)(libra_error_t *error);
typedef int32_t (*PFN_lbr_error_write)(libra_error_t error, char **out);
typedef int32_t (*PFN_lbr_error_free_string)(char **out);
typedef libra_error_t (*PFN_lbr_gl_init_context)(gl_loader_t loader);
typedef libra_error_t (*PFN_lbr_gl_filter_chain_create)(libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options, libra_gl_filter_chain_t *out);
typedef libra_error_t (*PFN_lbr_gl_filter_chain_frame)(libra_gl_filter_chain_t *chain, size_t frame_count, struct libra_source_image_gl_t image, struct libra_viewport_t viewport, struct libra_draw_framebuffer_gl_t out, const float *mvp, const struct frame_gl_opt_t *opt);
typedef libra_error_t (*PFN_lbr_gl_filter_chain_free)(libra_gl_filter_chain_t *chain);
typedef libra_error_t (*PFN_lbr_d3d11_filter_chain_create)(libra_shader_preset_t *preset, const struct filter_chain_d3d11_opt_t *options, const ID3D11Device *device, libra_d3d11_filter_chain_t *out);
typedef libra_error_t (*PFN_lbr_d3d11_filter_chain_frame)(libra_d3d11_filter_chain_t *chain, size_t frame_count, struct libra_source_image_d3d11_t image, struct libra_viewport_t viewport, const ID3D11RenderTargetView *out, const float *mvp, const struct frame_d3d11_opt_t *opt);
typedef libra_error_t (*PFN_lbr_d3d11_filter_chain_free)(libra_d3d11_filter_chain_t *chain);
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif // __cplusplus #endif // __cplusplus
/// Get the error code corresponding to this error object.
///
/// ## Safety
/// - `error` must be valid and initialized.
LIBRA_ERRNO libra_error_errno(libra_error_t error);
/// Print the error message.
///
/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0.
/// ## Safety
/// - `error` must be a valid and initialized instance of `libra_error_t`.
int32_t libra_error_print(libra_error_t error);
/// Frees any internal state kept by the error.
///
/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0.
/// The resulting error object becomes null.
/// ## Safety
/// - `error` must be null or a pointer to a valid and initialized instance of `libra_error_t`.
int32_t libra_error_free(libra_error_t *error);
/// Writes the error message into `out`
///
/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0.
/// ## Safety
/// - `error` must be a valid and initialized instance of `libra_error_t`.
/// - `out` must be a non-null pointer. The resulting string must not be modified.
int32_t libra_error_write(libra_error_t error,
char **out);
/// Frees an error string previously allocated by `libra_error_write`.
///
/// After freeing, the pointer will be set to null.
/// ## Safety
/// - If `libra_error_write` is not null, it must point to a string previously returned by `libra_error_write`.
/// Attempting to free anything else, including strings or objects from other librashader functions, is immediate
/// Undefined Behaviour.
int32_t libra_error_free_string(char **out);
/// Load a preset. /// Load a preset.
/// ///
/// ## Safety /// ## Safety
@ -274,45 +336,6 @@ libra_error_t libra_d3d11_filter_chain_frame(libra_d3d11_filter_chain_t *chain,
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`.
libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain); libra_error_t libra_d3d11_filter_chain_free(libra_d3d11_filter_chain_t *chain);
/// Get the error code corresponding to this error object.
///
/// ## Safety
/// - `error` must be valid and initialized.
LIBRA_ERRNO libra_error_errno(libra_error_t error);
/// Print the error message.
///
/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0.
/// ## Safety
/// - `error` must be a valid and initialized instance of `libra_error_t`.
int32_t libra_error_print(libra_error_t error);
/// Frees any internal state kept by the error.
///
/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0.
/// The resulting error object becomes null.
/// ## Safety
/// - `error` must be null or a pointer to a valid and initialized instance of `libra_error_t`.
int32_t libra_error_free(libra_error_t *error);
/// Writes the error message into `out`
///
/// If `error` is null, this function does nothing and returns 1. Otherwise, this function returns 0.
/// ## Safety
/// - `error` must be a valid and initialized instance of `libra_error_t`.
/// - `out` must be a non-null pointer. The resulting string must not be modified.
int32_t libra_error_write(libra_error_t error,
char **out);
/// Frees an error string previously allocated by `libra_error_write`.
///
/// After freeing, the pointer will be set to null.
/// ## Safety
/// - If `libra_error_write` is not null, it must point to a string previously returned by `libra_error_write`.
/// Attempting to free anything else, including strings or objects from other librashader functions, is immediate
/// Undefined Behaviour.
int32_t libra_error_free_string(char **out);
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"
#endif // __cplusplus #endif // __cplusplus

View file

@ -1,7 +1,7 @@
//! Binding types for the librashader C API. //! Binding types for the librashader C API.
use std::ptr::NonNull;
use librashader::presets::ShaderPreset;
use crate::error::LibrashaderError; use crate::error::LibrashaderError;
use librashader::presets::ShaderPreset;
use std::ptr::NonNull;
pub type libra_shader_preset_t = Option<NonNull<ShaderPreset>>; pub type libra_shader_preset_t = Option<NonNull<ShaderPreset>>;
pub type libra_error_t = Option<NonNull<LibrashaderError>>; pub type libra_error_t = Option<NonNull<LibrashaderError>>;
@ -10,7 +10,8 @@ pub type libra_error_t = Option<NonNull<LibrashaderError>>;
pub type libra_gl_filter_chain_t = Option<NonNull<librashader::runtime::gl::FilterChainGL>>; pub type libra_gl_filter_chain_t = Option<NonNull<librashader::runtime::gl::FilterChainGL>>;
#[cfg(feature = "runtime-d3d11")] #[cfg(feature = "runtime-d3d11")]
pub type libra_d3d11_filter_chain_t = Option<NonNull<librashader::runtime::d3d11::FilterChainD3D11>>; pub type libra_d3d11_filter_chain_t =
Option<NonNull<librashader::runtime::d3d11::FilterChainD3D11>>;
/// Parameters for the output viewport. /// Parameters for the output viewport.
#[repr(C)] #[repr(C)]

View file

@ -25,7 +25,6 @@ pub enum LibrashaderError {
#[cfg(feature = "runtime-d3d11")] #[cfg(feature = "runtime-d3d11")]
#[error("There was an error in the D3D11 filter chain.")] #[error("There was an error in the D3D11 filter chain.")]
D3D11FilterError(#[from] librashader::runtime::d3d11::error::FilterChainError), D3D11FilterError(#[from] librashader::runtime::d3d11::error::FilterChainError),
} }
/// Error codes for librashader error types. /// Error codes for librashader error types.
@ -39,8 +38,7 @@ pub enum LIBRA_ERRNO {
RUNTIME_ERROR = 5, RUNTIME_ERROR = 5,
} }
pub type PFN_lbr_error_errno = extern "C" fn(error: libra_error_t) -> LIBRA_ERRNO;
pub type PFN_lbr_error_errno = extern "C" fn (libra_error_t) -> LIBRA_ERRNO;
#[no_mangle] #[no_mangle]
/// Get the error code corresponding to this error object. /// Get the error code corresponding to this error object.
/// ///
@ -51,12 +49,10 @@ pub extern "C" fn libra_error_errno(error: libra_error_t) -> LIBRA_ERRNO {
return LIBRA_ERRNO::UNKNOWN_ERROR return LIBRA_ERRNO::UNKNOWN_ERROR
}; };
unsafe { unsafe { error.as_ref().get_code() }
error.as_ref().get_code()
}
} }
pub type PFN_lbr_error_print = extern "C" fn (libra_error_t) -> i32; pub type PFN_lbr_error_print = extern "C" fn(error: libra_error_t) -> i32;
#[no_mangle] #[no_mangle]
/// Print the error message. /// Print the error message.
/// ///
@ -74,7 +70,7 @@ pub extern "C" fn libra_error_print(error: libra_error_t) -> i32 {
return 0; return 0;
} }
pub type PFN_lbr_error_free = extern "C" fn (*mut libra_error_t) -> i32; pub type PFN_lbr_error_free = extern "C" fn(error: *mut libra_error_t) -> i32;
#[no_mangle] #[no_mangle]
/// Frees any internal state kept by the error. /// Frees any internal state kept by the error.
/// ///
@ -93,12 +89,12 @@ pub extern "C" fn libra_error_free(error: *mut libra_error_t) -> i32 {
return 1; return 1;
}; };
unsafe { unsafe { drop(Box::from_raw(error.as_ptr())) }
drop(Box::from_raw(error.as_ptr()))
}
return 0; return 0;
} }
pub type PFN_lbr_error_write =
extern "C" fn(error: libra_error_t, out: *mut MaybeUninit<*mut c_char>) -> i32;
#[no_mangle] #[no_mangle]
/// Writes the error message into `out` /// Writes the error message into `out`
/// ///
@ -106,7 +102,10 @@ pub extern "C" fn libra_error_free(error: *mut libra_error_t) -> i32 {
/// ## Safety /// ## Safety
/// - `error` must be a valid and initialized instance of `libra_error_t`. /// - `error` must be a valid and initialized instance of `libra_error_t`.
/// - `out` must be a non-null pointer. The resulting string must not be modified. /// - `out` must be a non-null pointer. The resulting string must not be modified.
pub extern "C" fn libra_error_write(error: libra_error_t, out: *mut MaybeUninit<*mut c_char>) -> i32 { pub extern "C" fn libra_error_write(
error: libra_error_t,
out: *mut MaybeUninit<*mut c_char>,
) -> i32 {
let Some(error) = error else { let Some(error) = error else {
return 1 return 1
}; };
@ -125,6 +124,7 @@ pub extern "C" fn libra_error_write(error: libra_error_t, out: *mut MaybeUninit<
return 0; return 0;
} }
pub type PFN_lbr_error_free_string = extern "C" fn(out: *mut *mut c_char) -> i32;
#[no_mangle] #[no_mangle]
/// Frees an error string previously allocated by `libra_error_write`. /// Frees an error string previously allocated by `libra_error_write`.
/// ///
@ -157,8 +157,7 @@ impl LibrashaderError {
#[cfg(feature = "runtime-opengl")] #[cfg(feature = "runtime-opengl")]
LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR, LibrashaderError::OpenGlFilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
#[cfg(feature = "runtime-d3d11")] #[cfg(feature = "runtime-d3d11")]
LibrashaderError::D3D11FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR LibrashaderError::D3D11FilterError(_) => LIBRA_ERRNO::RUNTIME_ERROR,
} }
} }
pub(crate) const fn ok() -> libra_error_t { pub(crate) const fn ok() -> libra_error_t {
@ -177,41 +176,43 @@ impl LibrashaderError {
macro_rules! assert_non_null { macro_rules! assert_non_null {
($value:ident) => { ($value:ident) => {
if $value.is_null() { if $value.is_null() {
return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export() return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
} }
}; };
(noexport $value:ident) => { (noexport $value:ident) => {
if $value.is_null() { if $value.is_null() {
return Err($crate::error::LibrashaderError::InvalidParameter(stringify!($value))) return Err($crate::error::LibrashaderError::InvalidParameter(
} stringify!($value),
));
} }
};
} }
macro_rules! assert_some { macro_rules! assert_some {
($value:ident) => { ($value:ident) => {
if $value.is_none() { if $value.is_none() {
return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export() return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
}
} }
};
} }
macro_rules! assert_some_ptr { macro_rules! assert_some_ptr {
($value:ident) => { ($value:ident) => {
if $value.is_none() { if $value.is_none() {
return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export() return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
} }
let $value = unsafe { $value.as_ref().unwrap().as_ref() }; let $value = unsafe { $value.as_ref().unwrap().as_ref() };
}; };
(mut $value:ident) => { (mut $value:ident) => {
if $value.is_none() { if $value.is_none() {
return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export() return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
} }
let $value = unsafe { $value.as_mut().unwrap().as_mut() }; let $value = unsafe { $value.as_mut().unwrap().as_mut() };
} };
} }
use crate::ctypes::libra_error_t;
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; pub(crate) use assert_some_ptr;
use crate::ctypes::libra_error_t;

View file

@ -1,4 +1,3 @@
macro_rules! ffi_body { macro_rules! ffi_body {
($body:block) => { ($body:block) => {
{ {
@ -58,7 +57,6 @@ macro_rules! ffi_body {
} }
} }
macro_rules! extern_fn { macro_rules! extern_fn {
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) $body:block) => { ($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) $body:block) => {
paste::paste! { paste::paste! {

View file

@ -40,8 +40,8 @@
use std::os::raw::c_char; use std::os::raw::c_char;
pub mod ctypes;
pub mod error;
mod ffi;
pub mod presets; pub mod presets;
pub mod runtime; pub mod runtime;
pub mod error;
pub mod ctypes;
mod ffi;

View file

@ -1,13 +1,16 @@
//! The librashader preset C API (`libra_preset_*`). //! The librashader preset C API (`libra_preset_*`).
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::ctypes::{libra_error_t, libra_shader_preset_t};
use crate::error::{assert_non_null, assert_some, assert_some_ptr, LibrashaderError}; use crate::error::{assert_non_null, assert_some, assert_some_ptr, LibrashaderError};
use crate::ffi::ffi_body;
use librashader::presets::ShaderPreset;
use std::ffi::{c_char, CStr, CString};
use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
pub type PFN_lbr_preset_create = unsafe extern "C" fn (*const c_char, *mut MaybeUninit<libra_shader_preset_t>) -> libra_error_t; pub type PFN_lbr_preset_create = unsafe extern "C" fn(
filename: *const c_char,
out: *mut MaybeUninit<libra_shader_preset_t>,
) -> libra_error_t;
/// Load a preset. /// Load a preset.
/// ///
@ -17,14 +20,15 @@ pub type PFN_lbr_preset_create = unsafe extern "C" fn (*const c_char, *mut Maybe
/// ## Returns /// ## Returns
/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`. /// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_preset_create(filename: *const c_char, out: *mut MaybeUninit<libra_shader_preset_t>) -> libra_error_t { pub unsafe extern "C" fn libra_preset_create(
filename: *const c_char,
out: *mut MaybeUninit<libra_shader_preset_t>,
) -> libra_error_t {
ffi_body!({ ffi_body!({
assert_non_null!(filename); assert_non_null!(filename);
assert_non_null!(out); assert_non_null!(out);
let filename = unsafe { let filename = unsafe { CStr::from_ptr(filename) };
CStr::from_ptr(filename)
};
let filename = filename.to_str()?; let filename = filename.to_str()?;
@ -32,12 +36,15 @@ pub unsafe extern "C" fn libra_preset_create(filename: *const c_char, out: *mut
let preset = ShaderPreset::try_parse(filename)?; let preset = ShaderPreset::try_parse(filename)?;
unsafe { unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(preset))))) out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
preset,
)))))
} }
}) })
} }
pub type PFN_lbr_preset_free = unsafe extern "C" fn (*mut libra_shader_preset_t) -> libra_error_t; pub type PFN_lbr_preset_free =
unsafe extern "C" fn(preset: *mut libra_shader_preset_t) -> libra_error_t;
/// Free the preset. /// Free the preset.
/// ///
@ -58,15 +65,22 @@ pub unsafe extern "C" fn libra_preset_free(preset: *mut libra_shader_preset_t) -
}) })
} }
pub type PFN_lbr_preset_set_param = unsafe extern "C" fn (*mut libra_shader_preset_t, *const c_char, f32) -> libra_error_t; pub type PFN_lbr_preset_set_param = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
name: *const c_char,
value: f32,
) -> libra_error_t;
/// Set the value of the parameter in the preset. /// Set the value of the parameter in the preset.
/// ///
/// ## Safety /// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset. /// - `preset` must be null or a valid and aligned pointer to a shader preset.
/// - `name` must be null or a valid and aligned pointer to a string. /// - `name` must be null or a valid and aligned pointer to a string.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_preset_set_param(preset: *mut libra_shader_preset_t, pub unsafe extern "C" fn libra_preset_set_param(
name: *const c_char, value: f32) -> libra_error_t { preset: *mut libra_shader_preset_t,
name: *const c_char,
value: f32,
) -> libra_error_t {
ffi_body!(|name|; mut |preset| { ffi_body!(|name|; mut |preset| {
let name = unsafe { let name = unsafe {
CStr::from_ptr(name) CStr::from_ptr(name)
@ -81,7 +95,11 @@ pub unsafe extern "C" fn libra_preset_set_param(preset: *mut libra_shader_preset
}) })
} }
pub type PFN_lbr_preset_get_param = unsafe extern "C" fn (*mut libra_shader_preset_t, *const c_char, *mut MaybeUninit<f32>) -> libra_error_t; pub type PFN_lbr_preset_get_param = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
name: *const c_char,
value: *mut MaybeUninit<f32>,
) -> libra_error_t;
/// Get the value of the parameter as set in the preset. /// Get the value of the parameter as set in the preset.
/// ///
@ -90,12 +108,13 @@ pub type PFN_lbr_preset_get_param = unsafe extern "C" fn (*mut libra_shader_pres
/// - `name` must be null or a valid and aligned pointer to a string. /// - `name` must be null or a valid and aligned pointer to a string.
/// - `value` may be a pointer to a uninitialized `float`. /// - `value` may be a pointer to a uninitialized `float`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_preset_get_param(preset: *mut libra_shader_preset_t, pub unsafe extern "C" fn libra_preset_get_param(
name: *const c_char, value: *mut MaybeUninit<f32>) -> libra_error_t { preset: *mut libra_shader_preset_t,
ffi_body!(|name, preset | { name: *const c_char,
let name = unsafe { value: *mut MaybeUninit<f32>,
CStr::from_ptr(name) ) -> libra_error_t {
}; ffi_body!(|name, preset| {
let name = unsafe { CStr::from_ptr(name) };
let name = name.to_str()?; let name = name.to_str()?;
assert_some_ptr!(preset); assert_some_ptr!(preset);
@ -103,14 +122,13 @@ pub unsafe extern "C" fn libra_preset_get_param(preset: *mut libra_shader_preset
assert_non_null!(value); assert_non_null!(value);
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 { value.write(MaybeUninit::new(param.value)) }
value.write(MaybeUninit::new(param.value))
}
} }
}) })
} }
pub type PFN_lbr_preset_print = unsafe extern "C" fn (*mut libra_shader_preset_t) -> libra_error_t; pub type PFN_lbr_preset_print =
unsafe extern "C" fn(preset: *mut libra_shader_preset_t) -> libra_error_t;
/// Pretty print the shader preset. /// Pretty print the shader preset.
/// ///
@ -124,22 +142,28 @@ pub unsafe extern "C" fn libra_preset_print(preset: *mut libra_shader_preset_t)
}) })
} }
pub type PFN_lbr_preset_get_runtime_param_names = unsafe extern "C" fn(
pub type PFN_lbr_preset_get_runtime_param_names = unsafe extern "C" fn (*mut libra_shader_preset_t, *mut MaybeUninit<f32>) -> libra_error_t; preset: *mut libra_shader_preset_t,
value: MaybeUninit<*mut *const c_char>,
) -> libra_error_t;
/// Get a list of runtime parameter names. /// Get a list of runtime parameter names.
/// ///
/// The returned value can not currently be freed. /// The returned value can not currently be freed.
/// This function should be considered in progress. Its use is discouraged. /// This function should be considered in progress. Its use is discouraged.
#[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(
ffi_body!(|preset | { preset: *mut libra_shader_preset_t,
mut value: MaybeUninit<*mut *const c_char>,
) -> libra_error_t {
ffi_body!(|preset| {
assert_some_ptr!(preset); assert_some_ptr!(preset);
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();
for param in iter { for param in iter {
let c_string = CString::new(param.id).map_err(|err| LibrashaderError::UnknownError(Box::new(err)))?; let c_string = CString::new(param.id)
.map_err(|err| LibrashaderError::UnknownError(Box::new(err)))?;
c_strings.push(c_string.into_raw().cast_const()); c_strings.push(c_string.into_raw().cast_const());
} }

View file

@ -1,11 +1,15 @@
use std::mem::MaybeUninit; use crate::ctypes::{
use windows::Win32::Graphics::Direct3D11::{ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView}; libra_d3d11_filter_chain_t, libra_error_t, libra_shader_preset_t, libra_viewport_t,
use crate::ctypes::{libra_d3d11_filter_chain_t, libra_error_t, libra_shader_preset_t, libra_viewport_t}; };
use crate::ffi::ffi_body;
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError}; use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use std::ptr::NonNull; use crate::ffi::ffi_body;
use librashader::runtime::d3d11::{DxImageView, Viewport}; use librashader::runtime::d3d11::{DxImageView, Viewport};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use std::slice; use std::slice;
use windows::Win32::Graphics::Direct3D11::{
ID3D11Device, ID3D11RenderTargetView, ID3D11ShaderResourceView,
};
pub use librashader::runtime::d3d11::options::FilterChainOptionsD3D11; pub use librashader::runtime::d3d11::options::FilterChainOptionsD3D11;
pub use librashader::runtime::d3d11::options::FrameOptionsD3D11; pub use librashader::runtime::d3d11::options::FrameOptionsD3D11;
@ -19,11 +23,9 @@ pub struct libra_source_image_d3d11_t {
/// The width of the source image. /// The width of the source image.
pub width: u32, pub width: u32,
/// The height of the source image. /// The height of the source image.
pub height: u32 pub height: u32,
} }
impl TryFrom<libra_source_image_d3d11_t> for DxImageView { impl TryFrom<libra_source_image_d3d11_t> for DxImageView {
type Error = LibrashaderError; type Error = LibrashaderError;
@ -38,6 +40,12 @@ impl TryFrom<libra_source_image_d3d11_t> for DxImageView {
} }
} }
pub type PFN_lbr_d3d11_filter_chain_create = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsD3D11,
device: *const ID3D11Device,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>,
) -> libra_error_t;
/// Create the filter chain given the shader preset. /// Create the filter chain given the shader preset.
/// ///
/// The shader preset is immediately invalidated and must be recreated after /// The shader preset is immediately invalidated and must be recreated after
@ -48,10 +56,12 @@ impl TryFrom<libra_source_image_d3d11_t> for DxImageView {
/// - `options` must be either null, or valid and aligned. /// - `options` must be either null, or valid and aligned.
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_d3d11_filter_chain_create(preset: *mut libra_shader_preset_t, pub unsafe extern "C" fn libra_d3d11_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsD3D11, options: *const FilterChainOptionsD3D11,
device: *const ID3D11Device, device: *const ID3D11Device,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>) -> libra_error_t { out: *mut MaybeUninit<libra_d3d11_filter_chain_t>,
) -> libra_error_t {
ffi_body!({ ffi_body!({
assert_non_null!(preset); assert_non_null!(preset);
assert_non_null!(device); assert_non_null!(device);
@ -67,15 +77,30 @@ pub unsafe extern "C" fn libra_d3d11_filter_chain_create(preset: *mut libra_shad
Some(unsafe { &*options }) Some(unsafe { &*options })
}; };
let chain = librashader::runtime::d3d11::FilterChainD3D11::load_from_preset(
let chain = librashader::runtime::d3d11::FilterChainD3D11::load_from_preset(unsafe { &*device }, *preset, options)?; unsafe { &*device },
*preset,
options,
)?;
unsafe { unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(chain))))) out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
} }
}) })
} }
pub type PFN_lbr_d3d11_filter_chain_frame = unsafe extern "C" fn(
chain: *mut libra_d3d11_filter_chain_t,
frame_count: usize,
image: libra_source_image_d3d11_t,
viewport: libra_viewport_t,
out: *const ID3D11RenderTargetView,
mvp: *const f32,
opt: *const FrameOptionsD3D11,
) -> libra_error_t;
/// Draw a frame with the given parameters for the given filter chain. /// Draw a frame with the given parameters for the given filter chain.
/// ///
/// ## Safety /// ## Safety
@ -86,16 +111,15 @@ pub unsafe extern "C" fn libra_d3d11_filter_chain_create(preset: *mut libra_shad
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t` /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct. /// struct.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_d3d11_filter_chain_frame(chain: *mut libra_d3d11_filter_chain_t, pub unsafe extern "C" fn libra_d3d11_filter_chain_frame(
chain: *mut libra_d3d11_filter_chain_t,
frame_count: usize, frame_count: usize,
image: libra_source_image_d3d11_t, image: libra_source_image_d3d11_t,
viewport: libra_viewport_t, viewport: libra_viewport_t,
out: *const ID3D11RenderTargetView, out: *const ID3D11RenderTargetView,
mvp: *const f32, mvp: *const f32,
opt: *const FrameOptionsD3D11, opt: *const FrameOptionsD3D11,
) -> libra_error_t { ) -> libra_error_t {
ffi_body!(mut |chain| { ffi_body!(mut |chain| {
assert_some_ptr!(mut chain); assert_some_ptr!(mut chain);
assert_non_null!(out); assert_non_null!(out);
@ -125,13 +149,18 @@ pub unsafe extern "C" fn libra_d3d11_filter_chain_frame(chain: *mut libra_d3d11_
}) })
} }
pub type PFN_lbr_d3d11_filter_chain_free = unsafe extern "C" fn(
chain: *mut libra_d3d11_filter_chain_t,
) -> libra_error_t;
/// Free a D3D11 filter chain. /// Free a D3D11 filter chain.
/// ///
/// The resulting value in `chain` then becomes null. /// The resulting value in `chain` then becomes null.
/// ## Safety /// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`. /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_d3d11_filter_chain_free(chain: *mut libra_d3d11_filter_chain_t) -> libra_error_t { pub unsafe extern "C" fn libra_d3d11_filter_chain_free(
chain: *mut libra_d3d11_filter_chain_t,
) -> libra_error_t {
ffi_body!({ ffi_body!({
assert_non_null!(chain); assert_non_null!(chain);
unsafe { unsafe {

View file

@ -1,20 +1,23 @@
use std::ffi::{c_char, c_void, CString}; use crate::ctypes::{
use std::mem::MaybeUninit; 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_ptr, LibrashaderError}; use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::ffi_body; use crate::ffi::ffi_body;
use librashader::runtime::gl::{GLImage, Viewport};
use librashader::runtime::FilterChain;
use std::ffi::{c_char, c_void, CString};
use std::mem::MaybeUninit;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use librashader::runtime::FilterChain;
use librashader::runtime::gl::{GLImage, Viewport};
pub use librashader::runtime::gl::options::FilterChainOptionsGL; pub use librashader::runtime::gl::options::FilterChainOptionsGL;
pub use librashader::runtime::gl::options::FrameOptionsGL; pub use librashader::runtime::gl::options::FrameOptionsGL;
use librashader::Size; use librashader::Size;
/// A GL function loader that librashader needs to be initialized with. /// A GL function loader that librashader needs to be initialized with.
pub type gl_loader_t = unsafe extern "C" fn (*const c_char) -> *const c_void; pub type gl_loader_t = unsafe extern "C" fn(*const c_char) -> *const c_void;
pub type PFN_lbr_gl_init_context = unsafe extern "C" fn(loader: gl_loader_t) -> libra_error_t;
/// Initialize the OpenGL Context for librashader. /// Initialize the OpenGL Context for librashader.
/// ///
/// ## Safety /// ## Safety
@ -24,16 +27,19 @@ pub type gl_loader_t = unsafe extern "C" fn (*const c_char) -> *const c_void;
/// chain objects, and drawing with them causes immediate undefined behaviour. /// chain objects, and drawing with them causes immediate undefined behaviour.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_gl_init_context(loader: gl_loader_t) -> libra_error_t { pub unsafe extern "C" fn libra_gl_init_context(loader: gl_loader_t) -> libra_error_t {
gl::load_with(|s| { gl::load_with(|s| unsafe {
unsafe {
let proc_name = CString::new(s).unwrap_unchecked(); let proc_name = CString::new(s).unwrap_unchecked();
loader(proc_name.as_ptr()) loader(proc_name.as_ptr())
}
}); });
LibrashaderError::ok() LibrashaderError::ok()
} }
pub type PFN_lbr_gl_filter_chain_create = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptionsGL,
out: *mut MaybeUninit<libra_gl_filter_chain_t>,
) -> libra_error_t;
/// Create the filter chain given the shader preset. /// Create the filter chain given the shader preset.
/// ///
/// The shader preset is immediately invalidated and must be recreated after /// The shader preset is immediately invalidated and must be recreated after
@ -44,9 +50,11 @@ 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` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_gl_filter_chain_create(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 = unsafe { let preset = unsafe {
@ -61,11 +69,12 @@ pub unsafe extern "C" fn libra_gl_filter_chain_create(preset: *mut libra_shader_
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(NonNull::new(Box::into_raw(Box::new(chain))))) out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
} }
}) })
} }
@ -80,7 +89,7 @@ pub struct libra_source_image_gl_t {
/// The width of the source image. /// The width of the source image.
pub width: u32, pub width: u32,
/// The height of the source image. /// The height of the source image.
pub height: u32 pub height: u32,
} }
/// OpenGL parameters for the output framebuffer. /// OpenGL parameters for the output framebuffer.
@ -100,11 +109,21 @@ impl From<libra_source_image_gl_t> for GLImage {
handle: value.handle, handle: value.handle,
format: value.format, format: value.format,
size: Size::new(value.width, value.height), size: Size::new(value.width, value.height),
padded_size: Size::default() padded_size: Size::default(),
} }
} }
} }
pub type PFN_lbr_gl_filter_chain_frame = unsafe extern "C" fn(
chain: *mut libra_gl_filter_chain_t,
frame_count: usize,
image: libra_source_image_gl_t,
viewport: libra_viewport_t,
out: libra_draw_framebuffer_gl_t,
mvp: *const f32,
opt: *const FrameOptionsGL,
) -> libra_error_t;
/// Draw a frame with the given parameters for the given filter chain. /// Draw a frame with the given parameters for the given filter chain.
/// ///
/// ## Safety /// ## Safety
@ -115,14 +134,14 @@ impl From<libra_source_image_gl_t> for GLImage {
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t` /// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct. /// struct.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_gl_filter_chain_frame(chain: *mut libra_gl_filter_chain_t, pub unsafe extern "C" fn libra_gl_filter_chain_frame(
chain: *mut libra_gl_filter_chain_t,
frame_count: usize, frame_count: usize,
image: libra_source_image_gl_t, image: libra_source_image_gl_t,
viewport: libra_viewport_t, viewport: libra_viewport_t,
out: libra_draw_framebuffer_gl_t, out: libra_draw_framebuffer_gl_t,
mvp: *const f32, mvp: *const f32,
opt: *const FrameOptionsGL, opt: *const FrameOptionsGL,
) -> libra_error_t { ) -> libra_error_t {
ffi_body!(mut |chain| { ffi_body!(mut |chain| {
assert_some_ptr!(mut chain); assert_some_ptr!(mut chain);
@ -150,6 +169,9 @@ pub unsafe extern "C" fn libra_gl_filter_chain_frame(chain: *mut libra_gl_filter
}) })
} }
pub type PFN_lbr_gl_filter_chain_free = unsafe extern "C" fn(
chain: *mut libra_gl_filter_chain_t,
)-> libra_error_t;
/// Free a GL filter chain. /// Free a GL filter chain.
/// ///
@ -157,7 +179,9 @@ pub unsafe extern "C" fn libra_gl_filter_chain_frame(chain: *mut libra_gl_filter
/// ## Safety /// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`. /// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn libra_gl_filter_chain_free(chain: *mut libra_gl_filter_chain_t) -> libra_error_t { pub unsafe extern "C" fn libra_gl_filter_chain_free(
chain: *mut libra_gl_filter_chain_t,
) -> libra_error_t {
ffi_body!({ ffi_body!({
assert_non_null!(chain); assert_non_null!(chain);
unsafe { unsafe {