summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-01-16 03:38:24 +0100
committerMitya Selivanov <automainint@guattari.tech>2025-01-16 03:38:24 +0100
commit725662a623ac36d44d2b44c568d8dd6c3eeeeca1 (patch)
tree50afdc84553f44ab0dc7dff425752e87f0a5e661
parentc6c72f54ea7f25defa7d39216f7713c46b873362 (diff)
downloadreduced_system_layer-725662a623ac36d44d2b44c568d8dd6c3eeeeca1.zip
Drag and drop impl on X11 (not tested)
-rw-r--r--examples/julia_set.c1
-rw-r--r--examples/particles.c1
-rw-r--r--graphics.c48
-rw-r--r--[-rwxr-xr-x]reduced_system_layer.c936
-rw-r--r--test.c22
5 files changed, 653 insertions, 355 deletions
diff --git a/examples/julia_set.c b/examples/julia_set.c
index e50a246..c7f7e9b 100644
--- a/examples/julia_set.c
+++ b/examples/julia_set.c
@@ -83,6 +83,7 @@ i32 main(i32 argc, c8 **argv) {
g_platform = (Platform) {
.title = "Julia Set",
+ .pixel_size = 1,
.exact_resolution = 1,
};
diff --git a/examples/particles.c b/examples/particles.c
index 130b5bf..894fee0 100644
--- a/examples/particles.c
+++ b/examples/particles.c
@@ -118,6 +118,7 @@ i32 main(i32 argc, c8 **argv) {
g_platform = (Platform) {
.title = "Particles",
+ .pixel_size = 1,
.exact_resolution = 1,
};
diff --git a/graphics.c b/graphics.c
index 2431e8c..6f786c5 100644
--- a/graphics.c
+++ b/graphics.c
@@ -51,6 +51,11 @@ vec3_f32 lch_from_rgb(vec3_f32 rgb);
vec4_f32 with_alpha(vec3_f32 color, f32 alpha);
vec3_f32 without_alpha(vec4_f32 color);
+u32 rgb_u32_from_f32(vec3_f32 color);
+vec3_f32 rgb_f32_from_u32(u32 color);
+u32 rgba_u32_from_f32(vec4_f32 color);
+vec4_f32 rgba_f32_from_u32(u32 color);
+
#define RGB(...) ((Brush) { .color = { __VA_ARGS__, 1.f } })
#define RGBA(...) ((Brush) { .color = { __VA_ARGS__ } })
#define LCH(...) ((Brush) { .color = with_alpha(gamma_apply(rgb_from_lch((vec3_f32) { __VA_ARGS__ })), 1.f) } })
@@ -442,6 +447,49 @@ vec3_f32 without_alpha(vec4_f32 color) {
};
}
+u32 rgb_u32_from_f32(vec3_f32 color) {
+ i32 ir = (i32) floor(color.x * 255. + .5);
+ i32 ig = (i32) floor(color.y * 255. + .5);
+ i32 ib = (i32) floor(color.z * 255. + .5);
+
+ u32 r = ir < 0 ? 0u : ir > 255 ? 255u : (u32) ir;
+ u32 g = ig < 0 ? 0u : ig > 255 ? 255u : (u32) ig;
+ u32 b = ib < 0 ? 0u : ib > 255 ? 255u : (u32) ib;
+
+ return (r << 16) | (g << 8) | b;
+}
+
+vec3_f32 rgb_f32_from_u32(u32 color) {
+ return (vec3_f32) {
+ .x = ((color & 0xff0000) >> 16) / 255.f,
+ .y = ((color & 0x00ff00) >> 8) / 255.f,
+ .z = (color & 0x0000ff) / 255.f,
+ };
+}
+
+u32 rgba_u32_from_f32(vec4_f32 color) {
+ i32 ir = (i32) floor(color.x * 255. + .5);
+ i32 ig = (i32) floor(color.y * 255. + .5);
+ i32 ib = (i32) floor(color.z * 255. + .5);
+ i32 ia = (i32) floor(color.w * 255. + .5);
+
+ u32 r = ir < 0 ? 0u : ir > 255 ? 255u : (u32) ir;
+ u32 g = ig < 0 ? 0u : ig > 255 ? 255u : (u32) ig;
+ u32 b = ib < 0 ? 0u : ib > 255 ? 255u : (u32) ib;
+ u32 a = ia < 0 ? 0u : ia > 255 ? 255u : (u32) ia;
+
+ return (a << 24) | (r << 16) | (g << 8) | b;
+}
+
+vec4_f32 rgba_f32_from_u32(u32 color) {
+ return (vec4_f32) {
+ .x = ((color & 0x00ff0000) >> 16) / 255.f,
+ .y = ((color & 0x0000ff00) >> 8) / 255.f,
+ .z = (color & 0x000000ff) / 255.f,
+ .w = ((color & 0xff000000) >> 24) / 255.f,
+ };
+}
+
b8 rectangle_contains(f64 x0, f64 y0, f64 width, f64 height, f64 px, f64 py) {
return px >= x0 && px < x0 + width && py >= y0 && py < y0 + height;
}
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 980e12c..017fc43 100755..100644
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -1,125 +1,99 @@
-#if 0 /*
-#/ ================================================================
-#/
-#/ reduced_system_layer.c
-#/
-#/ This is a reduced system layer.
-#/ It allows you to create a window, draw graphics in it, handle
-#/ input events, write samples to audio output, send and receive
-#/ UDP packets.
-#/
-#/ ----------------------------------------------------------------
-#/
-#/ DESIGN PRINCIPLES
-#/
-#/ - Minimalistic feature set. For graphics, you have access to the
-#/ pixel buffer, and that's it.
-#/
-#/ - No implicit control flow. No callbacks. You write your own
-#/ main and call everything explicitly. But the number of things
-#/ you have to call to do something is as little as possible.
-#/
-#/ - Optimized to use in a single source file.
-#/ Installation process? Ctrl+C, Ctrl+V, done.
-#/
-#/ ----------------------------------------------------------------
-#/
-#/ To-Do list
-#/
-#/ - Examples
-#/ - Conway's Game of Life
-#/ - Julia Set
-#/ - Labyrinth
-#/ - Chat
-#/ - Window
-#/ - Wayland
-#/ - Windows graphics
-#/ - Drop files
-#/ - Sound
-#/ - Windows audio
-#/ - Recording
-#/ - Networking
-#/ - Windows sockets
-#/ - Graphics
-#/ - UI
-#/ - Icons
-#/ - Vector math
-#/ - Anti-aliasing
-#/ - Logging
-#/ - Test suite
-#/ - Long term
-#/ - Allocator
-#/ - Parsing
-#/ - Printing
-#/ - File system
-#/ - Secure random
-#/ - Process
-#/ - Shared memory
-#/ - Shared mutex
-#/ - Stackless coroutines
-#/ - Big integer
-#/ - Mersenne Twister 64
-#/ - Arithmetic coding
-#/ - Threads - https://nachtimwald.com/2019/04/05/cross-platform-thread-wrapper
-#/ - Web sockets
-#/ - HTTP
-#/ - Cryptography - https://github.com/jedisct1/supercop
-#/
-#/ Done
-#/
-#/ - Examples
-#/ - Echo
-#/ - UI
-#/ - Particles
-#/ - Graph
-#/ - Sine Wave
-#/ - Window
-#/ - X11
-#/ - WebAssembly
-#/ - Sound
-#/ - ALSA
-#/ - WebAssembly audio
-#/ - Networking
-#/ - Unix UDP sockets
-#/ - UTF-8
-#/ - Testing
-#/ - Graphics
-#/ - Font
-#/ - Adaptive resolution
-#/ - Oklab color
-#/ - Relative coordinates
-#/ - Blending
-#/ - Self-contained impl
-#/
-#/ ----------------------------------------------------------------
-#/
-#/ (C) 2025 Mitya Selivanov <guattari.tech>
-#/
-#/ ================================================================
-#/
-#/ Self-compilation shell script
-#/
-#/ ================================================================
-
-SRC=${0##*./}
-BIN=${SRC%.*}
-gcc \
- -Wall -Wextra -Werror -pedantic \
- -Wno-old-style-declaration \
- -Wno-missing-braces \
- -Wno-unused-variable \
- -Wno-unused-but-set-variable \
- -Wno-unused-parameter \
- -Wno-overlength-strings \
- -O3 \
- -fsanitize=undefined,address,leak \
- -D REDUCED_SYSTEM_LAYER_EXAMPLE \
- -lX11 -lm -lasound \
- -o $BIN $SRC && \
- ./$BIN $@ && rm $BIN
-exit $? # */
-#endif
-
+// ================================================================
+//
+// reduced_system_layer.c
+//
+// This is a reduced system layer.
+// It allows you to create a window, draw graphics in it, handle
+// input events, write samples to audio output, send and receive
+// UDP packets.
+//
+// ----------------------------------------------------------------
+//
+// DESIGN PRINCIPLES
+//
+// - Minimalistic feature set. For graphics, you have access to the
+// pixel buffer, and that's it.
+//
+// - No implicit control flow. No callbacks. You write your own
+// main and call everything explicitly. But the number of things
+// you have to call to do something is as little as possible.
+//
+// - Optimized to use in a single source file.
+// Installation process? Ctrl+C, Ctrl+V, done.
+//
+// ----------------------------------------------------------------
+//
+// To-Do list
+//
+// - Examples
+// - Conway's Game of Life
+// - Julia Set
+// - Labyrinth
+// - Chat
+// - Window
+// - Wayland
+// - Windows graphics
+// - Drop files
+// - Sound
+// - Windows audio
+// - Recording
+// - Networking
+// - Windows sockets
+// - Graphics
+// - UI
+// - Icons
+// - Vector math
+// - Anti-aliasing
+// - Logging
+// - Test suite
+// - Long term
+// - Allocator
+// - Parsing
+// - Printing
+// - File system
+// - Secure random
+// - Process
+// - Shared memory
+// - Shared mutex
+// - Stackless coroutines
+// - Big integer
+// - Mersenne Twister 64
+// - Arithmetic coding
+// - Threads - https://nachtimwald.com/2019/04/05/cross-platform-thread-wrapper
+// - Web sockets
+// - HTTP
+// - Cryptography - https://github.com/jedisct1/supercop
+//
+// Done
+//
+// - Examples
+// - Echo
+// - UI
+// - Particles
+// - Graph
+// - Sine Wave
+// - Window
+// - X11
+// - WebAssembly
+// - Sound
+// - ALSA
+// - WebAssembly audio
+// - Networking
+// - Unix UDP sockets
+// - UTF-8
+// - Testing
+// - Graphics
+// - Font
+// - Adaptive resolution
+// - Oklab color
+// - Relative coordinates
+// - Blending
+// - Self-contained impl
+//
+// ----------------------------------------------------------------
+//
+// (C) 2025 Mitya Selivanov <guattari.tech>
+//
// ================================================================
//
// Types
@@ -159,13 +133,26 @@ typedef struct { f64 v[16]; } mat4;
#endif // TYPES_HEADER_GUARD_
// ================================================================
+
+#ifndef REDUCED_SYSTEM_LAYER_HEADER_GUARD_
+#define REDUCED_SYSTEM_LAYER_HEADER_GUARD_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// ================================================================
//
-// Basic declarations
+// User program interface
//
// ================================================================
-#ifndef REDUCED_SYSTEM_LAYER_HEADER_GUARD_
-#define REDUCED_SYSTEM_LAYER_HEADER_GUARD_
+// NOTE: This procedure is required for the WebAssembly compatibility.
+void update_and_render_frame(void);
+
+#if defined(__wasm__)
+i32 main(i32 argc, c8 **argv);
+#endif
// ================================================================
//
@@ -206,11 +193,7 @@ typedef struct { f64 v[16]; } mat4;
#endif
#ifndef DEFAULT_PIXEL_SIZE
-#if defined(__wasm__)
#define DEFAULT_PIXEL_SIZE 3
-#else
-#define DEFAULT_PIXEL_SIZE 1
-#endif
#endif
#ifndef MIN_FRAME_DURATION
@@ -241,28 +224,117 @@ typedef struct { f64 v[16]; } mat4;
#define MAX_NUM_SOUND_FRAMES (10 * SOUND_SAMPLE_RATE * NUM_SOUND_CHANNELS)
#endif
-#ifndef DROP_FILE_BUFFER_SIZE
-#define DROP_FILE_BUFFER_SIZE (20 * 1024 * 1024)
+#ifndef DROP_FILES_BUFFER_SIZE
+#define DROP_FILES_BUFFER_SIZE (20 * 1024 * 1024)
#endif
// ================================================================
//
-// PLATFORM API
+// Basic declarations
//
// ================================================================
-#if !defined(__wasm__)
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
-#include <stdlib.h>
+
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+// ================================================================
+//
+// Math
+//
+// ================================================================
+
+#if !defined(__wasm__)
#include <math.h>
+#else
+f64 floor(f64 x);
+f64 ceil(f64 x);
+f64 sqrt(f64 x);
+f64 cbrt(f64 x);
+f64 pow(f64 x, f64 y);
+f64 log(f64 x);
+f64 log2(f64 x);
+f64 log10(f64 x);
+f64 exp(f64 x);
+f64 sin(f64 x);
+f64 cos(f64 x);
+f64 tan(f64 x);
+f64 asin(f64 x);
+f64 acos(f64 x);
+f64 atan(f64 x);
+f64 atan2(f64 y, f64 x);
#endif
-#ifdef __cplusplus
-extern "C" {
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+#ifndef M_E
+#define M_E (2.71828182845904523536)
+#endif
+
+#ifndef M_LOG_2
+#define M_LOG_2 (0.69314718055994530941)
+#endif
+
+#ifndef M_LOG_10
+#define M_LOG_10 (2.30258509299404568402)
#endif
+#ifndef M_LOG2_E
+#define M_LOG2_E (1.44269504088896340736)
+#endif
+
+#ifndef M_LOG10_E
+#define M_LOG10_E (0.43429448190325182765)
+#endif
+
+#ifndef M_LOG_PI
+#define M_LOG_PI (1.14472988584940017414)
+#endif
+
+#ifndef M_SQRT_2
+#define M_SQRT_2 (1.41421356237309504880)
+#endif
+
+#ifndef M_SQRT_3
+#define M_SQRT_3 (1.73205080756887729352)
+#endif
+
+#ifndef M_SQRT_PI
+#define M_SQRT_PI (1.77245385090551602730)
+#endif
+
+#ifndef M_SQRT_E
+#define M_SQRT_E (1.64872127070012814685)
+#endif
+
+#ifndef M_CBRT_2
+#define M_CBRT_2 (1.25992104989487316476)
+#endif
+
+#ifndef M_CBRT_3
+#define M_CBRT_3 (1.44224957030740838232)
+#endif
+
+#ifndef M_CBRT_PI
+#define M_CBRT_PI (1.46459188756152326302)
+#endif
+
+#ifndef M_CBRT_E
+#define M_CBRT_E (1.39561242508608952863)
+#endif
+
+// ================================================================
+//
+// PLATFORM API
+//
+// ================================================================
+
enum {
IPv4_UDP = 1,
IPv6_UDP = 2,
@@ -417,6 +489,7 @@ typedef struct {
c8 *title;
i32 frame_width;
i32 frame_height;
+ i32 pixel_size;
b8 exact_resolution;
b8 graceful_exit;
@@ -426,7 +499,6 @@ typedef struct {
b8 files_dropped;
i32 real_width;
i32 real_height;
- i32 pixel_size;
i64 input_size;
i64 clipboard_size;
i32 cursor_x;
@@ -438,6 +510,7 @@ typedef struct {
i64 sound_clock_time;
i64 sound_clock_carry;
i64 num_sound_samples_elapsed;
+ i64 sound_position;
i64 num_drop_files;
Drop_File *drop_files;
@@ -448,7 +521,9 @@ typedef struct {
c8 clipboard [MAX_CLIPBOARD_SIZE];
b8 key_down [MAX_NUM_KEYS];
b8 key_pressed [MAX_NUM_KEYS];
- u8 drop_buffer [DROP_FILE_BUFFER_SIZE];
+
+ // TODO: Allocator for big buffers
+ u8 drop_files_buffer[DROP_FILES_BUFFER_SIZE];
} Platform;
typedef struct {
@@ -462,15 +537,11 @@ typedef struct {
} IP_Address;
// UTF-8
-// NOTE We need UTF-8 because we use Xutf8LookupString on Xlib.
+// NOTE: We need UTF-8 because we use Xutf8LookupString on Xlib.
i32 utf8_size(c32 c);
c32 utf8_read(i64 len, c8 *s);
i32 utf8_write(c32 c, c8 *buffer);
-// Color
-u32 rgb_u32_from_f32(vec3_f32 c);
-vec3_f32 rgb_f32_from_u32(u32 color);
-
// Time and sleep
i64 p_time(void);
void p_yield(void);
@@ -483,10 +554,6 @@ i32 p_handle_events(void);
i32 p_wait_events(void);
void p_render_frame(void);
-// User-defined frame updating procedure
-// NOTE This procedure is required for the WebAssembly compatibility.
-void update_and_render_frame(void);
-
// Convenient helper procedure for the event loop
void p_event_loop(void);
@@ -503,147 +570,16 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port);
extern Platform g_platform;
-#if defined(__wasm__)
-
-i32 main(i32 argc, c8 **argv);
-
-f64 floor(f64 x);
-f64 ceil(f64 x);
-f64 sqrt(f64 x);
-f64 cbrt(f64 x);
-f64 pow(f64 x, f64 y);
-f64 log(f64 x);
-f64 log2(f64 x);
-f64 log10(f64 x);
-f64 exp(f64 x);
-f64 sin(f64 x);
-f64 cos(f64 x);
-f64 tan(f64 x);
-f64 asin(f64 x);
-f64 acos(f64 x);
-f64 atan(f64 x);
-f64 atan2(f64 y, f64 x);
-
-#endif // defined(__wasm__)
-
-#ifndef NULL
-#define NULL ((void *) 0)
-#endif
-
-#ifndef M_PI
-#define M_PI (3.14159265358979323846)
-#endif
-
-#ifndef M_E
-#define M_E (2.71828182845904523536)
-#endif
-
-#ifndef M_LOG_2
-#define M_LOG_2 (0.69314718055994530941)
-#endif
-
-#ifndef M_LOG_10
-#define M_LOG_10 (2.30258509299404568402)
-#endif
-
-#ifndef M_LOG2_E
-#define M_LOG2_E (1.44269504088896340736)
-#endif
-
-#ifndef M_LOG10_E
-#define M_LOG10_E (0.43429448190325182765)
-#endif
-
-#ifndef M_LOG_PI
-#define M_LOG_PI (1.14472988584940017414)
-#endif
-
-#ifndef M_SQRT_2
-#define M_SQRT_2 (1.41421356237309504880)
-#endif
-
-#ifndef M_SQRT_3
-#define M_SQRT_3 (1.73205080756887729352)
-#endif
-
-#ifndef M_SQRT_PI
-#define M_SQRT_PI (1.77245385090551602730)
-#endif
-
-#ifndef M_SQRT_E
-#define M_SQRT_E (1.64872127070012814685)
-#endif
-
-#ifndef M_CBRT_2
-#define M_CBRT_2 (1.25992104989487316476)
-#endif
-
-#ifndef M_CBRT_3
-#define M_CBRT_3 (1.44224957030740838232)
-#endif
-
-#ifndef M_CBRT_PI
-#define M_CBRT_PI (1.46459188756152326302)
-#endif
-
-#ifndef M_CBRT_E
-#define M_CBRT_E (1.39561242508608952863)
-#endif
+// ================================================================
#ifdef __cplusplus
-}
+} // extern "C"
#endif
-// ================================================================
-
#endif // REDUCED_SYSTEM_LAYER_HEADER_GUARD_
// ================================================================
//
-// EXAMPLE CODE
-//
-// ================================================================
-
-#ifdef REDUCED_SYSTEM_LAYER_EXAMPLE
-
-void update_and_render_frame(void) {
- p_handle_events();
-
- i64 w = g_platform.frame_width / 2;
- i64 h = g_platform.frame_height / 2;
- i64 x = w / 2;
- i64 y = h / 2;
-
- for (i64 j = 0; j < g_platform.frame_height; ++j)
- for (i64 i = 0; i < g_platform.frame_width; ++i)
- if (i < x || i >= x + w || j < y || j >= y + h)
- g_platform.pixels[j * g_platform.frame_width + i] = (vec4_f32) { .8f, .8f, .8f, 1.f };
- else
- g_platform.pixels[j * g_platform.frame_width + i] = (vec4_f32) { .27f, .21f, .24f, 1.f };
-
- p_render_frame();
- p_sleep_for(0);
-}
-
-i32 main(i32 argc, c8 **argv) {
- (void) argc;
- (void) argv;
-
- g_platform = (Platform) {
- .title = "Example",
- .frame_width = 1280,
- .frame_height = 720,
- };
-
- p_event_loop();
-
- return 0;
-}
-
-#endif
-
-// ================================================================
-//
// PLATFORM IMPLEMENTATION
//
// ================================================================
@@ -747,7 +683,7 @@ i32 utf8_write(c32 c, c8 *buffer) {
return 0;
}
-u32 rgb_u32_from_f32(vec3_f32 c) {
+u32 rgb_u32_from_f32_(vec3_f32 c) {
i32 ir = (i32) floor(c.x * 255. + .5);
i32 ig = (i32) floor(c.y * 255. + .5);
i32 ib = (i32) floor(c.z * 255. + .5);
@@ -759,14 +695,6 @@ u32 rgb_u32_from_f32(vec3_f32 c) {
return (r << 16) | (g << 8) | b;
}
-vec3_f32 rgb_f32_from_u32(u32 color) {
- return (vec3_f32) {
- .x = (f32) ((color >> 16) & 0xff) / 255.,
- .y = (f32) ((color >> 8) & 0xff) / 255.,
- .z = (f32) ( color & 0xff) / 255.,
- };
-}
-
static i64 sound_samples_elapsed_(void) {
if (g_platform.sound_clock_time == 0) {
g_platform.sound_clock_time = p_time();
@@ -784,11 +712,8 @@ static i64 sound_samples_elapsed_(void) {
return num_samples;
}
-// TEMP
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-
static void drop_files_clean_(void) {
+ g_platform.files_dropped = 0;
g_platform.num_drop_files = 0;
g_platform.drop_files = NULL;
}
@@ -824,15 +749,15 @@ static void drop_files_set_num_(i64 num) {
return;
}
- i64 available = DROP_FILE_BUFFER_SIZE - drop_files_data_size_(g_platform.num_drop_files);
+ i64 available = DROP_FILES_BUFFER_SIZE - drop_files_data_size_(g_platform.num_drop_files);
if (available < num * (i64) sizeof(Drop_File))
return;
i64 src_size = (i64) sizeof(Drop_File) * g_platform.num_drop_files;
i64 dst_size = (i64) sizeof(Drop_File) * num;
- u8 *src = g_platform.drop_buffer + (DROP_FILE_BUFFER_SIZE - src_size);
- u8 *dst = g_platform.drop_buffer + (DROP_FILE_BUFFER_SIZE - num * (i64) sizeof(Drop_File));
+ u8 *src = g_platform.drop_files_buffer + (DROP_FILES_BUFFER_SIZE - src_size);
+ u8 *dst = g_platform.drop_files_buffer + (DROP_FILES_BUFFER_SIZE - num * (i64) sizeof(Drop_File));
for (i64 i = 0; i < src_size; ++i)
dst[i] = src[i];
@@ -843,53 +768,85 @@ static void drop_files_set_num_(i64 num) {
g_platform.drop_files = (Drop_File *) dst;
}
+static void drop_files_empty_after_(i64 index) {
+ if (g_platform.drop_files == NULL) {
+ LOG_ERROR("Sanity");
+ return;
+ }
+
+ for (i64 i = index + 1; i < g_platform.num_drop_files; ++i) {
+ if (g_platform.drop_files[i].name_size != 0) {
+ LOG_ERROR("Sanity");
+ g_platform.drop_files[i].name_size = 0;
+ }
+
+ if (g_platform.drop_files[i].data_size != 0) {
+ LOG_ERROR("Sanity");
+ g_platform.drop_files[i].data_size = 0;
+ }
+ }
+}
+
+static void drop_files_empty_data_after_(i64 index) {
+ if (g_platform.drop_files == NULL) {
+ LOG_ERROR("Sanity");
+ return;
+ }
+
+ for (i64 i = index + 1; i < g_platform.num_drop_files; ++i) {
+ if (g_platform.drop_files[i].data_size != 0) {
+ LOG_ERROR("Sanity");
+ g_platform.drop_files[i].data_size = 0;
+ }
+ }
+}
+
static void drop_files_set_name_(i64 index, i64 name_size, c8 *name) {
- if (g_platform.drop_files == NULL || index + 1 != g_platform.num_drop_files) {
+ if (g_platform.drop_files == NULL) {
LOG_ERROR("Sanity");
return;
}
+ drop_files_empty_after_(index);
+
i64 offset = drop_files_data_size_(index);
- i64 available = DROP_FILE_BUFFER_SIZE - offset - g_platform.num_drop_files * sizeof(Drop_File);
+ i64 available = DROP_FILES_BUFFER_SIZE - offset - g_platform.num_drop_files * sizeof(Drop_File);
if (available < name_size + 1) {
- LOG_ERROR("Sanity");
+ LOG_ERROR("Out of memory");
return;
}
g_platform.drop_files[index].name_size = name_size + 1;
- g_platform.drop_files[index].name = (c8 *) g_platform.drop_buffer + offset;
+ g_platform.drop_files[index].name = (c8 *) g_platform.drop_files_buffer + offset;
for (i64 i = 0; i < name_size; ++i)
g_platform.drop_files[index].name[i] = name[i];
g_platform.drop_files[index].name[name_size] = '\0';
}
-static void drop_files_set_data_(i64 index, i64 data_size, u8 *data) {
- if (g_platform.drop_files == NULL || index + 1 != g_platform.num_drop_files) {
+static void drop_files_set_data_(i64 index, i64 data_size) {
+ if (g_platform.drop_files == NULL) {
LOG_ERROR("Sanity");
return;
}
+ drop_files_empty_data_after_(index);
+
g_platform.drop_files[index].data_size = 0;
i64 offset = drop_files_data_size_(index + 1);
- i64 available = DROP_FILE_BUFFER_SIZE - offset - g_platform.num_drop_files * sizeof(Drop_File);
+ i64 available = DROP_FILES_BUFFER_SIZE - offset - g_platform.num_drop_files * sizeof(Drop_File);
if (available < data_size) {
- LOG_ERROR("Sanity");
+ LOG_ERROR("Out of memory");
return;
}
g_platform.drop_files[index].data_size = data_size;
- g_platform.drop_files[index].data = g_platform.drop_buffer + offset;
-
- for (i64 i = 0; i < data_size; ++i)
- g_platform.drop_files[index].data[i] = data[i];
+ g_platform.drop_files[index].data = g_platform.drop_files_buffer + offset;
}
-#pragma GCC diagnostic pop
-
// ================================================================
//
// Unix
@@ -913,10 +870,10 @@ void p_yield(void) {
}
void p_sleep_for(i64 duration) {
- if (duration <= 0) {
+ if (duration == 0)
usleep(0);
+ if (duration <= 0)
return;
- }
if (duration >= 1000)
// seconds
@@ -1182,14 +1139,13 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
#include <alsa/asoundlib.h>
static b8 _sound_ready = 0;
-static i64 _sound_position = 0;
static snd_pcm_t *_sound_out = NULL;
static void sound_init(void) {
if (_sound_ready)
return;
- _sound_position = 0;
+ g_platform.sound_position = 0;
i32 s;
@@ -1263,7 +1219,7 @@ static void sound_cleanup(void) {
if (s < 0)
LOG_ERROR("snd_pcm_drain failed: %s", snd_strerror(s));
- // FIXME Memory leaks, seems to be an ALSA bug.
+ // FIXME: Memory leaks, seems to be an ALSA bug.
// snd_pcm_close(_sound_out);
// snd_config_update_free_global();
@@ -1283,17 +1239,17 @@ void p_handle_sound(void) {
i32 s;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - _sound_position) {
- s = snd_pcm_writei(_sound_out, g_platform.sound_ring + _sound_position, num_frames / NUM_SOUND_CHANNELS);
+ if (num_frames <= MAX_NUM_SOUND_FRAMES - g_platform.sound_position) {
+ s = snd_pcm_writei(_sound_out, g_platform.sound_ring + g_platform.sound_position, num_frames / NUM_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
- memset(g_platform.sound_ring + _sound_position, 0, num_frames * sizeof *g_platform.sound_ring);
+ memset(g_platform.sound_ring + g_platform.sound_position, 0, num_frames * sizeof *g_platform.sound_ring);
} else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - _sound_position;
+ i64 part_one = MAX_NUM_SOUND_FRAMES - g_platform.sound_position;
i64 part_two = num_frames - part_one;
- s = snd_pcm_writei(_sound_out, g_platform.sound_ring + _sound_position, part_one / NUM_SOUND_CHANNELS);
+ s = snd_pcm_writei(_sound_out, g_platform.sound_ring + g_platform.sound_position, part_one / NUM_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
@@ -1301,11 +1257,11 @@ void p_handle_sound(void) {
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
- memset(g_platform.sound_ring + _sound_position, 0, part_one * sizeof *g_platform.sound_ring);
+ memset(g_platform.sound_ring + g_platform.sound_position, 0, part_one * sizeof *g_platform.sound_ring);
memset(g_platform.sound_ring, 0, part_two * sizeof *g_platform.sound_ring);
}
- _sound_position = (_sound_position + num_frames) % MAX_NUM_SOUND_FRAMES;
+ g_platform.sound_position = (g_platform.sound_position + num_frames) % MAX_NUM_SOUND_FRAMES;
}
void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
@@ -1326,13 +1282,13 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
if (num_frames > MAX_NUM_SOUND_FRAMES) {
- LOG_ERROR("Sound buffer overflow.");
+ LOG_ERROR("Sound buffer overflow.");
return;
}
sound_init();
- i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES;
+ i64 begin = (g_platform.sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES;
if (num_frames <= MAX_NUM_SOUND_FRAMES - begin)
for (i64 i = 0; i < num_frames; ++i)
@@ -1358,22 +1314,43 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
#if defined(__linux__)
+#include <sys/stat.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
-static i64 _frame_time = 0;
-static XImage _image = {0};
-static Display *_display = NULL;
-static GC _gc = NULL;
-static XIM _im = NULL;
-static XIC _ic = NULL;
-static Window _window = 0;
-static Atom _wm_delete_window = 0;
-static Atom _clipboard = 0;
-static Atom _targets = 0;
-static Atom _utf8_string = 0;
-static Atom _target = None;
+static i64 _frame_time = 0;
+static XImage _image = {0};
+static Display *_display = NULL;
+static GC _gc = NULL;
+static XIM _im = NULL;
+static XIC _ic = NULL;
+static Window _window = 0;
+static Window _drop_source = 0;
+static Atom _wm_delete_window = 0;
+static Atom _clipboard = 0;
+static Atom _targets = 0;
+static Atom _utf8_string = 0;
+static Atom _target = 0;
+static Atom _dnd_type_list = 0;
+static Atom _dnd_selection = 0;
+static Atom _dnd_enter = 0;
+static Atom _dnd_position = 0;
+static Atom _dnd_status = 0;
+static Atom _dnd_leave = 0;
+static Atom _dnd_drop = 0;
+static Atom _dnd_finished = 0;
+static Atom _dnd_action_copy = 0;
+static Atom _dnd_action_move = 0;
+static Atom _dnd_action_link = 0;
+static Atom _dnd_action_ask = 0;
+static Atom _dnd_action_private = 0;
+static Atom _text_uri_list = 0;
+static Atom _text_plain = 0;
+static Atom _dnd_aware = 0;
+static Window _dnd_source = 0;
+static Atom _dnd_format = 0;
+static u32 _dnd_version = 0;
static i16 _key_table [MAX_NUM_KEYS] = {0};
static b8 _key_repeat [MAX_NUM_KEYS] = {0};
@@ -1567,12 +1544,35 @@ void p_init(void) {
_targets = XInternAtom(_display, "TARGETS", False);
_utf8_string = XInternAtom(_display, "UTF8_STRING", False);
+ _target = None;
+
XSetICFocus(_ic);
XSetWMProtocols(_display, _window, &_wm_delete_window, 1);
if (g_platform.title != NULL)
XStoreName(_display, _window, g_platform.title);
+ _dnd_type_list = XInternAtom(_display, "XdndTypeList", False);
+ _dnd_selection = XInternAtom(_display, "XdndSelection", False);
+ _dnd_enter = XInternAtom(_display, "XdndEnter", False);
+ _dnd_position = XInternAtom(_display, "XdndPosition", False);
+ _dnd_status = XInternAtom(_display, "XdndStatus", False);
+ _dnd_leave = XInternAtom(_display, "XdndLeave", False);
+ _dnd_drop = XInternAtom(_display, "XdndDrop", False);
+ _dnd_finished = XInternAtom(_display, "XdndFinished", False);
+ _dnd_action_copy = XInternAtom(_display, "XdndActionCopy", False);
+ _dnd_action_move = XInternAtom(_display, "XdndActionMove", False);
+ _dnd_action_link = XInternAtom(_display, "XdndActionLink", False);
+ _dnd_action_ask = XInternAtom(_display, "XdndActionAsk", False);
+ _dnd_action_private = XInternAtom(_display, "XdndActionPrivate", False);
+ _text_uri_list = XInternAtom(_display, "text/uri-list", False);
+ _text_plain = XInternAtom(_display, "text/plain", False);
+ _dnd_aware = XInternAtom(_display, "XdndAware", False);
+
+ _dnd_format = None;
+
+ XChangeProperty(_display, _window, _dnd_aware, 4, 32, PropModeReplace, &(u8) {5}, 1);
+
XMapWindow(_display, _window);
XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, _image.width, _image.height);
@@ -1603,6 +1603,9 @@ i32 p_handle_events(void) {
i32 num_events = 0;
+ if (g_platform.files_dropped)
+ drop_files_clean_();
+
memset(g_platform.key_pressed, 0, sizeof g_platform.key_pressed);
memset(_key_repeat, 0, sizeof _key_repeat);
@@ -1789,7 +1792,75 @@ i32 p_handle_events(void) {
break;
case SelectionNotify:
- if (ev.xselection.property != None) {
+ if (ev.xselection.property == _dnd_selection) {
+ u8 *data;
+ i32 len;
+
+ XGetWindowProperty(
+ _display,
+ ev.xselection.requestor,
+ _dnd_selection,
+ 0,
+ DROP_FILES_BUFFER_SIZE,
+ False,
+ ev.xselection.target,
+ &(Atom) {0},
+ &(i32) {0},
+ (void *) &len,
+ &(unsigned long) {0},
+ &data
+ );
+
+ if (len == 0)
+ break;
+
+ if (data) {
+ i64 num = 0;
+ for (i64 i = 0; i < len; ++i)
+ if (data[i] == '\n' || i + 1 == len)
+ ++num;
+ drop_files_set_num_(num);
+
+ i64 index = 0;
+ i64 offset = 0;
+
+ for (i64 i = 0; i < len; ++i)
+ if (data[i] == '\n' || i + 1 == len) {
+ drop_files_set_name_(index, i - offset, (c8 *) data + offset);
+
+ ++index;
+ offset = i + 1;
+ }
+
+ XFree(data);
+ }
+
+ if (_dnd_version >= 2) {
+ XSendEvent(
+ _display,
+ _dnd_source,
+ False,
+ NoEventMask,
+ &(XEvent) {
+ .xclient = {
+ .type = ClientMessage,
+ .message_type = _dnd_finished,
+ .window = _drop_source,
+ .format = 32,
+ .data = {
+ .l = {
+ _window,
+ len,
+ _dnd_action_copy,
+ },
+ },
+ },
+ }
+ );
+
+ XFlush(_display);
+ }
+ } else if (ev.xselection.property != None) {
i64 len = 0;
u8 *data = NULL;
@@ -1802,8 +1873,8 @@ i32 p_handle_events(void) {
False,
AnyPropertyType,
&(Atom) {0},
- &(int) {0},
- (unsigned long *) &len,
+ &(i32) {0},
+ (void *) &len,
&(unsigned long) {0},
&data
);
@@ -1833,6 +1904,7 @@ i32 p_handle_events(void) {
if (data)
XFree(data);
}
+
break;
case EnterNotify: g_platform.has_cursor = 1; break;
@@ -1854,6 +1926,163 @@ i32 p_handle_events(void) {
case ClientMessage:
if ((Atom) ev.xclient.data.l[0] == _wm_delete_window)
g_platform.done = 1;
+ else {
+ if (ev.xclient.message_type == _dnd_enter) {
+ i64 count;
+ Atom *formats;
+ Atom real_formats[6];
+
+ u32 list = ev.xclient.data.l[1] & 1;
+
+ _dnd_source = ev.xclient.data.l[0];
+ _dnd_format = None;
+ _dnd_version = ev.xclient.data.l[1] >> 24;
+
+ if (_dnd_version > 5) {
+ LOG_ERROR("X client message version not supported: %d.", _dnd_version);
+ break;
+ }
+
+ if (list)
+ XGetWindowProperty(
+ _display,
+ _dnd_source,
+ _dnd_type_list,
+ 0,
+ DROP_FILES_BUFFER_SIZE / 4,
+ False,
+ 4,
+ &(Atom) {0},
+ &(i32) {0},
+ (void *) &count,
+ &(unsigned long) {0},
+ (void *) &formats
+ );
+ else {
+ count = 0;
+
+ if (ev.xclient.data.l[2] != None) real_formats[count++] = ev.xclient.data.l[2];
+ if (ev.xclient.data.l[3] != None) real_formats[count++] = ev.xclient.data.l[3];
+ if (ev.xclient.data.l[4] != None) real_formats[count++] = ev.xclient.data.l[4];
+
+ formats = real_formats;
+ }
+
+ for (i64 i = 0; i < count; ++i)
+ if (formats[i] == _text_uri_list || formats[i] == _text_plain) {
+ _dnd_format = formats[i];
+ break;
+ }
+
+ if (list)
+ XFree(formats);
+
+ break;
+ }
+
+ if (_dnd_version > 5)
+ break;
+
+ if (ev.xclient.message_type == _dnd_position) {
+ i32 xabs = (ev.xclient.data.l[2] >> 16) & 0xffff;
+ i32 yabs = ev.xclient.data.l[2] & 0xffff;
+
+ Window dummy;
+ i32 xpos;
+ i32 ypos;
+
+ XTranslateCoordinates(
+ _display,
+ XDefaultRootWindow(_display),
+ _window,
+ xabs, yabs,
+ &xpos, &ypos,
+ &dummy
+ );
+
+ g_platform.cursor_dx += xpos - g_platform.cursor_x;
+ g_platform.cursor_dy += ypos - g_platform.cursor_y;
+ g_platform.cursor_x = xpos;
+ g_platform.cursor_y = ypos;
+
+ XEvent reply = {
+ .xclient = {
+ .type = ClientMessage,
+ .message_type = _dnd_status,
+ .window = _drop_source,
+ .format = 32,
+ .data = {
+ .l = { _window, },
+ },
+ },
+ };
+
+ if (_dnd_format) {
+ reply.xclient.data.l[1] = 1;
+ if (_dnd_version >= 2)
+ reply.xclient.data.l[4] = _dnd_action_copy;
+ }
+
+ XSendEvent(_display, _dnd_source, False, NoEventMask, &reply);
+ XFlush(_display);
+ } else if (ev.xclient.message_type == _dnd_drop) {
+ g_platform.files_dropped = 1;
+
+ if (g_platform.drop_files == NULL)
+ LOG_ERROR("No drop files.");
+ else
+ for (i64 i = 0; i < g_platform.num_drop_files; ++i) {
+ FILE *f = fopen(g_platform.drop_files[i].name, "rb");
+
+ if (f != NULL) {
+ i64 size = 0;
+ struct stat info;
+ if (fstat(fileno(f), &info) == 0 && S_ISREG(info.st_mode))
+ size = (i64) info.st_size;
+ else
+ LOG_ERROR("Unable to get the file info: %s", g_platform.drop_files[i].name);
+
+ drop_files_set_data_(i, size);
+
+ i64 num = (i64) fread(g_platform.drop_files[i].data, 1, g_platform.drop_files[i].data_size + 1, f);
+ fclose(f);
+
+ if (num != g_platform.drop_files[i].data_size) {
+ LOG_ERROR("Unable to read the file: %s", g_platform.drop_files[i].name);
+ drop_files_set_data_(i, 0);
+ }
+ } else
+ LOG_ERROR("Unable to open the file: %s", g_platform.drop_files[i].name);
+ }
+
+ if (_dnd_format)
+ XConvertSelection(
+ _display,
+ _dnd_selection,
+ _dnd_format,
+ _dnd_selection,
+ _window,
+ _dnd_version >= 1 ? ev.xclient.data.l[2] : CurrentTime
+ );
+ else if (_dnd_version >= 2) {
+ XEvent reply = {
+ .xclient = {
+ .type = ClientMessage,
+ .message_type = _dnd_finished,
+ .window = _drop_source,
+ .format = 32,
+ .data = {
+ .l = { _window, },
+ },
+ },
+ };
+
+ XSendEvent(_display, _dnd_source, False, NoEventMask, &reply);
+ XFlush(_display);
+ }
+ }
+ }
+
break;
default:;
@@ -1918,11 +2147,11 @@ void p_render_frame(void) {
if (g_platform.frame_width == _image.width && g_platform.frame_height == _image.height) {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_internal[i] = rgb_u32_from_f32((vec3_f32) { g_platform.pixels[i].x, g_platform.pixels[i].y, g_platform.pixels[i].z });
+ _pixels_internal[i] = rgb_u32_from_f32_((vec3_f32) { g_platform.pixels[i].x, g_platform.pixels[i].y, g_platform.pixels[i].z });
} else {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_scaled[i] = rgb_u32_from_f32((vec3_f32) { g_platform.pixels[i].x, g_platform.pixels[i].y, g_platform.pixels[i].z });
+ _pixels_scaled[i] = rgb_u32_from_f32_((vec3_f32) { g_platform.pixels[i].x, g_platform.pixels[i].y, g_platform.pixels[i].z });
for (i64 j = 0; j < _image.height; ++j) {
i64 j0 = (j * g_platform.frame_height) / _image.height;
@@ -1975,7 +2204,6 @@ static i32 _num_events = 0;
static i32 _input_size = 0;
static b8 _wait_events = 0;
static i64 _timeout = 0;
-static i64 _sound_position = 0;
static i64 _sound_read = 0;
static u16 _key_map [MAX_NUM_KEYS] = {0};
@@ -2002,6 +2230,9 @@ i64 p_time(void) {
}
void p_sleep_for(i64 duration) {
+ if (duration <= 0)
+ return;
+
i64 t = p_time();
if (_timeout < t)
@@ -2012,9 +2243,11 @@ void p_sleep_for(i64 duration) {
void p_init(void) {
++_num_events;
- g_platform.done = 1;
- _sound_position = SOUND_AVAIL_MIN % MAX_NUM_SOUND_FRAMES;
- _sound_read = 0;
+
+ g_platform.done = 1;
+ g_platform.sound_position = 0;
+
+ _sound_read = (MAX_NUM_SOUND_FRAMES + ((-SOUND_AVAIL_MIN) % MAX_NUM_SOUND_FRAMES)) % MAX_NUM_SOUND_FRAMES;
}
i32 p_handle_events(void) {
@@ -2041,11 +2274,11 @@ void p_render_frame(void) {
if (_frame_width == g_platform.frame_width && _frame_height == g_platform.frame_height) {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_internal[i] = 0xff000000u | rgb_u32_from_f32((vec3_f32) { g_platform.pixels[i].z, g_platform.pixels[i].y, g_platform.pixels[i].x });
+ _pixels_internal[i] = 0xff000000u | rgb_u32_from_f32_((vec3_f32) { g_platform.pixels[i].z, g_platform.pixels[i].y, g_platform.pixels[i].x });
} else {
i64 size = g_platform.frame_width * g_platform.frame_height;
for (i64 i = 0; i < size; ++i)
- _pixels_scaled[i] = rgb_u32_from_f32((vec3_f32) { g_platform.pixels[i].z, g_platform.pixels[i].y, g_platform.pixels[i].x });
+ _pixels_scaled[i] = rgb_u32_from_f32_((vec3_f32) { g_platform.pixels[i].z, g_platform.pixels[i].y, g_platform.pixels[i].x });
for (i64 j = 0; j < _frame_height; ++j) {
i64 j0 = (j * g_platform.frame_height) / _frame_height;
@@ -2074,7 +2307,7 @@ void p_clipboard_write(i64 size, c8 *data) {
void p_handle_sound(void) {
g_platform.num_sound_samples_elapsed = sound_samples_elapsed_();
- _sound_position = (_sound_position + g_platform.num_sound_samples_elapsed * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ g_platform.sound_position = (g_platform.sound_position + g_platform.num_sound_samples_elapsed * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
}
void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
@@ -2094,7 +2327,7 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_frames > MAX_NUM_SOUND_FRAMES)
return;
- i64 begin = (_sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ i64 begin = (g_platform.sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
if (num_frames <= MAX_NUM_SOUND_FRAMES - begin)
for (i64 i = 0; i < num_frames; ++i)
@@ -2242,6 +2475,11 @@ __attribute__((export_name("js_href_size"))) i32 js_href_size(void) {
}
__attribute__((export_name("js_main"))) void js_main(void) {
+ (void) drop_files_clean_;
+ (void) drop_files_set_num_;
+ (void) drop_files_set_name_;
+ (void) drop_files_set_data_;
+
main(1, (c8 *[1]) { _href });
}
diff --git a/test.c b/test.c
index 3051910..fc6088f 100644
--- a/test.c
+++ b/test.c
@@ -60,10 +60,23 @@ typedef unsigned u32;
typedef unsigned long long u64;
typedef char c8;
typedef int c32;
-typedef signed char b8;
+typedef unsigned char b8;
typedef float f32;
typedef double f64;
+typedef struct { f64 x, y; } vec2;
+typedef struct { f64 x, y, z; } vec3;
+typedef struct { f64 x, y, z, w; } vec4;
+typedef struct { f32 x, y; } vec2_f32;
+typedef struct { f32 x, y, z; } vec3_f32;
+typedef struct { f32 x, y, z, w; } vec4_f32;
+typedef struct { i64 x, y; } vec2_i64;
+typedef struct { i64 x, y, z; } vec3_i64;
+typedef struct { i64 x, y, z, w; } vec4_i64;
+typedef struct { f64 v[ 4]; } mat2;
+typedef struct { f64 v[ 9]; } mat3;
+typedef struct { f64 v[16]; } mat4;
+
#endif // TYPES_HEADER_GUARD_
// ================================================================
@@ -352,7 +365,7 @@ static void test_handle_signal(i32 signum) {
longjmp(test_restore_execution, signum);
}
-static void test_setup_signals() {
+static void test_setup_signals(void) {
for (u32 i = 0; i < sizeof signums_ / sizeof *signums_; i++)
signal(signums_[i], test_handle_signal);
}
@@ -696,7 +709,7 @@ void bench_register(c8 const *name, c8 const *file, bench_run_fn fn) {
}
}
-static void bench_setup_signals() {
+static void bench_setup_signals(void) {
for (u32 i = 0; i < sizeof signums_ / sizeof *signums_; i++)
signal(signums_[i], test_handle_signal);
}
@@ -726,7 +739,6 @@ static i32 compare_32_(void const *x_, void const *y_) {
}
i32 run_benchmarks(i32 argc, c8 **argv) {
- i32 success_count = 0;
i32 status = 0;
i32 no_color = 0;
i32 line_width = 20;
@@ -895,7 +907,6 @@ i32 run_benchmarks(i32 argc, c8 **argv) {
if (bench->repeats <= 0) {
no_color || print_color_(yellow_);
printf(" 0 runs\n");
- success_count++;
} else if (bench_status == 0) {
no_color || print_color_(red_);
printf(" FAIL\n");
@@ -922,7 +933,6 @@ i32 run_benchmarks(i32 argc, c8 **argv) {
printf("%-9g", (f64) roof * 0.001);
no_color || print_color_(light_);
printf(" %d runs\n", repeats);
- success_count++;
}
}
}