capi: use extern_ffi where possible

This commit is contained in:
chyyran 2023-01-13 16:05:13 -05:00
parent 946fe11c69
commit f25693815b
13 changed files with 591 additions and 902 deletions

View file

@ -44,4 +44,4 @@ features = [
optional = true
[package.metadata.cargo-post.dependencies]
cbindgen = "0.24.3"
cbindgen = { git = "https://github.com/eqrion/cbindgen" }

View file

@ -4,7 +4,14 @@ include_guard = "__LIBRASHADER_H__"
pragma_once = true
usize_is_size_t = true
documentation_style = "c++"
after_includes = "#ifdef _WIN32\n#include <d3d11.h>\n#else\ntypedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;\n#endif"
after_includes = "#ifdef _WIN32 && RUNTIME_D3D11 \n#include <d3d11.h>\n#else\ntypedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;\n#endif"
[defines]
"feature = runtime-opengl" = "LIBRA_RUNTIME_OPENGL"
"feature = runtime-d3d11" = "LIBRA_RUNTIME_D3D11"
[parse]
parse_deps = true
include = ["librashader",
@ -14,7 +21,7 @@ include = ["librashader",
"librashader-runtime-gl",
"librashader-runtime-d3d11"
]
expand = ["librashader-capi"]
[struct]
@ -25,35 +32,32 @@ prefix_with_name = true
[export]
include = [
# preset
"PFN_lbr_load_preset",
"PFN_lbr_preset_free",
"PFN_lbr_preset_set_param",
"PFN_lbr_preset_get_param",
"PFN_lbr_preset_print",
"PFN_lbr_preset_get_runtime_param_names",
"PFN_libra_load_preset",
"PFN_libra_preset_free",
"PFN_libra_preset_set_param",
"PFN_libra_preset_get_param",
"PFN_libra_preset_print",
"PFN_libra_preset_get_runtime_param_names",
# error
"PFN_lbr_error_errno",
"PFN_lbr_error_print",
"PFN_lbr_error_free",
"PFN_lbr_error_write",
"PFN_lbr_error_free_string",
"PFN_libra_error_errno",
"PFN_libra_error_print",
"PFN_libra_error_free",
"PFN_libra_error_write",
"PFN_libra_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",
"PFN_libra_gl_init_context",
"PFN_libra_gl_filter_chain_create",
"PFN_libra_gl_filter_chain_frame",
"PFN_libra_gl_filter_chain_free",
# d3d11
"PFN_lbr_d3d11_filter_chain_create",
"PFN_lbr_d3d11_filter_chain_frame",
"PFN_lbr_d3d11_filter_chain_free"
"PFN_libra_d3d11_filter_chain_create",
"PFN_libra_d3d11_filter_chain_frame",
"PFN_libra_d3d11_filter_chain_free",
]
#exclude = ["LibrashaderError"]
#
[export.rename]
"LibrashaderError" = "_libra_error"
"ShaderPreset" = "_shader_preset"

View file

@ -8,32 +8,31 @@
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#ifdef _WIN32
#ifdef _WIN32 && RUNTIME_D3D11
#include <d3d11.h>
#else
typedef void ID3D11Device;typedef void ID3D11RenderTargetView;typedef void ID3D1ShaderResourceView;
typedef void ID3D11Device; typedef void ID3D11RenderTargetView; typedef void ID3D1ShaderResourceView;
#endif
/// Error codes for librashader error types.
enum LIBRA_ERRNO
#ifdef __cplusplus
: int32_t
: int32_t
#endif // __cplusplus
{
LIBRA_ERRNO_UNKNOWN_ERROR = 0,
LIBRA_ERRNO_INVALID_PARAMETER = 1,
LIBRA_ERRNO_INVALID_PATH = 2,
LIBRA_ERRNO_PRESET_ERROR = 3,
LIBRA_ERRNO_PREPROCESS_ERROR = 4,
LIBRA_ERRNO_RUNTIME_ERROR = 5,
{
LIBRA_ERRNO_UNKNOWN_ERROR = 0,
LIBRA_ERRNO_INVALID_PARAMETER = 1,
LIBRA_ERRNO_INVALID_PATH = 2,
LIBRA_ERRNO_PRESET_ERROR = 3,
LIBRA_ERRNO_PREPROCESS_ERROR = 4,
LIBRA_ERRNO_RUNTIME_ERROR = 5,
};
#ifndef __cplusplus
typedef int32_t LIBRA_ERRNO;
#endif // __cplusplus
typedef struct _filter_chain_d3d11 _filter_chain_d3d11;
typedef struct _filter_chain_gl _filter_chain_gl;
/// A Direct3D 11 filter chain.
typedef struct FilterChain FilterChain;
/// The error type for librashader.
typedef struct _libra_error _libra_error;
@ -44,297 +43,346 @@ typedef struct _libra_error _libra_error;
/// parameter metadata.
typedef struct _shader_preset _shader_preset;
typedef struct _libra_error *libra_error_t;
typedef struct _libra_error* libra_error_t;
typedef struct _shader_preset *libra_shader_preset_t;
typedef struct _shader_preset* libra_shader_preset_t;
#if defined(RUNTIME_OPENGL)
/// A GL function loader that librashader needs to be initialized with.
typedef const void *(*gl_loader_t)(const char*);
typedef const void* (*gl_loader_t)(const char*);
#endif
/// Options for filter chain creation.
typedef struct filter_chain_gl_opt_t {
/// The GLSL version. Should be at least `330`.
uint16_t gl_version;
/// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
bool use_dsa;
} filter_chain_gl_opt_t;
/// Options for Direct3D11 filter chain creation.
typedef struct FilterChainOptions {
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
bool use_deferred_context;
/// Whether or not to explicitly disable mipmap
/// generation regardless of shader preset settings.
bool force_no_mipmaps;
} FilterChainOptions;
typedef struct _filter_chain_gl *libra_gl_filter_chain_t;
#if defined(RUNTIME_OPENGL)
typedef struct FilterChain* libra_gl_filter_chain_t;
#endif
#if defined(RUNTIME_OPENGL)
/// OpenGL parameters for the source image.
typedef struct libra_source_image_gl_t {
/// A texture GLuint to the source image.
uint32_t handle;
/// The format of the source image.
uint32_t format;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
/// A texture GLuint to the source image.
uint32_t handle;
/// The format of the source image.
uint32_t format;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
} libra_source_image_gl_t;
#endif
/// Parameters for the output viewport.
typedef struct libra_viewport_t {
float x;
float y;
uint32_t width;
uint32_t height;
float x;
float y;
uint32_t width;
uint32_t height;
} libra_viewport_t;
#if defined(RUNTIME_OPENGL)
/// OpenGL parameters for the output framebuffer.
typedef struct libra_draw_framebuffer_gl_t {
/// A framebuffer GLuint to the output framebuffer.
uint32_t handle;
/// A texture GLuint to the logical buffer of the output framebuffer.
uint32_t texture;
/// The format of the output framebuffer.
uint32_t format;
/// A framebuffer GLuint to the output framebuffer.
uint32_t handle;
/// A texture GLuint to the logical buffer of the output framebuffer.
uint32_t texture;
/// The format of the output framebuffer.
uint32_t format;
} libra_draw_framebuffer_gl_t;
/// Options for each OpenGL shader frame.
typedef struct frame_gl_opt_t {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} frame_gl_opt_t;
/// Options for Direct3D11 filter chain creation.
typedef struct filter_chain_d3d11_opt_t {
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
bool use_deferred_context;
} filter_chain_d3d11_opt_t;
typedef struct _filter_chain_d3d11 *libra_d3d11_filter_chain_t;
/// OpenGL parameters for the source image.
typedef struct libra_source_image_d3d11_t {
/// A shader resource view into the source image
const ID3D11ShaderResourceView *handle;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
} libra_source_image_d3d11_t;
#endif
/// Options for each Direct3D11 shader frame.
typedef struct frame_d3d11_opt_t {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} frame_d3d11_opt_t;
typedef struct FrameOptions {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} FrameOptions;
typedef libra_error_t (*PFN_lbr_preset_free)(libra_shader_preset_t *preset);
#if defined(RUNTIME_D3D11)
typedef struct FilterChain* libra_d3d11_filter_chain_t;
#endif
typedef libra_error_t (*PFN_lbr_preset_set_param)(libra_shader_preset_t *preset, const char *name, float value);
#if defined(RUNTIME_D3D11)
/// OpenGL parameters for the source image.
typedef struct libra_source_image_d3d11_t {
/// A shader resource view into the source image
const ID3D11ShaderResourceView* handle;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
} libra_source_image_d3d11_t;
#endif
typedef libra_error_t (*PFN_lbr_preset_get_param)(libra_shader_preset_t *preset, const char *name, float *value);
typedef libra_error_t(*PFN_libra_preset_free)(libra_shader_preset_t* preset);
typedef libra_error_t (*PFN_lbr_preset_print)(libra_shader_preset_t *preset);
typedef libra_error_t(*PFN_libra_preset_set_param)(libra_shader_preset_t* preset,
const char* name,
float value);
typedef libra_error_t (*PFN_lbr_preset_get_runtime_param_names)(libra_shader_preset_t *preset, const char **value);
typedef libra_error_t(*PFN_libra_preset_get_param)(libra_shader_preset_t* preset,
const char* name,
float* value);
typedef LIBRA_ERRNO (*PFN_lbr_error_errno)(libra_error_t error);
typedef libra_error_t(*PFN_libra_preset_print)(libra_shader_preset_t* preset);
typedef int32_t (*PFN_lbr_error_print)(libra_error_t error);
typedef libra_error_t(*PFN_libra_preset_get_runtime_param_names)(libra_shader_preset_t* preset,
const char** value);
typedef int32_t (*PFN_lbr_error_free)(libra_error_t *error);
typedef LIBRA_ERRNO(*PFN_libra_error_errno)(libra_error_t error);
typedef int32_t (*PFN_lbr_error_write)(libra_error_t error, char **out);
typedef int32_t(*PFN_libra_error_print)(libra_error_t error);
typedef int32_t (*PFN_lbr_error_free_string)(char **out);
typedef int32_t(*PFN_libra_error_free)(libra_error_t* error);
typedef libra_error_t (*PFN_lbr_gl_init_context)(gl_loader_t loader);
typedef int32_t(*PFN_libra_error_write)(libra_error_t error, char** out);
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 int32_t(*PFN_libra_error_free_string)(char** 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);
#if defined(RUNTIME_OPENGL)
typedef libra_error_t(*PFN_libra_gl_init_context)(gl_loader_t loader);
#endif
typedef libra_error_t (*PFN_lbr_gl_filter_chain_free)(libra_gl_filter_chain_t *chain);
#if defined(RUNTIME_OPENGL)
typedef libra_error_t(*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
libra_gl_filter_chain_t* out);
#endif
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);
#if defined(RUNTIME_OPENGL)
typedef libra_error_t(*PFN_libra_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 FrameOptions* opt);
#endif
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);
#if defined(RUNTIME_OPENGL)
typedef libra_error_t(*PFN_libra_gl_filter_chain_free)(libra_gl_filter_chain_t* chain);
#endif
typedef libra_error_t (*PFN_lbr_d3d11_filter_chain_free)(libra_d3d11_filter_chain_t *chain);
#if defined(RUNTIME_D3D11)
typedef libra_error_t(*PFN_libra_d3d11_filter_chain_create)(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
const ID3D11Device* device,
libra_d3d11_filter_chain_t* out);
#endif
#if defined(RUNTIME_D3D11)
typedef libra_error_t(*PFN_libra_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 FrameOptions* opt);
#endif
#if defined(RUNTIME_D3D11)
typedef libra_error_t(*PFN_libra_d3d11_filter_chain_free)(libra_d3d11_filter_chain_t* chain);
#endif
#ifdef __cplusplus
extern "C" {
#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);
/// 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);
/// 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);
/// 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);
/// 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);
/// 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.
///
/// ## Safety
/// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset.
/// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`.
/// ## Returns
/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`.
libra_error_t libra_preset_create(const char *filename,
libra_shader_preset_t *out);
/// Load a preset.
///
/// ## Safety
/// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset.
/// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`.
/// ## Returns
/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`.
libra_error_t libra_preset_create(const char* filename,
libra_shader_preset_t* out);
/// Free the preset.
///
/// If `preset` is null, this function does nothing. The resulting value in `preset` then becomes
/// null.
///
/// ## Safety
/// - `preset` must be a valid and aligned pointer to a shader preset.
libra_error_t libra_preset_free(libra_shader_preset_t *preset);
/// Free the preset.
///
/// If `preset` is null, this function does nothing. The resulting value in `preset` then becomes
/// null.
///
/// ## Safety
/// - `preset` must be a valid and aligned pointer to a shader preset.
libra_error_t libra_preset_free(libra_shader_preset_t* preset);
/// Set the value of the parameter in the preset.
///
/// ## Safety
/// - `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.
libra_error_t libra_preset_set_param(libra_shader_preset_t *preset, const char *name, float value);
/// Set the value of the parameter in the preset.
///
/// ## Safety
/// - `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.
libra_error_t libra_preset_set_param(libra_shader_preset_t* preset, const char* name, float value);
/// Get the value of the parameter as set in the preset.
///
/// ## Safety
/// - `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.
/// - `value` may be a pointer to a uninitialized `float`.
libra_error_t libra_preset_get_param(libra_shader_preset_t *preset, const char *name, float *value);
/// Get the value of the parameter as set in the preset.
///
/// ## Safety
/// - `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.
/// - `value` may be a pointer to a uninitialized `float`.
libra_error_t libra_preset_get_param(libra_shader_preset_t* preset, const char* name, float* value);
/// Pretty print the shader preset.
///
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
libra_error_t libra_preset_print(libra_shader_preset_t *preset);
/// Pretty print the shader preset.
///
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
libra_error_t libra_preset_print(libra_shader_preset_t* preset);
/// Get a list of runtime parameter names.
///
/// The returned value can not currently be freed.
/// This function should be considered in progress. Its use is discouraged.
libra_error_t libra_preset_get_runtime_param_names(libra_shader_preset_t *preset,
const char **value);
/// Get a list of runtime parameter names.
///
/// The returned value can not currently be freed.
/// This function should be considered in progress. Its use is discouraged.
libra_error_t libra_preset_get_runtime_param_names(libra_shader_preset_t* preset,
const char** value);
/// Initialize the OpenGL Context for librashader.
///
/// ## Safety
/// 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.
libra_error_t libra_gl_init_context(gl_loader_t loader);
#if defined(RUNTIME_OPENGL)
/// Initialize the OpenGL Context for librashader.
///
/// ## Safety
/// 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.
libra_error_t libra_gl_init_context(gl_loader_t loader);
#endif
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
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);
#if defined(RUNTIME_OPENGL)
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
libra_gl_filter_chain_t* out);
#endif
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_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);
#if defined(RUNTIME_OPENGL)
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_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 FrameOptions* opt);
#endif
/// Free a GL filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain);
#if defined(RUNTIME_OPENGL)
/// Free a GL filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t* chain);
#endif
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
libra_error_t libra_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);
#if defined(RUNTIME_D3D11)
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
libra_error_t libra_d3d11_filter_chain_create(libra_shader_preset_t* preset,
const struct FilterChainOptions* options,
const ID3D11Device* device,
libra_d3d11_filter_chain_t* out);
#endif
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_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);
#if defined(RUNTIME_D3D11)
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_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 FrameOptions* opt);
#endif
/// Free a D3D11 filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `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);
#if defined(RUNTIME_D3D11)
/// Free a D3D11 filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `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);
#endif
#ifdef __cplusplus
} // extern "C"

