capi(gl): update to take opengl context in constructor

This commit is contained in:
chyyran 2024-08-09 03:15:52 -04:00 committed by Ronny Chan
parent 2552d4321b
commit 61fdaeea14
7 changed files with 39 additions and 70 deletions

View file

@ -644,16 +644,11 @@ typedef int32_t (*PFN_libra_error_write)(libra_error_t error, char **out);
/// Function pointer definition for libra_error_free_string /// Function pointer definition for libra_error_free_string
typedef int32_t (*PFN_libra_error_free_string)(char **out); typedef int32_t (*PFN_libra_error_free_string)(char **out);
#if defined(LIBRA_RUNTIME_OPENGL)
/// Function pointer definition for
///libra_gl_init_context
typedef libra_error_t (*PFN_libra_gl_init_context)(libra_gl_loader_t loader);
#endif
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
/// Function pointer definition for /// Function pointer definition for
///libra_gl_filter_chain_create ///libra_gl_filter_chain_create
typedef libra_error_t (*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t *preset, typedef libra_error_t (*PFN_libra_gl_filter_chain_create)(libra_shader_preset_t *preset,
libra_gl_loader_t loader,
const struct filter_chain_gl_opt_t *options, const struct filter_chain_gl_opt_t *options,
libra_gl_filter_chain_t *out); libra_gl_filter_chain_t *out);
#endif #endif
@ -1197,20 +1192,6 @@ libra_error_t libra_preset_get_runtime_params(libra_shader_preset_t *preset,
/// in undefined behaviour. /// in undefined behaviour.
libra_error_t libra_preset_free_runtime_params(struct libra_preset_param_list_t preset); libra_error_t libra_preset_free_runtime_params(struct libra_preset_param_list_t preset);
#if defined(LIBRA_RUNTIME_OPENGL)
/// Initialize the OpenGL Context for librashader.
///
/// This only has to be done once throughout the lifetime of the application,
/// unless for whatever reason you switch OpenGL loaders mid-flight.
///
/// ## Safety
/// Attempting to create a filter chain will fail if the GL context is not initialized.
///
/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
/// chain objects, and drawing with them causes immediate undefined behaviour.
libra_error_t libra_gl_init_context(libra_gl_loader_t loader);
#endif
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
/// Create the filter chain given the shader preset. /// Create the filter chain given the shader preset.
/// ///
@ -1222,6 +1203,7 @@ libra_error_t libra_gl_init_context(libra_gl_loader_t loader);
/// - `options` must be either null, or valid and aligned. /// - `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.
libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset, libra_error_t libra_gl_filter_chain_create(libra_shader_preset_t *preset,
libra_gl_loader_t loader,
const struct filter_chain_gl_opt_t *options, const struct filter_chain_gl_opt_t *options,
libra_gl_filter_chain_t *out); libra_gl_filter_chain_t *out);
#endif #endif

View file

@ -194,12 +194,9 @@ libra_error_t __librashader__noop_preset_free_runtime_params(
return NULL; return NULL;
} }
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
libra_error_t __librashader__noop_gl_init_context(libra_gl_loader_t loader) {
return NULL;
}
libra_error_t __librashader__noop_gl_filter_chain_create( libra_error_t __librashader__noop_gl_filter_chain_create(
libra_shader_preset_t *preset, const struct filter_chain_gl_opt_t *options, libra_shader_preset_t *preset, libra_gl_loader_t loader,
const struct filter_chain_gl_opt_t *options,
libra_gl_filter_chain_t *out) { libra_gl_filter_chain_t *out) {
*out = NULL; *out = NULL;
return NULL; return NULL;
@ -799,17 +796,6 @@ typedef struct libra_instance_t {
PFN_libra_error_free_string error_free_string; PFN_libra_error_free_string error_free_string;
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
/// Initialize the OpenGL Context for librashader.
///
/// ## Safety
/// Attempting to create a filter chain will fail if the context is not
/// initialized.
///
/// Reinitializing the OpenGL context with a different loader immediately
/// invalidates previous filter chain objects, and drawing with them causes
/// immediate undefined behaviour.
PFN_libra_gl_init_context gl_init_context;
/// Create the filter chain given the shader preset. /// 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
@ -1445,7 +1431,6 @@ libra_instance_t __librashader_make_null_instance(void) {
instance.error_free_string = __librashader__noop_error_free_string; instance.error_free_string = __librashader__noop_error_free_string;
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
instance.gl_init_context = __librashader__noop_gl_init_context;
instance.gl_filter_chain_create = instance.gl_filter_chain_create =
__librashader__noop_gl_filter_chain_create; __librashader__noop_gl_filter_chain_create;
instance.gl_filter_chain_frame = __librashader__noop_gl_filter_chain_frame; instance.gl_filter_chain_frame = __librashader__noop_gl_filter_chain_frame;
@ -1620,7 +1605,6 @@ libra_instance_t librashader_load_instance(void) {
_LIBRASHADER_ASSIGN(librashader, instance, error_free_string); _LIBRASHADER_ASSIGN(librashader, instance, error_free_string);
#if defined(LIBRA_RUNTIME_OPENGL) #if defined(LIBRA_RUNTIME_OPENGL)
_LIBRASHADER_ASSIGN(librashader, instance, gl_init_context);
_LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_create); _LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_create);
_LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_frame); _LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_frame);
_LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_free); _LIBRASHADER_ASSIGN(librashader, instance, gl_filter_chain_free);

