Move native calls to Stb.Native

This commit is contained in:
H. Utku Maden 2024-06-19 11:31:51 +03:00
parent e7d7f5f826
commit 9b21bb837b
6 changed files with 62 additions and 12 deletions

@ -1,3 +1,4 @@
using ReFuel.Stb.Native;
using System; using System;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.IO; using System.IO;

@ -1,14 +1,16 @@
using System; using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Reflection; using System.Reflection;
namespace ReFuel.Stb namespace ReFuel.Stb.Native
{ {
/// <summary>
/// Direct access to the native STBI function calls.
/// </summary>
public unsafe static partial class Stbi public unsafe static partial class Stbi
{ {
private delegate void FailedAssertProc(byte *expression, byte *file, int line, byte *function); private delegate void FailedAssertProc(byte *expression, byte *file, int line, byte *function);
private static IntPtr stbiHandle;
private static readonly string[] LibraryNames = new string[] private static readonly string[] LibraryNames = new string[]
{ {
@ -29,22 +31,33 @@ namespace ReFuel.Stb
static Stbi() static Stbi()
{ {
NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), Resolver); NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), Resolver);
// Dummy call to fail_reason so we have a handle to STBI.
failure_reason();
// Load global address pointers.
_tga_with_rle_ptr = (int*)NativeLibrary.GetExport(stbiHandle, "stbi_write_tga_with_rle");
_png_compression_level_ptr = (int*)NativeLibrary.GetExport(stbiHandle, "stbi_write_png_compression_level");
_force_png_filter_ptr = (int*)NativeLibrary.GetExport(stbiHandle, "stbi_write_force_png_filter");
} }
private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath)
{ {
if (libraryName != "stbi") if (libraryName != "stbi")
return IntPtr.Zero; return IntPtr.Zero;
else if (stbiHandle != IntPtr.Zero)
return stbiHandle;
foreach (string name in LibraryNames) foreach (string name in LibraryNames)
{ {
if (NativeLibrary.TryLoad(name, assembly, searchPath, out IntPtr handle)) if (NativeLibrary.TryLoad(name, assembly, searchPath, out stbiHandle))
{ {
return handle; return stbiHandle;
} }
} }
return NativeLibrary.Load(libraryName); return stbiHandle = NativeLibrary.Load(libraryName);
} }
} }
} }

@ -1,7 +1,7 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ReFuel.Stb namespace ReFuel.Stb.Native
{ {
public enum StbiEnum : uint public enum StbiEnum : uint
{ {

@ -1,5 +1,10 @@
using ReFuel.Stb.Native;
namespace ReFuel.Stb namespace ReFuel.Stb
{ {
/// <summary>
/// Enumeration of supported STBI image formats.
/// </summary>
public enum StbiImageFormat public enum StbiImageFormat
{ {
Default = (int)StbiEnum.STBI_default, Default = (int)StbiEnum.STBI_default,

@ -1,13 +1,34 @@
using ReFuel.Stb.Native;
using System; using System;
using System.IO; using System.IO;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ReFuel.Stb namespace ReFuel.Stb
{ {
/// <summary>
/// Pointer to STBI stream read function.
/// </summary>
/// <param name="userdata">User provided userdata pointer.</param>
/// <param name="buffer">C array to read into.</param>
/// <param name="count">Size of the C array in bytes.</param>
/// <returns>The number of bytes read from the stream.</returns>
public unsafe delegate int StbiReadProc(void *userdata, byte* buffer, int count); public unsafe delegate int StbiReadProc(void *userdata, byte* buffer, int count);
/// <summary>
/// Pointer to STBI stream skip function.
/// </summary>
/// <param name="userdata">User provided userdata pointer.</param>
/// <param name="count">Number of bytes to skip.</param>
public unsafe delegate void StbiSkipProc(void *userdata, int count); public unsafe delegate void StbiSkipProc(void *userdata, int count);
/// <summary>
/// Pointer to STBI stream end of file function.
/// </summary>
/// <param name="userdata">User provided userdata pointer.</param>
/// <returns>Non-zero value if the end of the stream has been reached.</returns>
public unsafe delegate int StbiEofProc(void *userdata); public unsafe delegate int StbiEofProc(void *userdata);
/// <summary>
/// An easy to use stream wrapper for use with STBI image load functions.
/// </summary>
public unsafe class StbiStreamWrapper : IDisposable public unsafe class StbiStreamWrapper : IDisposable
{ {
private readonly stbi_io_callbacks _callbacks; private readonly stbi_io_callbacks _callbacks;
@ -74,7 +95,11 @@ namespace ReFuel.Stb
} }
} }
internal struct StbiWriteStreamWrapper /// <summary>
/// An easy to use stream wrapper for STBI image write functions.
/// </summary>
/// <remarks>Keep struct alive for the duration of the write operation.</remarks>
public struct StbiWriteStreamWrapper
{ {
private readonly Stream _stream; private readonly Stream _stream;
private readonly StbiWriteProc _cb; private readonly StbiWriteProc _cb;

@ -1,15 +1,21 @@
using System; using System;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
namespace ReFuel.Stb namespace ReFuel.Stb.Native
{ {
/// <summary>
/// Procedure to STBI image write function.
/// </summary>
/// <param name="context">User provided context pointer.</param>
/// <param name="data">C Array of data to write.</param>
/// <param name="size">Size of the C array in bytes.</param>
public unsafe delegate void StbiWriteProc(void* context, void* data, int size); public unsafe delegate void StbiWriteProc(void* context, void* data, int size);
public unsafe partial class Stbi public unsafe partial class Stbi
{ {
private static readonly int* _tga_with_rle_ptr; private static readonly int* _tga_with_rle_ptr;
private static readonly int* _png_compression_level_ptr; private static readonly int* _png_compression_level_ptr;
private static readonly int* _forced_png_filter_ptr; private static readonly int* _force_png_filter_ptr;
public static int write_tga_with_rle public static int write_tga_with_rle
{ {
@ -25,8 +31,8 @@ namespace ReFuel.Stb
public static int write_force_png_filter public static int write_force_png_filter
{ {
get => *_forced_png_filter_ptr; get => *_force_png_filter_ptr;
set => *_forced_png_filter_ptr = value; set => *_force_png_filter_ptr = value;
} }
[DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_png_to_func")] [DllImport("stbi", CallingConvention = CallingConvention.Cdecl, EntryPoint = "stbi_write_png_to_func")]