View file

@ -1,7 +1,7 @@
use std::{env, fs};
use std::fs::File;
use std::io::{BufWriter, Write};
use std::path::{Path, PathBuf};
use std::path::PathBuf;
pub fn main() {
// Do not update files on docsrs

View file

@ -1,6 +1,6 @@
//! The librashader error C API. (`libra_error_*`).
use std::any::Any;
use std::ffi::{c_char, CStr, CString};
use std::ffi::{c_char, CString};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
use thiserror::Error;
@ -42,7 +42,9 @@ pub enum LIBRA_ERRNO {
RUNTIME_ERROR = 5,
}
pub type PFN_lbr_error_errno = extern "C" fn(error: libra_error_t) -> LIBRA_ERRNO;
// Nothing here can use extern_fn because they are lower level than libra_error_t.
pub type PFN_libra_error_errno = extern "C" fn(error: libra_error_t) -> LIBRA_ERRNO;
#[no_mangle]
/// Get the error code corresponding to this error object.
///
@ -56,7 +58,7 @@ pub extern "C" fn libra_error_errno(error: libra_error_t) -> LIBRA_ERRNO {
unsafe { error.as_ref().get_code() }
}
pub type PFN_lbr_error_print = extern "C" fn(error: libra_error_t) -> i32;
pub type PFN_libra_error_print = extern "C" fn(error: libra_error_t) -> i32;
#[no_mangle]
/// Print the error message.
///
@ -74,7 +76,7 @@ pub extern "C" fn libra_error_print(error: libra_error_t) -> i32 {
return 0;
}
pub type PFN_lbr_error_free = extern "C" fn(error: *mut libra_error_t) -> i32;
pub type PFN_libra_error_free = extern "C" fn(error: *mut libra_error_t) -> i32;
#[no_mangle]
/// Frees any internal state kept by the error.
///
@ -87,7 +89,7 @@ pub extern "C" fn libra_error_free(error: *mut libra_error_t) -> i32 {
return 1;
}
let mut error = unsafe { &mut *error };
let error = unsafe { &mut *error };
let error = error.take();
let Some(error) = error else {
return 1;
@ -97,7 +99,7 @@ pub extern "C" fn libra_error_free(error: *mut libra_error_t) -> i32 {
return 0;
}
pub type PFN_lbr_error_write =
pub type PFN_libra_error_write =
extern "C" fn(error: libra_error_t, out: *mut MaybeUninit<*mut c_char>) -> i32;
#[no_mangle]
/// Writes the error message into `out`
@ -128,7 +130,7 @@ pub extern "C" fn libra_error_write(
return 0;
}
pub type PFN_lbr_error_free_string = extern "C" fn(out: *mut *mut c_char) -> i32;
pub type PFN_libra_error_free_string = extern "C" fn(out: *mut *mut c_char) -> i32;
#[no_mangle]
/// Frees an error string previously allocated by `libra_error_write`.
///
@ -194,13 +196,14 @@ macro_rules! assert_non_null {
}
};
}
macro_rules! assert_some {
($value:ident) => {
if $value.is_none() {
return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
}
};
}
// macro_rules! assert_some {
// ($value:ident) => {
// if $value.is_none() {
// return $crate::error::LibrashaderError::InvalidParameter(stringify!($value)).export();
// }
// };
// }
macro_rules! assert_some_ptr {
($value:ident) => {
@ -221,5 +224,5 @@ macro_rules! assert_some_ptr {
use crate::ctypes::libra_error_t;
pub(crate) use assert_non_null;
pub(crate) use assert_some;
// pub(crate) use assert_some;
pub(crate) use assert_some_ptr;

View file

@ -65,10 +65,57 @@ macro_rules! extern_fn {
#[no_mangle]
$(#[$($attrss)*])*
fn $func_name($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t {
pub extern "C" fn $func_name($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t {
$crate::ffi::ffi_body!($body)
}
}
};
($(#[$($attrss:tt)*])* raw fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) $body:block) => {
paste::paste! {
pub type [<PFN_ $func_name>] = unsafe extern "C" fn($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t;
}
#[no_mangle]
$(#[$($attrss)*])*
pub extern "C" fn $func_name($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t {
$body
}
};
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) |$($ref_capture:ident),*|; mut |$($mut_capture:ident),*| $body:block) => {
paste::paste! {
pub type [<PFN_ $func_name>] = unsafe extern "C" fn($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t;
}
#[no_mangle]
$(#[$($attrss)*])*
pub extern "C" fn $func_name($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t {
$crate::ffi::ffi_body!(|$($ref_capture),*|; mut |$($mut_capture),*| $body)
}
};
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) mut |$($mut_capture:ident),*| $body:block) => {
paste::paste! {
pub type [<PFN_ $func_name>] = unsafe extern "C" fn($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t;
}
#[no_mangle]
$(#[$($attrss)*])*
pub extern "C" fn $func_name($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t {
$crate::ffi::ffi_body!(mut |$($mut_capture),*| $body)
}
};
($(#[$($attrss:tt)*])* fn $func_name:ident ($($arg_name:ident : $arg_ty:ty),*) |$($ref_capture:ident),*| $body:block) => {
paste::paste! {
pub type [<PFN_ $func_name>] = unsafe extern "C" fn($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t;
}
#[no_mangle]
$(#[$($attrss)*])*
pub extern "C" fn $func_name($($arg_name: $arg_ty,)*) -> $crate::ctypes::libra_error_t {
$crate::ffi::ffi_body!(|$($ref_capture),*| $body)
}
};
}
pub(crate) use extern_fn;

View file

@ -38,11 +38,12 @@
#![feature(vec_into_raw_parts)]
#![deny(unsafe_op_in_unsafe_fn)]
use std::os::raw::c_char;
pub mod ctypes;
pub mod error;
mod ffi;
pub mod presets;
#[cfg(feature = "reflect")]
pub mod reflect;
pub mod runtime;

View file

@ -1,7 +1,7 @@
//! The librashader preset C API (`libra_preset_*`).
use crate::ctypes::{libra_error_t, libra_shader_preset_t};
use crate::error::{assert_non_null, assert_some, assert_some_ptr, LibrashaderError};
use crate::ffi::ffi_body;
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::{extern_fn, ffi_body};
use librashader::presets::ShaderPreset;
use std::ffi::{c_char, CStr, CString};
use std::mem::MaybeUninit;
@ -12,76 +12,63 @@ pub type PFN_lbr_preset_create = unsafe extern "C" fn(
out: *mut MaybeUninit<libra_shader_preset_t>,
) -> libra_error_t;
/// Load a preset.
///
/// ## Safety
/// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset.
/// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`.
/// ## Returns
/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`.
#[no_mangle]
pub unsafe extern "C" fn libra_preset_create(
filename: *const c_char,
out: *mut MaybeUninit<libra_shader_preset_t>,
) -> libra_error_t {
ffi_body!({
extern_fn! {
/// Load a preset.
///
/// ## Safety
/// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset.
/// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`.
/// ## Returns
/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`.
fn libra_preset_create(
filename: *const c_char,
out: *mut MaybeUninit<libra_shader_preset_t>
) {
assert_non_null!(filename);
assert_non_null!(out);
let filename = unsafe { CStr::from_ptr(filename) };
let filename = filename.to_str()?;
println!("loading {filename}");
let preset = ShaderPreset::try_parse(filename)?;
let preset = ShaderPreset::try_parse(filename)?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
preset,
)))))
}
})
}
}
pub type PFN_lbr_preset_free =
unsafe extern "C" fn(preset: *mut libra_shader_preset_t) -> libra_error_t;
/// Free the preset.
///
/// If `preset` is null, this function does nothing. The resulting value in `preset` then becomes
/// null.
///
/// ## Safety
/// - `preset` must be a valid and aligned pointer to a shader preset.
#[no_mangle]
pub unsafe extern "C" fn libra_preset_free(preset: *mut libra_shader_preset_t) -> libra_error_t {
ffi_body!({
extern_fn! {
/// Free the preset.
///
/// If `preset` is null, this function does nothing. The resulting value in `preset` then becomes
/// null.
///
/// ## Safety
/// - `preset` must be a valid and aligned pointer to a shader preset.
fn libra_preset_free(preset: *mut libra_shader_preset_t) {
assert_non_null!(preset);
unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
drop(Box::from_raw(preset.unwrap().as_ptr()));
}
})
}
}
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.
///
/// ## Safety
/// - `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.
#[no_mangle]
pub unsafe extern "C" fn libra_preset_set_param(
preset: *mut libra_shader_preset_t,
name: *const c_char,
value: f32,
) -> libra_error_t {
ffi_body!(|name|; mut |preset| {
extern_fn! {
/// Set the value of the parameter in the preset.
///
/// ## Safety
/// - `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.
fn libra_preset_set_param(
preset: *mut libra_shader_preset_t,
name: *const c_char,
value: f32
) |name|; mut |preset| {
let name = unsafe {
CStr::from_ptr(name)
};
@ -92,30 +79,22 @@ pub unsafe extern "C" fn libra_preset_set_param(
if let Some(param) = preset.parameters.iter_mut().find(|c| c.name == name) {
param.value = value
}
})
}
}
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.
///
/// ## Safety
/// - `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.
/// - `value` may be a pointer to a uninitialized `float`.
#[no_mangle]
pub unsafe extern "C" fn libra_preset_get_param(
preset: *mut libra_shader_preset_t,
name: *const c_char,
value: *mut MaybeUninit<f32>,
) -> libra_error_t {
ffi_body!(|name, preset| {
extern_fn! {
/// Get the value of the parameter as set in the preset.
///
/// ## Safety
/// - `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.
/// - `value` may be a pointer to a uninitialized `float`.
fn libra_preset_get_param(
preset: *mut libra_shader_preset_t,
name: *const c_char,
value: *mut MaybeUninit<f32>
) |name, preset| {
let name = unsafe { CStr::from_ptr(name) };
let name = name.to_str()?;
assert_some_ptr!(preset);
@ -124,25 +103,22 @@ pub unsafe extern "C" fn libra_preset_get_param(
if let Some(param) = preset.parameters.iter().find(|c| c.name == name) {
unsafe { value.write(MaybeUninit::new(param.value)) }
}
})
}
}
pub type PFN_lbr_preset_print =
unsafe extern "C" fn(preset: *mut libra_shader_preset_t) -> libra_error_t;
/// Pretty print the shader preset.
///
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
#[no_mangle]
pub unsafe extern "C" fn libra_preset_print(preset: *mut libra_shader_preset_t) -> libra_error_t {
ffi_body!(|preset| {
extern_fn! {
/// Pretty print the shader preset.
///
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
fn libra_preset_print(preset: *mut libra_shader_preset_t) |preset| {
assert_some_ptr!(preset);
println!("{:#?}", preset);
})
}
}
pub type PFN_lbr_preset_get_runtime_param_names = unsafe extern "C" fn(
// can't use extern_fn! for this because of the mut.
pub type PFN_libra_preset_get_runtime_param_names = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
value: MaybeUninit<*mut *const c_char>,
) -> libra_error_t;
@ -168,6 +144,7 @@ pub unsafe extern "C" fn libra_preset_get_runtime_param_names(
}
let (parts, _len, _cap) = c_strings.into_raw_parts();
value.write(parts);
})
}

View file

@ -12,7 +12,6 @@ use librashader::reflect::{
};
use librashader::{FilterMode, WrapMode};
use rustc_hash::FxHashMap;
use std::error::Error;
pub(crate) struct LookupTexture {
wrap_mode: WrapMode,

View file

@ -1,8 +1,8 @@
use crate::ctypes::{
libra_d3d11_filter_chain_t, libra_error_t, libra_shader_preset_t, libra_viewport_t,
libra_d3d11_filter_chain_t, libra_shader_preset_t, libra_viewport_t,
};
use crate::error::{assert_non_null, assert_some_ptr, LibrashaderError};
use crate::ffi::ffi_body;
use crate::ffi::extern_fn;
use librashader::runtime::d3d11::{D3D11InputView, D3D11OutputView};
use std::mem::MaybeUninit;
use std::ptr::NonNull;
@ -41,29 +41,22 @@ impl TryFrom<libra_source_image_d3d11_t> for D3D11InputView {
}
}
pub type PFN_lbr_d3d11_filter_chain_create = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptions,
device: *const ID3D11Device,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>,
) -> libra_error_t;
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
#[no_mangle]
pub unsafe extern "C" fn libra_d3d11_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptions,
device: *const ID3D11Device,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>,
) -> libra_error_t {
ffi_body!({
extern_fn! {
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
fn libra_d3d11_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptions,
device: *const ID3D11Device,
out: *mut MaybeUninit<libra_d3d11_filter_chain_t>
) {
assert_non_null!(preset);
assert_non_null!(device);
let preset = unsafe {
@ -89,39 +82,28 @@ pub unsafe extern "C" fn libra_d3d11_filter_chain_create(
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 FrameOptions,
) -> libra_error_t;
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
#[no_mangle]
pub unsafe extern "C" fn libra_d3d11_filter_chain_frame(
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 FrameOptions,
) -> libra_error_t {
ffi_body!(mut |chain| {
extern_fn! {
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
fn libra_d3d11_filter_chain_frame(
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 FrameOptions
) mut |chain| {
assert_some_ptr!(mut chain);
assert_non_null!(out);
@ -149,26 +131,21 @@ pub unsafe extern "C" fn libra_d3d11_filter_chain_frame(
let image = image.try_into()?;
chain.frame(image, &viewport, frame_count, opt.as_ref())?;
})
}
}
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.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`.
#[no_mangle]
pub unsafe extern "C" fn libra_d3d11_filter_chain_free(
chain: *mut libra_d3d11_filter_chain_t,
) -> libra_error_t {
ffi_body!({
extern_fn! {
/// Free a D3D11 filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_d3d11_filter_chain_t`.
fn libra_d3d11_filter_chain_free(chain: *mut libra_d3d11_filter_chain_t) {
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

@ -1,8 +1,8 @@
use crate::ctypes::{
libra_error_t, libra_gl_filter_chain_t, libra_shader_preset_t, libra_viewport_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::ffi::ffi_body;
use crate::ffi::extern_fn;
use librashader::runtime::gl::{Framebuffer, GLImage};
use std::ffi::{c_char, c_void, CString};
use std::mem::MaybeUninit;
@ -13,72 +13,9 @@ pub use librashader::runtime::gl::options::FilterChainOptions;
pub use librashader::runtime::gl::options::FrameOptions;
use librashader::runtime::{Size, Viewport};
/// 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 PFN_lbr_gl_init_context = unsafe extern "C" fn(loader: gl_loader_t) -> libra_error_t;
/// Initialize the OpenGL Context for librashader.
///
/// ## Safety
/// 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.
#[no_mangle]
pub unsafe extern "C" fn libra_gl_init_context(loader: gl_loader_t) -> libra_error_t {
gl::load_with(|s| unsafe {
let proc_name = CString::new(s).unwrap_unchecked();
loader(proc_name.as_ptr())
});
LibrashaderError::ok()
}
pub type PFN_lbr_gl_filter_chain_create = unsafe extern "C" fn(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptions,
out: *mut MaybeUninit<libra_gl_filter_chain_t>,
) -> libra_error_t;
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
#[no_mangle]
pub unsafe extern "C" fn libra_gl_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptions,
out: *mut MaybeUninit<libra_gl_filter_chain_t>,
) -> libra_error_t {
ffi_body!({
assert_non_null!(preset);
let preset = unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
None
} else {
Some(unsafe { &*options })
};
let chain = librashader::runtime::gl::FilterChain::load_from_preset(*preset, options)?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
}
})
}
/// OpenGL parameters for the source image.
#[repr(C)]
pub struct libra_source_image_gl_t {
@ -114,51 +51,93 @@ impl From<libra_source_image_gl_t> for GLImage {
}
}
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 FrameOptions,
) -> libra_error_t;
extern_fn! {
/// Initialize the OpenGL Context for librashader.
///
/// ## Safety
/// 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.
raw fn libra_gl_init_context(loader: gl_loader_t) {
gl::load_with(|s| unsafe {
let proc_name = CString::new(s).unwrap_unchecked();
loader(proc_name.as_ptr())
});
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
#[no_mangle]
pub unsafe extern "C" fn libra_gl_filter_chain_frame(
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 FrameOptions,
) -> libra_error_t {
ffi_body!(mut |chain| {
LibrashaderError::ok()
}
}
extern_fn! {
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
fn libra_gl_filter_chain_create(
preset: *mut libra_shader_preset_t,
options: *const FilterChainOptions,
out: *mut MaybeUninit<libra_gl_filter_chain_t>
) {
assert_non_null!(preset);
let preset = unsafe {
let preset_ptr = &mut *preset;
let preset = preset_ptr.take();
Box::from_raw(preset.unwrap().as_ptr())
};
let options = if options.is_null() {
None
} else {
Some(unsafe { &*options })
};
let chain = librashader::runtime::gl::FilterChain::load_from_preset(*preset, options)?;
unsafe {
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain,
)))))
}
}
}
extern_fn! {
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
fn libra_gl_filter_chain_frame(
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 FrameOptions
) mut |chain| {
assert_some_ptr!(mut chain);
let image: GLImage = image.into();
let mvp = if mvp.is_null() {
None
} else {
Some(<&[f32; 16]>::try_from(unsafe { slice::from_raw_parts(mvp, 16) }).unwrap())
};
let opt = if opt.is_null() {
None
} else {
Some(unsafe { opt.read() })
};
let framebuffer = Framebuffer::new_from_raw(out.texture, out.handle, out.format, Size::new(viewport.width, viewport.height), 1);
let viewport = Viewport {
x: viewport.x,
@ -167,27 +146,23 @@ pub unsafe extern "C" fn libra_gl_filter_chain_frame(
mvp,
};
chain.frame(&image, &viewport, frame_count, opt.as_ref())?;
})
}
}
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.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
#[no_mangle]
pub unsafe extern "C" fn libra_gl_filter_chain_free(
chain: *mut libra_gl_filter_chain_t,
) -> libra_error_t {
ffi_body!({
extern_fn! {
/// Free a GL filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
fn libra_gl_filter_chain_free(
chain: *mut libra_gl_filter_chain_t
) {
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

@ -1,343 +0,0 @@
#ifndef __LIBRASHADER_H__
#define __LIBRASHADER_H__
#pragma once
#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.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.
enum LIBRA_ERRNO
#ifdef __cplusplus
: int32_t
#endif // __cplusplus
{
LIBRA_ERRNO_UNKNOWN_ERROR = 0,
LIBRA_ERRNO_INVALID_PARAMETER = 1,
LIBRA_ERRNO_INVALID_PATH = 2,
LIBRA_ERRNO_PRESET_ERROR = 3,
LIBRA_ERRNO_PREPROCESS_ERROR = 4,
LIBRA_ERRNO_RUNTIME_ERROR = 5,
};
#ifndef __cplusplus
typedef int32_t LIBRA_ERRNO;
#endif // __cplusplus
typedef struct _filter_chain_d3d11 _filter_chain_d3d11;
typedef struct _filter_chain_gl _filter_chain_gl;
/// The error type for librashader.
typedef struct _libra_error _libra_error;
/// A shader preset including all specified parameters, textures, and paths to specified shaders.
///
/// A shader preset can be used to create a filter chain runtime instance, or reflected to get
/// parameter metadata.
typedef struct _shader_preset _shader_preset;
typedef struct _libra_error *libra_error_t;
typedef struct _shader_preset *libra_shader_preset_t;
/// A GL function loader that librashader needs to be initialized with.
typedef const void *(*gl_loader_t)(const char*);
/// Options for filter chain creation.
typedef struct filter_chain_gl_opt_t {
/// The GLSL version. Should be at least `330`.
uint16_t gl_version;
/// Whether or not to use the Direct State Access APIs. Only available on OpenGL 4.5+.
bool use_dsa;
} filter_chain_gl_opt_t;
typedef struct _filter_chain_gl *libra_gl_filter_chain_t;
/// OpenGL parameters for the source image.
typedef struct libra_source_image_gl_t {
/// A texture GLuint to the source image.
uint32_t handle;
/// The format of the source image.
uint32_t format;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
} libra_source_image_gl_t;
/// Parameters for the output viewport.
typedef struct libra_viewport_t {
float x;
float y;
uint32_t width;
uint32_t height;
} libra_viewport_t;
/// OpenGL parameters for the output framebuffer.
typedef struct libra_draw_framebuffer_gl_t {
/// A framebuffer GLuint to the output framebuffer.
uint32_t handle;
/// A texture GLuint to the logical buffer of the output framebuffer.
uint32_t texture;
/// The format of the output framebuffer.
uint32_t format;
} libra_draw_framebuffer_gl_t;
/// Options for each OpenGL shader frame.
typedef struct frame_gl_opt_t {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} frame_gl_opt_t;
/// Options for Direct3D11 filter chain creation.
typedef struct filter_chain_d3d11_opt_t {
/// Use a deferred context to record shader rendering state.
///
/// The deferred context will be executed on the immediate context
/// with `RenderContextState = true`.
bool use_deferred_context;
} filter_chain_d3d11_opt_t;
typedef struct _filter_chain_d3d11 *libra_d3d11_filter_chain_t;
/// OpenGL parameters for the source image.
typedef struct libra_source_image_d3d11_t {
/// A shader resource view into the source image
const ID3D11ShaderResourceView *handle;
/// The width of the source image.
uint32_t width;
/// The height of the source image.
uint32_t height;
} libra_source_image_d3d11_t;
/// Options for each Direct3D11 shader frame.
typedef struct frame_d3d11_opt_t {
/// Whether or not to clear the history buffers.
bool clear_history;
/// The direction of the frame. 1 should be vertical.
int32_t frame_direction;
} frame_d3d11_opt_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 *preset, const char *name, float value);
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 *preset);
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
extern "C" {
#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.
///
/// ## Safety
/// - `filename` must be either null or a valid, aligned pointer to a string path to the shader preset.
/// - `out` must be either null, or an aligned pointer to an uninitialized or invalid `libra_shader_preset_t`.
/// ## Returns
/// - If any parameters are null, `out` is unchanged, and this function returns `LIBRA_ERR_INVALID_PARAMETER`.
libra_error_t libra_preset_create(const char *filename,
libra_shader_preset_t *out);
/// Free the preset.
///
/// If `preset` is null, this function does nothing. The resulting value in `preset` then becomes
/// null.
///
/// ## Safety
/// - `preset` must be a valid and aligned pointer to a shader preset.
libra_error_t libra_preset_free(libra_shader_preset_t *preset);
/// Set the value of the parameter in the preset.
///
/// ## Safety
/// - `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.
libra_error_t libra_preset_set_param(libra_shader_preset_t *preset, const char *name, float value);
/// Get the value of the parameter as set in the preset.
///
/// ## Safety
/// - `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.
/// - `value` may be a pointer to a uninitialized `float`.
libra_error_t libra_preset_get_param(libra_shader_preset_t *preset, const char *name, float *value);
/// Pretty print the shader preset.
///
/// ## Safety
/// - `preset` must be null or a valid and aligned pointer to a shader preset.
libra_error_t libra_preset_print(libra_shader_preset_t *preset);
/// Get a list of runtime parameter names.
///
/// The returned value can not currently be freed.
/// This function should be considered in progress. Its use is discouraged.
libra_error_t libra_preset_get_runtime_param_names(libra_shader_preset_t *preset,
const char **value);
/// Initialize the OpenGL Context for librashader.
///
/// ## Safety
/// 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.
libra_error_t libra_gl_init_context(gl_loader_t loader);
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
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);
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_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);
/// Free a GL filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `chain` must be either null or a valid and aligned pointer to an initialized `libra_gl_filter_chain_t`.
libra_error_t libra_gl_filter_chain_free(libra_gl_filter_chain_t *chain);
/// Create the filter chain given the shader preset.
///
/// The shader preset is immediately invalidated and must be recreated after
/// the filter chain is created.
///
/// ## Safety:
/// - `preset` 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.
libra_error_t libra_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);
/// Draw a frame with the given parameters for the given filter chain.
///
/// ## Safety
/// - `chain` may be null, invalid, but not uninitialized. If `chain` is null or invalid, this
/// function will return an error.
/// - `mvp` may be null, or if it is not null, must be an aligned pointer to 16 consecutive `float`
/// values for the model view projection matrix.
/// - `opt` may be null, or if it is not null, must be an aligned pointer to a valid `frame_gl_opt_t`
/// struct.
libra_error_t libra_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);
/// Free a D3D11 filter chain.
///
/// The resulting value in `chain` then becomes null.
/// ## Safety
/// - `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);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif /* __LIBRASHADER_H__ */

View file

@ -4,13 +4,14 @@
#include <iostream>
#include <filesystem>
#include "librashader.h"
#define LIBRA_RUNTIME_OPENGL
#include "../../../../librashader-capi/librashader.h"
int main()
{
std::cout << "Hello World!\n";
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);
auto error = libra_preset_create("../../../slang-shaders/border/gameboy-player/gameboy-player-crt-royale.slangp", &preset);
if (error != NULL) {
std::cout << "error happened\n";
}