View file

@ -7,12 +7,14 @@ use librashader::runtime::gl::{
FilterChain, FilterChainOptions, FrameOptions, GLFramebuffer, GLImage, FilterChain, FilterChainOptions, FrameOptions, GLFramebuffer, GLImage,
}; };
use std::ffi::CStr; use std::ffi::CStr;
use std::ffi::{c_char, c_void, CString}; use std::ffi::{c_char, c_void};
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::num::NonZeroU32;
use std::ptr::NonNull; use std::ptr::NonNull;
use std::slice; use std::slice;
use std::sync::Arc;
use crate::LIBRASHADER_API_VERSION; use crate::LIBRASHADER_API_VERSION;
use librashader::runtime::gl::error::FilterChainError;
use librashader::runtime::FilterChainParameters; use librashader::runtime::FilterChainParameters;
use librashader::runtime::{Size, Viewport}; use librashader::runtime::{Size, Viewport};
@ -49,8 +51,12 @@ pub struct libra_output_framebuffer_gl_t {
impl From<libra_source_image_gl_t> for GLImage { impl From<libra_source_image_gl_t> for GLImage {
fn from(value: libra_source_image_gl_t) -> Self { fn from(value: libra_source_image_gl_t) -> Self {
let handle = NonZeroU32::try_from(value.handle)
.ok()
.map(glow::NativeTexture);
GLImage { GLImage {
handle: value.handle, handle,
format: value.format, format: value.format,
size: Size::new(value.width, value.height), size: Size::new(value.width, value.height),
} }
@ -108,27 +114,6 @@ config_struct! {
} }
} }
extern_fn! {
/// Initialize the OpenGL Context for librashader.
///
/// This only has to be done once throughout the lifetime of the application,
/// unless for whatever reason you switch OpenGL loaders mid-flight.
///
/// ## Safety
/// Attempting to create a filter chain will fail if the GL context is not initialized.
///
/// Reinitializing the OpenGL context with a different loader immediately invalidates previous filter
/// chain objects, and drawing with them causes immediate undefined behaviour.
raw fn libra_gl_init_context(loader: libra_gl_loader_t) {
gl::load_with(|s| unsafe {
let proc_name = CString::new(s).unwrap_unchecked();
loader(proc_name.as_ptr())
});
LibrashaderError::ok()
}
}
extern_fn! { extern_fn! {
/// Create the filter chain given the shader preset. /// Create the filter chain given the shader preset.
/// ///
@ -141,6 +126,7 @@ extern_fn! {
/// - `out` must be aligned, but may be null, invalid, or uninitialized. /// - `out` must be aligned, but may be null, invalid, or uninitialized.
fn libra_gl_filter_chain_create( fn libra_gl_filter_chain_create(
preset: *mut libra_shader_preset_t, preset: *mut libra_shader_preset_t,
loader: libra_gl_loader_t,
options: *const MaybeUninit<filter_chain_gl_opt_t>, options: *const MaybeUninit<filter_chain_gl_opt_t>,
out: *mut MaybeUninit<libra_gl_filter_chain_t> out: *mut MaybeUninit<libra_gl_filter_chain_t>
) { ) {
@ -160,7 +146,11 @@ extern_fn! {
let options = options.map(FromUninit::from_uninit); let options = options.map(FromUninit::from_uninit);
unsafe { unsafe {
let chain = FilterChain::load_from_preset(*preset, options.as_ref())?; let context = glow::Context::from_loader_function_cstr(
|proc_name| loader(proc_name.as_ptr()));
let chain = FilterChain::load_from_preset(Arc::new(context),
*preset, options.as_ref())?;
out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new( out.write(MaybeUninit::new(NonNull::new(Box::into_raw(Box::new(
chain, chain,
@ -206,8 +196,19 @@ extern_fn! {
}; };
let opt = opt.map(FromUninit::from_uninit); let opt = opt.map(FromUninit::from_uninit);
let framebuffer = GLFramebuffer::new_from_raw(out.texture, out.fbo, out.format,
Size::new(out.width, out.height), 1); let texture = NonZeroU32::try_from(out.texture)
.ok()
.map(glow::NativeTexture);
let fbo = NonZeroU32::try_from(out.fbo)
.ok()
.map(glow::NativeFramebuffer)
.ok_or(FilterChainError::GlInvalidFramebuffer)?;
let framebuffer = GLFramebuffer::new_from_raw(Arc::clone(chain.get_context()),
texture, fbo, out.format, Size::new(out.width, out.height), 1);
let viewport = Viewport { let viewport = Viewport {
x: viewport.x, x: viewport.x,
y: viewport.y, y: viewport.y,

View file

@ -31,7 +31,8 @@ pub const LIBRASHADER_CURRENT_VERSION: LIBRASHADER_API_VERSION = 1;
/// ## ABI Versions /// ## ABI Versions
/// - ABI version 0: null instance (unloaded) /// - ABI version 0: null instance (unloaded)
/// - ABI version 1: 0.1.0 /// - ABI version 1: 0.1.0
pub const LIBRASHADER_CURRENT_ABI: LIBRASHADER_ABI_VERSION = 1; /// - ABI version 2: 0.4.0
pub const LIBRASHADER_CURRENT_ABI: LIBRASHADER_ABI_VERSION = 2;
/// Function pointer definition for libra_abi_version /// Function pointer definition for libra_abi_version
pub type PFN_libra_instance_abi_version = extern "C" fn() -> LIBRASHADER_ABI_VERSION; pub type PFN_libra_instance_abi_version = extern "C" fn() -> LIBRASHADER_ABI_VERSION;

View file

@ -34,6 +34,8 @@ pub enum FilterChainError {
GlSamplerError, GlSamplerError,
#[error("opengl could not create samplers")] #[error("opengl could not create samplers")]
GlProgramError, GlProgramError,
#[error("an invalid framebuffer was provided to frame")]
GlInvalidFramebuffer,
#[error("opengl error: {0}")] #[error("opengl error: {0}")]
GlError(String), GlError(String),
} }

View file

@ -132,7 +132,7 @@ impl<T: GLInterface> FilterChainImpl<T> {
/// Load a filter chain from a pre-parsed `ShaderPreset`. /// Load a filter chain from a pre-parsed `ShaderPreset`.
pub(crate) unsafe fn load_from_preset( pub(crate) unsafe fn load_from_preset(
preset: ShaderPreset, preset: ShaderPreset,
context: glow::Context, context: Arc<glow::Context>,
options: Option<&FilterChainOptionsGL>, options: Option<&FilterChainOptionsGL>,
) -> error::Result<Self> { ) -> error::Result<Self> {
let disable_cache = options.map_or(false, |o| o.disable_cache); let disable_cache = options.map_or(false, |o| o.disable_cache);
@ -156,7 +156,6 @@ impl<T: GLInterface> FilterChainImpl<T> {
// load luts // load luts
let luts = T::LoadLut::load_luts(&context, &preset.textures)?; let luts = T::LoadLut::load_luts(&context, &preset.textures)?;
let context = Arc::new(context);
let framebuffer_gen = || T::FramebufferInterface::new(&context, 1); let framebuffer_gen = || T::FramebufferInterface::new(&context, 1);
let input_gen = || InputTexture { let input_gen = || InputTexture {
image: Default::default(), image: Default::default(),

View file

@ -24,7 +24,7 @@ pub struct FilterChainGL {
impl FilterChainGL { impl FilterChainGL {
/// Load a filter chain from a pre-parsed `ShaderPreset`. /// Load a filter chain from a pre-parsed `ShaderPreset`.
pub unsafe fn load_from_preset( pub unsafe fn load_from_preset(
ctx: glow::Context, ctx: Arc<glow::Context>,
preset: ShaderPreset, preset: ShaderPreset,
options: Option<&FilterChainOptionsGL>, options: Option<&FilterChainOptionsGL>,
) -> Result<Self> { ) -> Result<Self> {
@ -47,7 +47,7 @@ impl FilterChainGL {
/// Load the shader preset at the given path into a filter chain. /// Load the shader preset at the given path into a filter chain.
pub unsafe fn load_from_path( pub unsafe fn load_from_path(
ctx: glow::Context, ctx: Arc<glow::Context>,
path: impl AsRef<Path>, path: impl AsRef<Path>,
options: Option<&FilterChainOptionsGL>, options: Option<&FilterChainOptionsGL>,
) -> Result<Self> { ) -> Result<Self> {