Added new numeric types for unsigned integers, including uint2, uint3, and uint4, along with their matrix types. Added a new `quaternion` struct with constructors and methods for creating and manipulating quaternions. Added methods for projecting and reflecting vectors, enhancing geometric operations. Added utility functions for generating orthonormal bases and changing vector signs. Added comprehensive unit tests for new mathematical functions and quaternion operations. Added a high-performance job scheduling system with job management features and worker thread management. Added new structs for job execution, allowing efficient job scheduling and execution. Added utility functions for job execution, including methods for obtaining unique job IDs. Changed access modifiers and property definitions in several files for improved clarity and maintainability. Changed property definitions and method implementations in `ImageInfo.cs`, `ImageResult.cs`, and `ImageResultFloat.cs` for better readability. Changed memory management functions in `CRuntime.cs` and improved memory allocation tracking in `MemoryStats.cs`. Changed the project file to include references to necessary projects and enable unsafe code blocks. Removed the `WorkerThreadPool.cs` file, integrating worker thread management directly into the `JobScheduler`. Removed the `float4` struct and its associated methods and properties, transitioning to a new code generation strategy. Removed the `float4.tt` template and other related files, indicating a shift in code generation approach. Removed the `Vectorize.cs` file, indicating a change in how vector operations are handled. Updated the `.gitignore` file to include IDE-specific settings. Updated various XML files to define project components and structure. Updated the `AllocationManager.cs` to improve memory allocation management and introduce new strategies. Updated the `UnsafeArray.cs`, `UnsafeHashMap.cs`, and `UnsafeList.cs` to enhance performance and safety in unsafe contexts. Updated error handling and function pointer management in `MemoryLeakException.cs` and `FunctionPointer.cs`. Updated the `AssemblyInfo.cs` file to include global using directives for better code organization.
545 lines
20 KiB
C#
545 lines
20 KiB
C#
// Generated by Sichem at 12/24/2021 8:28:15 PM
|
|
|
|
using Misaki.HighPerformance.Image.Runtime;
|
|
using System.Runtime.InteropServices;
|
|
|
|
namespace Misaki.HighPerformance.Image
|
|
{
|
|
unsafe partial class StbImage
|
|
{
|
|
public static int stbi__gif_test(stbi__context s)
|
|
{
|
|
var r = stbi__gif_test_raw(s);
|
|
stbi__rewind(s);
|
|
return r;
|
|
}
|
|
|
|
public static void* stbi__gif_load(stbi__context s, int* x, int* y, int* comp, int req_comp,
|
|
stbi__result_info* ri)
|
|
{
|
|
byte* u = null;
|
|
var g = new stbi__gif();
|
|
u = stbi__gif_load_next(s, g, comp, req_comp, null);
|
|
if (u != null)
|
|
{
|
|
*x = g.w;
|
|
*y = g.h;
|
|
if (req_comp != 0 && req_comp != 4)
|
|
u = stbi__convert_format(u, 4, req_comp, (uint)g.w, (uint)g.h);
|
|
}
|
|
else if (g._out_ != null)
|
|
{
|
|
CRuntime.free(g._out_);
|
|
}
|
|
|
|
CRuntime.free(g.history);
|
|
CRuntime.free(g.background);
|
|
return u;
|
|
}
|
|
|
|
public static void* stbi__load_gif_main(stbi__context s, int** delays, int* x, int* y, int* z, int* comp,
|
|
int req_comp)
|
|
{
|
|
if (stbi__gif_test(s) != 0)
|
|
{
|
|
var layers = 0;
|
|
byte* u = null;
|
|
byte* _out_ = null;
|
|
byte* two_back = null;
|
|
var g = new stbi__gif();
|
|
var stride = 0;
|
|
var out_size = 0;
|
|
var delays_size = 0;
|
|
if (delays != null)
|
|
*delays = null;
|
|
do
|
|
{
|
|
u = stbi__gif_load_next(s, g, comp, req_comp, two_back);
|
|
if (u != null)
|
|
{
|
|
*x = g.w;
|
|
*y = g.h;
|
|
++layers;
|
|
stride = g.w * g.h * 4;
|
|
if (_out_ != null)
|
|
{
|
|
void* tmp = (byte*)CRuntime.realloc(_out_, (ulong)(layers * stride));
|
|
if (tmp == null)
|
|
return stbi__load_gif_main_outofmem(g, _out_, delays);
|
|
_out_ = (byte*)tmp;
|
|
out_size = layers * stride;
|
|
if (delays != null)
|
|
{
|
|
var new_delays = (int*)CRuntime.realloc(*delays, (ulong)(sizeof(int) * layers));
|
|
if (new_delays == null)
|
|
return stbi__load_gif_main_outofmem(g, _out_, delays);
|
|
*delays = new_delays;
|
|
delays_size = layers * sizeof(int);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
_out_ = (byte*)stbi__malloc((ulong)(layers * stride));
|
|
if (_out_ == null)
|
|
return stbi__load_gif_main_outofmem(g, _out_, delays);
|
|
out_size = layers * stride;
|
|
if (delays != null)
|
|
{
|
|
*delays = (int*)stbi__malloc((ulong)(layers * sizeof(int)));
|
|
if (*delays == null)
|
|
return stbi__load_gif_main_outofmem(g, _out_, delays);
|
|
delays_size = layers * sizeof(int);
|
|
}
|
|
}
|
|
|
|
CRuntime.memcpy(_out_ + (layers - 1) * stride, u, (ulong)stride);
|
|
if (layers >= 2)
|
|
two_back = _out_ - 2 * stride;
|
|
if (delays != null)
|
|
(*delays)[layers - 1U] = g.delay;
|
|
}
|
|
} while (u != null);
|
|
|
|
CRuntime.free(g._out_);
|
|
CRuntime.free(g.history);
|
|
CRuntime.free(g.background);
|
|
if (req_comp != 0 && req_comp != 4)
|
|
_out_ = stbi__convert_format(_out_, 4, req_comp, (uint)(layers * g.w), (uint)g.h);
|
|
*z = layers;
|
|
return _out_;
|
|
}
|
|
|
|
return (byte*)(ulong)(stbi__err("not GIF") != 0 ? 0 : 0);
|
|
}
|
|
|
|
public static int stbi__gif_info(stbi__context s, int* x, int* y, int* comp)
|
|
{
|
|
return stbi__gif_info_raw(s, x, y, comp);
|
|
}
|
|
|
|
public static int stbi__gif_test_raw(stbi__context s)
|
|
{
|
|
var sz = 0;
|
|
if (stbi__get8(s) != 71 || stbi__get8(s) != 73 || stbi__get8(s) != 70 || stbi__get8(s) != 56)
|
|
return 0;
|
|
sz = stbi__get8(s);
|
|
if (sz != 57 && sz != 55)
|
|
return 0;
|
|
if (stbi__get8(s) != 97)
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
public static void stbi__gif_parse_colortable(stbi__context s, byte[][] pal, int num_entries, int transp)
|
|
{
|
|
var i = 0;
|
|
for (i = 0; i < num_entries; ++i)
|
|
{
|
|
pal[i][2] = stbi__get8(s);
|
|
pal[i][1] = stbi__get8(s);
|
|
pal[i][0] = stbi__get8(s);
|
|
pal[i][3] = (byte)(transp == i ? 0 : 255);
|
|
}
|
|
}
|
|
|
|
public static int stbi__gif_header(stbi__context s, stbi__gif g, int* comp, int is_info)
|
|
{
|
|
byte version = 0;
|
|
if (stbi__get8(s) != 71 || stbi__get8(s) != 73 || stbi__get8(s) != 70 || stbi__get8(s) != 56)
|
|
return stbi__err("not GIF");
|
|
version = stbi__get8(s);
|
|
if (version != 55 && version != 57)
|
|
return stbi__err("not GIF");
|
|
if (stbi__get8(s) != 97)
|
|
return stbi__err("not GIF");
|
|
stbi__g_failure_reason = "";
|
|
g.w = stbi__get16le(s);
|
|
g.h = stbi__get16le(s);
|
|
g.flags = stbi__get8(s);
|
|
g.bgindex = stbi__get8(s);
|
|
g.ratio = stbi__get8(s);
|
|
g.transparent = -1;
|
|
if (g.w > 1 << 24)
|
|
return stbi__err("too large");
|
|
if (g.h > 1 << 24)
|
|
return stbi__err("too large");
|
|
if (comp != null)
|
|
*comp = 4;
|
|
if (is_info != 0)
|
|
return 1;
|
|
if ((g.flags & 0x80) != 0)
|
|
stbi__gif_parse_colortable(s, g.pal, 2 << (g.flags & 7), -1);
|
|
return 1;
|
|
}
|
|
|
|
public static int stbi__gif_info_raw(stbi__context s, int* x, int* y, int* comp)
|
|
{
|
|
var g = new stbi__gif();
|
|
if (g == null)
|
|
return stbi__err("outofmem");
|
|
if (stbi__gif_header(s, g, comp, 1) == 0)
|
|
{
|
|
stbi__rewind(s);
|
|
return 0;
|
|
}
|
|
|
|
if (x != null)
|
|
*x = g.w;
|
|
if (y != null)
|
|
*y = g.h;
|
|
return 1;
|
|
}
|
|
|
|
public static void stbi__out_gif_code(stbi__gif g, ushort code)
|
|
{
|
|
byte* p;
|
|
var idx = 0;
|
|
if (g.codes[code].prefix >= 0)
|
|
stbi__out_gif_code(g, (ushort)g.codes[code].prefix);
|
|
if (g.cur_y >= g.max_y)
|
|
return;
|
|
idx = g.cur_x + g.cur_y;
|
|
p = &g._out_[idx];
|
|
g.history[idx / 4] = 1;
|
|
var c = g.color_table[g.codes[code].suffix];
|
|
if (c[3] > 128)
|
|
{
|
|
p[0] = c[2];
|
|
p[1] = c[1];
|
|
p[2] = c[0];
|
|
p[3] = c[3];
|
|
}
|
|
|
|
g.cur_x += 4;
|
|
if (g.cur_x >= g.max_x)
|
|
{
|
|
g.cur_x = g.start_x;
|
|
g.cur_y += g.step;
|
|
while (g.cur_y >= g.max_y && g.parse > 0)
|
|
{
|
|
g.step = (1 << g.parse) * g.line_size;
|
|
g.cur_y = g.start_y + (g.step >> 1);
|
|
--g.parse;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static byte* stbi__process_gif_raster(stbi__context s, stbi__gif g)
|
|
{
|
|
byte lzw_cs = 0;
|
|
var len = 0;
|
|
var init_code = 0;
|
|
uint first = 0;
|
|
var codesize = 0;
|
|
var codemask = 0;
|
|
var avail = 0;
|
|
var oldcode = 0;
|
|
var bits = 0;
|
|
var valid_bits = 0;
|
|
var clear = 0;
|
|
stbi__gif_lzw* p;
|
|
lzw_cs = stbi__get8(s);
|
|
if (lzw_cs > 12)
|
|
return null;
|
|
clear = 1 << lzw_cs;
|
|
first = 1;
|
|
codesize = lzw_cs + 1;
|
|
codemask = (1 << codesize) - 1;
|
|
bits = 0;
|
|
valid_bits = 0;
|
|
for (init_code = 0; init_code < clear; init_code++)
|
|
{
|
|
g.codes[init_code].prefix = -1;
|
|
g.codes[init_code].first = (byte)init_code;
|
|
g.codes[init_code].suffix = (byte)init_code;
|
|
}
|
|
|
|
avail = clear + 2;
|
|
oldcode = -1;
|
|
len = 0;
|
|
for (; ; )
|
|
if (valid_bits < codesize)
|
|
{
|
|
if (len == 0)
|
|
{
|
|
len = stbi__get8(s);
|
|
if (len == 0)
|
|
return g._out_;
|
|
}
|
|
|
|
--len;
|
|
bits |= stbi__get8(s) << valid_bits;
|
|
valid_bits += 8;
|
|
}
|
|
else
|
|
{
|
|
var code = bits & codemask;
|
|
bits >>= codesize;
|
|
valid_bits -= codesize;
|
|
if (code == clear)
|
|
{
|
|
codesize = lzw_cs + 1;
|
|
codemask = (1 << codesize) - 1;
|
|
avail = clear + 2;
|
|
oldcode = -1;
|
|
first = 0;
|
|
}
|
|
else if (code == clear + 1)
|
|
{
|
|
stbi__skip(s, len);
|
|
while ((len = stbi__get8(s)) > 0)
|
|
stbi__skip(s, len);
|
|
return g._out_;
|
|
}
|
|
else if (code <= avail)
|
|
{
|
|
if (first != 0)
|
|
return (byte*)(ulong)(stbi__err("no clear code") != 0 ? 0 : 0);
|
|
if (oldcode >= 0)
|
|
{
|
|
fixed (stbi__gif_lzw* p2 = &g.codes[avail++])
|
|
{
|
|
p = p2;
|
|
if (avail > 8192)
|
|
return (byte*)(ulong)(stbi__err("too many codes") != 0 ? 0 : 0);
|
|
p->prefix = (short)oldcode;
|
|
p->first = g.codes[oldcode].first;
|
|
p->suffix = code == avail ? p->first : g.codes[code].first;
|
|
}
|
|
}
|
|
else if (code == avail)
|
|
{
|
|
return (byte*)(ulong)(stbi__err("illegal code in raster") != 0 ? 0 : 0);
|
|
}
|
|
|
|
stbi__out_gif_code(g, (ushort)code);
|
|
if ((avail & codemask) == 0 && avail <= 0x0FFF)
|
|
{
|
|
codesize++;
|
|
codemask = (1 << codesize) - 1;
|
|
}
|
|
|
|
oldcode = code;
|
|
}
|
|
else
|
|
{
|
|
return (byte*)(ulong)(stbi__err("illegal code in raster") != 0 ? 0 : 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static byte* stbi__gif_load_next(stbi__context s, stbi__gif g, int* comp, int req_comp, byte* two_back)
|
|
{
|
|
var dispose = 0;
|
|
var first_frame = 0;
|
|
var pi = 0;
|
|
var pcount = 0;
|
|
first_frame = 0;
|
|
if (g._out_ == null)
|
|
{
|
|
if (stbi__gif_header(s, g, comp, 0) == 0)
|
|
return null;
|
|
if (stbi__mad3sizes_valid(4, g.w, g.h, 0) == 0)
|
|
return (byte*)(ulong)(stbi__err("too large") != 0 ? 0 : 0);
|
|
pcount = g.w * g.h;
|
|
g._out_ = (byte*)stbi__malloc((ulong)(4 * pcount));
|
|
g.background = (byte*)stbi__malloc((ulong)(4 * pcount));
|
|
g.history = (byte*)stbi__malloc((ulong)pcount);
|
|
if (g._out_ == null || g.background == null || g.history == null)
|
|
return (byte*)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0);
|
|
CRuntime.memset(g._out_, 0x00, (ulong)(4 * pcount));
|
|
CRuntime.memset(g.background, 0x00, (ulong)(4 * pcount));
|
|
CRuntime.memset(g.history, 0x00, (ulong)pcount);
|
|
first_frame = 1;
|
|
}
|
|
else
|
|
{
|
|
dispose = (g.eflags & 0x1C) >> 2;
|
|
pcount = g.w * g.h;
|
|
if (dispose == 3 && two_back == null)
|
|
dispose = 2;
|
|
if (dispose == 3)
|
|
{
|
|
for (pi = 0; pi < pcount; ++pi)
|
|
if (g.history[pi] != 0)
|
|
CRuntime.memcpy(&g._out_[pi * 4], &two_back[pi * 4], (ulong)4);
|
|
}
|
|
else if (dispose == 2)
|
|
{
|
|
for (pi = 0; pi < pcount; ++pi)
|
|
if (g.history[pi] != 0)
|
|
CRuntime.memcpy(&g._out_[pi * 4], &g.background[pi * 4], (ulong)4);
|
|
}
|
|
|
|
CRuntime.memcpy(g.background, g._out_, (ulong)(4 * g.w * g.h));
|
|
}
|
|
|
|
CRuntime.memset(g.history, 0x00, (ulong)(g.w * g.h));
|
|
for (; ; )
|
|
{
|
|
int tag = stbi__get8(s);
|
|
switch (tag)
|
|
{
|
|
case 0x2C:
|
|
{
|
|
var x = 0;
|
|
var y = 0;
|
|
var w = 0;
|
|
var h = 0;
|
|
byte* o;
|
|
x = stbi__get16le(s);
|
|
y = stbi__get16le(s);
|
|
w = stbi__get16le(s);
|
|
h = stbi__get16le(s);
|
|
if (x + w > g.w || y + h > g.h)
|
|
return (byte*)(ulong)(stbi__err("bad Image Descriptor") != 0 ? 0 : 0);
|
|
g.line_size = g.w * 4;
|
|
g.start_x = x * 4;
|
|
g.start_y = y * g.line_size;
|
|
g.max_x = g.start_x + w * 4;
|
|
g.max_y = g.start_y + h * g.line_size;
|
|
g.cur_x = g.start_x;
|
|
g.cur_y = g.start_y;
|
|
if (w == 0)
|
|
g.cur_y = g.max_y;
|
|
g.lflags = stbi__get8(s);
|
|
if ((g.lflags & 0x40) != 0)
|
|
{
|
|
g.step = 8 * g.line_size;
|
|
g.parse = 3;
|
|
}
|
|
else
|
|
{
|
|
g.step = g.line_size;
|
|
g.parse = 0;
|
|
}
|
|
|
|
if ((g.lflags & 0x80) != 0)
|
|
{
|
|
stbi__gif_parse_colortable(s, g.lpal, 2 << (g.lflags & 7),
|
|
(g.eflags & 0x01) != 0 ? g.transparent : -1);
|
|
g.color_table = g.lpal;
|
|
}
|
|
else if ((g.flags & 0x80) != 0)
|
|
{
|
|
g.color_table = g.pal;
|
|
}
|
|
else
|
|
{
|
|
return (byte*)(ulong)(stbi__err("missing color table") != 0 ? 0 : 0);
|
|
}
|
|
|
|
o = stbi__process_gif_raster(s, g);
|
|
if (o == null)
|
|
return null;
|
|
pcount = g.w * g.h;
|
|
if (first_frame != 0 && g.bgindex > 0)
|
|
for (pi = 0; pi < pcount; ++pi)
|
|
if (g.history[pi] == 0)
|
|
{
|
|
g.pal[g.bgindex][3] = 255;
|
|
fixed (byte* ptr = &g.pal[g.bgindex][0])
|
|
{
|
|
CRuntime.memcpy(&g._out_[pi * 4], ptr, (ulong)4);
|
|
}
|
|
}
|
|
|
|
return o;
|
|
}
|
|
|
|
case 0x21:
|
|
{
|
|
var len = 0;
|
|
int ext = stbi__get8(s);
|
|
if (ext == 0xF9)
|
|
{
|
|
len = stbi__get8(s);
|
|
if (len == 4)
|
|
{
|
|
g.eflags = stbi__get8(s);
|
|
g.delay = 10 * stbi__get16le(s);
|
|
if (g.transparent >= 0)
|
|
g.pal[g.transparent][3] = 255;
|
|
if ((g.eflags & 0x01) != 0)
|
|
{
|
|
g.transparent = stbi__get8(s);
|
|
if (g.transparent >= 0)
|
|
g.pal[g.transparent][3] = 0;
|
|
}
|
|
else
|
|
{
|
|
stbi__skip(s, 1);
|
|
g.transparent = -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
stbi__skip(s, len);
|
|
break;
|
|
}
|
|
}
|
|
|
|
while ((len = stbi__get8(s)) != 0)
|
|
stbi__skip(s, len);
|
|
break;
|
|
}
|
|
|
|
case 0x3B:
|
|
return null;
|
|
default:
|
|
return (byte*)(ulong)(stbi__err("unknown code") != 0 ? 0 : 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void* stbi__load_gif_main_outofmem(stbi__gif g, byte* _out_, int** delays)
|
|
{
|
|
CRuntime.free(g._out_);
|
|
CRuntime.free(g.history);
|
|
CRuntime.free(g.background);
|
|
if (_out_ != null)
|
|
CRuntime.free(_out_);
|
|
if (delays != null && *delays != null)
|
|
CRuntime.free(*delays);
|
|
return (byte*)(ulong)(stbi__err("outofmem") != 0 ? 0 : 0);
|
|
}
|
|
|
|
public class stbi__gif
|
|
{
|
|
public byte* _out_;
|
|
public byte* background;
|
|
public int bgindex;
|
|
public stbi__gif_lzw[] codes = new stbi__gif_lzw[8192];
|
|
public byte[][] color_table;
|
|
public int cur_x;
|
|
public int cur_y;
|
|
public int delay;
|
|
public int eflags;
|
|
public int flags;
|
|
public int h;
|
|
public byte* history;
|
|
public int lflags;
|
|
public int line_size;
|
|
public byte[][] lpal = Utility.CreateArray<byte>(256, 4);
|
|
public int max_x;
|
|
public int max_y;
|
|
public byte[][] pal = Utility.CreateArray<byte>(256, 4);
|
|
public int parse;
|
|
public int ratio;
|
|
public int start_x;
|
|
public int start_y;
|
|
public int step;
|
|
public int transparent;
|
|
public int w;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential)]
|
|
public struct stbi__gif_lzw
|
|
{
|
|
public short prefix;
|
|
public byte first;
|
|
public byte suffix;
|
|
}
|
|
}
|
|
}
|