summaryrefslogtreecommitdiff
path: root/reduced_system_layer.c
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-02-02 14:38:13 +0100
committerMitya Selivanov <automainint@guattari.tech>2025-02-02 14:38:13 +0100
commit27b4343c2a7e2583881485a5ac667894fec729f0 (patch)
tree018df2c4df87ef39f9c828a1d6e255825ee7ed9b /reduced_system_layer.c
parentbc9e6042e709b7790f2f130dde08b13c929653b1 (diff)
downloadreduced_system_layer-perf.zip
Refactor, renaming (work in progress)perf
Diffstat (limited to 'reduced_system_layer.c')
-rw-r--r--reduced_system_layer.c380
1 files changed, 231 insertions, 149 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 38b80dd..fff4f44 100644
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -23,6 +23,18 @@
// - Optimized to use in a single source file.
// Installation process? Ctrl+C, Ctrl+V, done.
//
+// STYLE CONVENTIONS
+//
+// - Capitalized_Snake_Case - Type name.
+// - snake_case - Non-type name.
+// - UPPER_SNAKE_CASE - Macro or constant.
+// - g_ prefix - Global variable name.
+//
+// Most procedures have long and descriptive names.
+// Some procedures have prefixes according to their domain.
+//
+// There may be exceptions if convenient.
+//
// ----------------------------------------------------------------
//
// To-Do list
@@ -62,10 +74,21 @@
// - Windows audio
// - Recording
// - Device selection
+// - Switching canvases - Web
// - Networking
// - Windows sockets
// - TCP
-// - Switching canvases - Web
+// - fetch - via libcurl on native platforms
+// - Cross-platform networking - UDP + TCP + WebSocket
+// Requires:
+// - [ ] Sockets - UDP, TCP
+// - [ ] HTTP client
+// - [ ] HTTP server
+// - [ ] Web sockets
+// - [ ] Key exchange
+// - [ ] Cipher suite (Lattice-based?)
+// - [ ] TLS
+// - [ ] Web sockets over TLS
// - Long term
// - dlopen - load libraries conditionally
// - X11
@@ -79,14 +102,11 @@
// - 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
-// - HTTP
// - Cryptography - https://github.com/jedisct1/supercop
-// - Web sockets
// - macOS support
// - Mobile devices support
//
@@ -101,6 +121,7 @@
// - Utility
// - UTF-8
// - Testing
+// - Stackless coroutines
// - Graphics
// - Font
// - Adaptive resolution
@@ -197,12 +218,18 @@ i32 main(i32 argc, c8 **argv);
#define NO_X11 0
#endif
+#ifndef STATIC_MEMORY_BUFFER_SIZE
+#define STATIC_MEMORY_BUFFER_SIZE (10 * 1024 * 1024)
+#endif
+
+// ----------------------------------------------------------------
+// TEMP: Static buffers.
+
#ifndef MAX_NUM_PIXELS
#define MAX_NUM_PIXELS (4 * 1024 * 1024)
#endif
#ifndef MAX_INPUT_SIZE
-// How many input events can be buffered during one frame.
#define MAX_INPUT_SIZE 256
#endif
@@ -222,6 +249,16 @@ i32 main(i32 argc, c8 **argv);
#define MAX_NUM_KEYS 512
#endif
+#ifndef MAX_NUM_PRIMARY_SOUND_FRAMES
+#define MAX_NUM_PRIMARY_SOUND_FRAMES (4 * 2 * 44100)
+#endif
+
+#ifndef DROP_FILES_BUFFER_SIZE
+#define DROP_FILES_BUFFER_SIZE (8 * 1024 * 1024)
+#endif
+
+// ----------------------------------------------------------------
+
#ifndef MIN_PIXEL_SIZE
#define MIN_PIXEL_SIZE (1.0)
#endif
@@ -238,19 +275,19 @@ i32 main(i32 argc, c8 **argv);
#define PIXEL_SIZE_DELTA (0.05)
#endif
-#ifndef MIN_FRAME_DURATION
// The pixel size will decrease when the frame duration is lower.
+#ifndef MIN_FRAME_DURATION
#define MIN_FRAME_DURATION 17
#endif
-#ifndef MAX_FRAME_DURATION
// The pixel size will increase when the frame duration is higher.
-#define MAX_FRAME_DURATION 34
+#ifndef MAX_FRAME_DURATION
+#define MAX_FRAME_DURATION 32
#endif
-#ifndef FRAME_DURATION_HARD_LIMIT
// The pixel size value will reset if the frame duration is higher.
-#define FRAME_DURATION_HARD_LIMIT 400
+#ifndef FRAME_DURATION_HARD_LIMIT
+#define FRAME_DURATION_HARD_LIMIT 200
#endif
#ifndef NUM_FRAMES_AVERAGED
@@ -258,33 +295,19 @@ i32 main(i32 argc, c8 **argv);
#endif
#ifndef AVERAGE_FRAME_BIAS
-#if defined(__wasm__)
-// NOTE: Web frame rate is quite unstable, so
-// we always pick the longest frame.
-#define AVERAGE_FRAME_BIAS (0.00)
-#else
#define AVERAGE_FRAME_BIAS (0.02)
#endif
-#endif
-
-#ifndef NUM_SOUND_CHANNELS
-#define NUM_SOUND_CHANNELS 2
-#endif
-#ifndef SOUND_SAMPLE_RATE
-#define SOUND_SAMPLE_RATE 44100
+#ifndef NUM_PRIMARY_SOUND_CHANNELS
+#define NUM_PRIMARY_SOUND_CHANNELS 2
#endif
-#ifndef SOUND_AVAIL_MIN
-#define SOUND_AVAIL_MIN 512
+#ifndef PRIMARY_SOUND_SAMPLE_RATE
+#define PRIMARY_SOUND_SAMPLE_RATE 44100
#endif
-#ifndef MAX_NUM_SOUND_FRAMES
-#define MAX_NUM_SOUND_FRAMES (4 * SOUND_SAMPLE_RATE * NUM_SOUND_CHANNELS)
-#endif
-
-#ifndef DROP_FILES_BUFFER_SIZE
-#define DROP_FILES_BUFFER_SIZE (8 * 1024 * 1024)
+#ifndef PRIMARY_SOUND_AVAIL_MIN
+#define PRIMARY_SOUND_AVAIL_MIN 512
#endif
#ifndef MOUSE_WHEEL_FACTOR
@@ -570,7 +593,7 @@ typedef struct {
i32 frame_height;
f64 pixel_size;
b8 exact_resolution;
- b8 graceful_exit;
+ b8 graceful_shutdown;
b8 done;
b8 has_focus;
@@ -603,6 +626,9 @@ typedef struct {
f32 clipboard_sound [MAX_CLIPBOARD_SIZE];
b8 key_down [MAX_NUM_KEYS];
b8 key_pressed [MAX_NUM_KEYS];
+
+ i64 memory_buffer_size;
+ u8 *memory_buffer;
} Platform;
// UTF-8
@@ -612,35 +638,41 @@ UTF8_Char utf8_read (i64 len, c8 *s);
i8 utf8_write(c32 c, c8 *buffer);
// Time and sleep
-i64 p_time(void);
-void p_yield(void);
-void p_sleep_for(i64 duration);
+i64 current_utc_time_in_milliseconds(void);
+void yield_thread_execution(void);
+void suspend_thread_for_milliseconds(i64 duration);
// Window
-void p_init(void);
-void p_cleanup(void);
-i32 p_handle_events(void);
-i32 p_wait_events(void);
-void p_render_frame(void);
+void init_main_window(void);
+i32 handle_main_window_events(void);
+i32 wait_main_window_events(void);
+void render_main_window_frame(void);
// Convenient helper procedure for the event loop
-void p_event_loop(void);
+void run_main_window_event_loop(void);
// Clipboard
-void p_clipboard_write_text(i64 size, c8 *data);
-void p_clipboard_write_image(i64 width, i64 heiht, vec4_f32 *pixels);
-void p_clipboard_write_sound(i8 num_channels, i64 num_samples, f32 *frames);
+void write_clipboard_text(i64 size, c8 *data);
+void write_clipboard_image(i64 width, i64 heiht, vec4_f32 *pixels);
+void write_clipboard_sound(i8 num_channels, i64 num_samples, f32 *frames);
// Take a screenshot
-void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels);
+void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels);
// Sound
-void p_handle_sound(void);
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames);
+void handle_primary_sound(void);
+void queue_primary_sound(i64 delay_in_samples, i64 num_samples, f32 *frames);
+
+// Networking
+i64 network_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address);
+i64 network_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port);
+
+// NOTE: This will shutdown main window, networking and audio.
+// If g_platform.graceful_shutdown is 0, this does nothing.
+void shutdown_all_systems(void);
-// UDP sockets
-i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address);
-i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port);
+// Memory
+void *seldom_memory_allocate(i64 size, i64 alignment, i64 previous_size, void *previous_data);
#ifdef REDUCED_SYSTEM_LAYER_HEADER
extern Platform g_platform;
@@ -669,23 +701,23 @@ Platform g_platform = {0};
static i64 _sound_clock_time = 0;
static i64 _sound_clock_carry = 0;
static i64 _sound_position = 0;
-static i64 _frame_index = 0;
+static i64 _frame_index = 0;
-static f32 _sound_ring [MAX_NUM_SOUND_FRAMES] = {0};
+static f32 _sound_ring [MAX_NUM_PRIMARY_SOUND_FRAMES] = {0};
static u8 _drop_files_buffer [DROP_FILES_BUFFER_SIZE] = {0};
-static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0};
+static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0};
-void p_event_loop(void) {
- p_init();
+void run_main_window_event_loop(void) {
+ init_main_window();
#if !defined(__wasm__)
while (!g_platform.done) update_and_render_frame();
- p_cleanup();
+ shutdown_all_systems();
#endif
}
// ================================================================
//
-// Utilities
+// Log
//
// ================================================================
@@ -702,6 +734,45 @@ void p_event_loop(void) {
} while (0)
#endif
+// ================================================================
+//
+// Seldom memory allocator
+//
+// ================================================================
+
+typedef struct {
+ i64 offset;
+ i64 size;
+} Memory_Slot_;
+
+static u8 memory_buffer_[STATIC_MEMORY_BUFFER_SIZE] = {0};
+
+static i64 num_memory_slots_(void) {
+ return *(i64 *) &g_platform.memory_buffer[g_platform.memory_buffer_size - 8];
+}
+
+void *seldom_memory_allocate(i64 size, i64 alignment, i64 previous_size, void *previous_data) {
+ if (g_platform.memory_buffer_size < 0)
+ LOG_ERROR("Invalid memory buffer size.");
+ if (g_platform.memory_buffer == NULL && g_platform.memory_buffer_size > 0)
+ LOG_ERROR("Invalid memory buffer.");
+
+ if (g_platform.memory_buffer == NULL || g_platform.memory_buffer_size <= 0) {
+ g_platform.memory_buffer_size = sizeof memory_buffer_;
+ g_platform.memory_buffer = memory_buffer_;
+ }
+
+ // TODO
+ LOG_ERROR("Not implemented.");
+ return NULL;
+}
+
+// ================================================================
+//
+// Utilities
+//
+// ================================================================
+
i8 utf8_size(c32 c) {
if ((c & 0x00007f) == c) return 1;
if ((c & 0x0007ff) == c) return 2;
@@ -825,13 +896,13 @@ static i64 average_frame_duration_(i64 duration) {
static i64 sound_samples_elapsed_(void) {
if (_sound_clock_time == 0) {
- _sound_clock_time = p_time();
+ _sound_clock_time = current_utc_time_in_milliseconds();
_sound_clock_carry = 0;
return 0;
}
- i64 time_elapsed = p_time() - _sound_clock_time;
- i64 delta = time_elapsed * SOUND_SAMPLE_RATE + _sound_clock_carry;
+ i64 time_elapsed = current_utc_time_in_milliseconds() - _sound_clock_time;
+ i64 delta = time_elapsed * PRIMARY_SOUND_SAMPLE_RATE + _sound_clock_carry;
i64 num_samples = delta / 1000;
_sound_clock_time += time_elapsed;
@@ -922,12 +993,11 @@ static void drop_files_empty_data_after_(i64 index) {
return;
}
- for (i64 i = index + 1; i < g_platform.num_drop_files; ++i) {
+ 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_len, c8 *name) {
@@ -1032,17 +1102,17 @@ static void pixel_size_calubrate_(i64 current_frame_duration) {
#include <sched.h>
#include <unistd.h>
-i64 p_time(void) {
+i64 current_utc_time_in_milliseconds(void) {
struct timespec t;
timespec_get(&t, TIME_UTC);
- return 1000 * t.tv_sec + t.tv_nsec / 1000000;
+ return 1000ll * t.tv_sec + t.tv_nsec / 1000000ll;
}
-void p_yield(void) {
+void yield_thread_execution(void) {
sched_yield();
}
-void p_sleep_for(i64 duration) {
+void suspend_thread_for_milliseconds(i64 duration) {
if (duration == 0)
usleep(0);
if (duration <= 0)
@@ -1061,7 +1131,7 @@ void p_sleep_for(i64 duration) {
// ================================================================
//
-// UDP sockets
+// Networking
//
// ================================================================
@@ -1080,18 +1150,18 @@ typedef struct {
IP_Address address;
} Socket_Slot;
-static b8 _sockets_ready = 0;
+static b8 _network_ready = 0;
static Socket_Slot _sockets[MAX_NUM_SOCKETS] = {0};
-static void sockets_init(void) {
- if (_sockets_ready)
+static void network_init_(void) {
+ if (_network_ready)
return;
signal(SIGPIPE, SIG_IGN);
- _sockets_ready = 1;
+ _network_ready = 1;
}
-static void sockets_cleanup(void) {
+static void network_cleanup_(void) {
for (i64 i = 0; i < MAX_NUM_SOCKETS; ++i)
if (_sockets[i].ready) {
close(_sockets[i].socket);
@@ -1099,8 +1169,8 @@ static void sockets_cleanup(void) {
}
}
-static b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) {
- sockets_init();
+static b8 network_open_(u16 slot, IP_Address address, u16 *local_port) {
+ network_init_();
b8 change_address =
!_sockets[slot].ready
@@ -1175,7 +1245,7 @@ static b8 sockets_open(u16 slot, IP_Address address, u16 *local_port) {
return 1;
}
-i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
+i64 network_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
if (slot >= MAX_NUM_SOCKETS) {
LOG_ERROR("Invalid slot %d.", (i32) (u32) slot);
return 0;
@@ -1186,7 +1256,7 @@ i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP
return 0;
}
- if (!sockets_open(slot, address, local_port))
+ if (!network_open_(slot, address, local_port))
return 0;
if (size <= 0)
return 0;
@@ -1238,7 +1308,7 @@ i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP
return received;
}
-i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
+i64 network_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
if (slot >= MAX_NUM_SOCKETS) {
LOG_ERROR("Invalid slot %d.", (i32) (u32) slot);
return 0;
@@ -1252,7 +1322,7 @@ i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
IP_Address local_address = address;
local_address.port = 0;
- if (!sockets_open(slot, local_address, local_port))
+ if (!network_open_(slot, local_address, local_port))
return 0;
if (size <= 0)
return 0;
@@ -1311,10 +1381,10 @@ 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 snd_pcm_t *_sound_out = NULL;
+static b8 _sound_ready = 0;
+static snd_pcm_t *_sound_out = NULL;
-static void sound_init(void) {
+static void sound_init_(void) {
if (_sound_ready)
return;
@@ -1343,11 +1413,11 @@ static void sound_init(void) {
if (s < 0)
LOG_ERROR("snd_pcm_hw_params_set_format failed: %s", snd_strerror(s));
- s = snd_pcm_hw_params_set_rate(_sound_out, hw_params, SOUND_SAMPLE_RATE, 0);
+ s = snd_pcm_hw_params_set_rate(_sound_out, hw_params, PRIMARY_SOUND_SAMPLE_RATE, 0);
if (s < 0)
LOG_ERROR("snd_pcm_hw_params_set_rate failed: %s", snd_strerror(s));
- s = snd_pcm_hw_params_set_channels(_sound_out, hw_params, NUM_SOUND_CHANNELS);
+ s = snd_pcm_hw_params_set_channels(_sound_out, hw_params, NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_hw_params_set_channels failed: %s", snd_strerror(s));
@@ -1361,7 +1431,7 @@ static void sound_init(void) {
if (s < 0)
LOG_ERROR("snd_pcm_sw_params_current failed: %s", snd_strerror(s));
- s = snd_pcm_sw_params_set_avail_min(_sound_out, sw_params, SOUND_AVAIL_MIN);
+ s = snd_pcm_sw_params_set_avail_min(_sound_out, sw_params, PRIMARY_SOUND_AVAIL_MIN);
if (s < 0)
LOG_ERROR("snd_pcm_sw_params_set_avail_min failed: %s", snd_strerror(s));
@@ -1376,7 +1446,7 @@ static void sound_init(void) {
_sound_ready = 1;
}
-static void sound_cleanup(void) {
+static void sound_cleanup_(void) {
if (!_sound_ready)
return;
@@ -1397,34 +1467,34 @@ static void sound_cleanup(void) {
_sound_ready = 0;
}
-void p_handle_sound(void) {
- sound_init();
+void handle_primary_sound(void) {
+ sound_init_();
g_platform.num_sound_samples_elapsed = sound_samples_elapsed_();
- i64 num_frames = g_platform.num_sound_samples_elapsed * NUM_SOUND_CHANNELS;
+ i64 num_frames = g_platform.num_sound_samples_elapsed * NUM_PRIMARY_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_SOUND_FRAMES) {
+ if (num_frames > MAX_NUM_PRIMARY_SOUND_FRAMES) {
LOG_ERROR("Sound buffer overflow.");
- num_frames = MAX_NUM_SOUND_FRAMES;
+ num_frames = MAX_NUM_PRIMARY_SOUND_FRAMES;
}
i32 s;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - _sound_position) {
- s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, num_frames / NUM_SOUND_CHANNELS);
+ if (num_frames <= MAX_NUM_PRIMARY_SOUND_FRAMES - _sound_position) {
+ s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, num_frames / NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
memset(_sound_ring + _sound_position, 0, num_frames * sizeof *_sound_ring);
} else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - _sound_position;
+ i64 part_one = MAX_NUM_PRIMARY_SOUND_FRAMES - _sound_position;
i64 part_two = num_frames - part_one;
- s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / NUM_SOUND_CHANNELS);
+ s = snd_pcm_writei(_sound_out, _sound_ring + _sound_position, part_one / NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
- s = snd_pcm_writei(_sound_out, _sound_ring, part_two / NUM_SOUND_CHANNELS);
+ s = snd_pcm_writei(_sound_out, _sound_ring, part_two / NUM_PRIMARY_SOUND_CHANNELS);
if (s < 0)
LOG_ERROR("snd_pcm_writei failed: %s", snd_strerror(s));
@@ -1432,17 +1502,17 @@ void p_handle_sound(void) {
memset(_sound_ring, 0, part_two * sizeof *_sound_ring);
}
- _sound_position = (_sound_position + num_frames) % MAX_NUM_SOUND_FRAMES;
+ _sound_position = (_sound_position + num_frames) % MAX_NUM_PRIMARY_SOUND_FRAMES;
}
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
+void queue_primary_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples < 0)
LOG_ERROR("Invalid num samples %lld.", num_samples);
if (frames == NULL)
return;
if (delay_in_samples < 0) {
- frames += -delay_in_samples * NUM_SOUND_CHANNELS;
+ frames += -delay_in_samples * NUM_PRIMARY_SOUND_CHANNELS;
num_samples -= delay_in_samples;
delay_in_samples = 0;
}
@@ -1450,22 +1520,22 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples <= 0)
return;
- i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
+ i64 num_frames = num_samples * NUM_PRIMARY_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_SOUND_FRAMES) {
+ if (num_frames > MAX_NUM_PRIMARY_SOUND_FRAMES) {
LOG_ERROR("Sound buffer overflow.");
return;
}
- sound_init();
+ sound_init_();
- i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_SOUND_FRAMES;
+ i64 begin = (_sound_position + delay_in_samples) % MAX_NUM_PRIMARY_SOUND_FRAMES;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - begin)
+ if (num_frames <= MAX_NUM_PRIMARY_SOUND_FRAMES - begin)
for (i64 i = 0; i < num_frames; ++i)
_sound_ring[begin + i] += frames[i];
else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - begin;
+ i64 part_one = MAX_NUM_PRIMARY_SOUND_FRAMES - begin;
i64 part_two = num_frames - part_one;
for (i64 i = 0; i < part_one; ++i)
@@ -2087,7 +2157,7 @@ i32 x11_error_handler_(Display *display, XErrorEvent *event) {
return 0;
}
-void p_init(void) {
+void init_main_window(void) {
for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i)
_frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2;
@@ -2241,6 +2311,11 @@ void p_init(void) {
_window = XCreateWindow(_display, _root_window, x, y, g_platform.frame_width, g_platform.frame_height, 0, depth, InputOutput, visual, CWEventMask, &(XSetWindowAttributes) { .event_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | EnterWindowMask | LeaveWindowMask | PointerMotionMask | VisibilityChangeMask | FocusChangeMask | StructureNotifyMask | SubstructureNotifyMask, });
+ if (_window == 0) {
+ LOG_ERROR("XCreateWindow failed.");
+ return;
+ }
+
_im = XOpenIM(_display, NULL, NULL, NULL);
if (_im == NULL) {
@@ -2309,8 +2384,10 @@ void p_init(void) {
_mapped = 0;
}
-void p_cleanup(void) {
- if (!g_platform.graceful_exit)
+void shutdown_all_systems(void) {
+ g_platform.done = 1;
+
+ if (!g_platform.graceful_shutdown)
return;
if (_window != 0)
@@ -2318,17 +2395,18 @@ void p_cleanup(void) {
if (_display != NULL)
XCloseDisplay (_display);
+ _window = 0;
_display = NULL;
- sockets_cleanup();
- sound_cleanup();
+ network_cleanup_();
+ sound_cleanup_();
}
-i32 p_handle_events(void) {
+i32 handle_main_window_events(void) {
if (_display == NULL)
return 0;
- _frame_time = p_time();
+ _frame_time = current_utc_time_in_milliseconds();
i32 num_events = 0;
@@ -2848,11 +2926,11 @@ i32 p_handle_events(void) {
return num_events;
}
-i32 p_wait_events(void) {
+i32 wait_main_window_events(void) {
i32 num_events = 0;
for (;;) {
- num_events = p_handle_events();
+ num_events = handle_main_window_events();
if (num_events != 0)
break;
usleep(0);
@@ -2861,7 +2939,7 @@ i32 p_wait_events(void) {
return num_events;
}
-void p_render_frame(void) {
+void render_main_window_frame(void) {
if (g_platform.done)
return;
@@ -2891,10 +2969,10 @@ void p_render_frame(void) {
XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, _image.width, _image.height);
XFlush(_display);
- pixel_size_calubrate_(p_time() - _frame_time);
+ pixel_size_calubrate_(current_utc_time_in_milliseconds() - _frame_time);
}
-void p_clipboard_write_text(i64 size, c8 *data) {
+void write_clipboard_text(i64 size, c8 *data) {
if (size > MAX_CLIPBOARD_SIZE) {
LOG_ERROR("Size is too big %lld.", size);
return;
@@ -2951,7 +3029,7 @@ b8 x11_screenshot_(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels
// ================================================================
#if defined(__linux__) && (!NO_X11 || !NO_WAYLAND)
-void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
+void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
if (width == NULL || height == NULL) {
LOG_ERROR("Invalid arguments.");
return;
@@ -3090,11 +3168,11 @@ __attribute__((export_name("js_key_map"))) void *js_key_map(void) {
}
__attribute__((export_name("js_sound_sample_rate"))) f64 js_sound_sample_rate(void) {
- return (f64) SOUND_SAMPLE_RATE;
+ return (f64) PRIMARY_SOUND_SAMPLE_RATE;
}
__attribute__((export_name("js_num_sound_channels"))) i32 js_num_sound_channels(void) {
- return NUM_SOUND_CHANNELS;
+ return NUM_PRIMARY_SOUND_CHANNELS;
}
#endif // defined(__wasm__)
@@ -3125,26 +3203,30 @@ static c8 _href [4096] = {0};
static u32 _pixels_scaled [MAX_NUM_PIXELS] = {0};
static u32 _pixels_internal [MAX_NUM_PIXELS] = {0};
static b8 _key_pressed [MAX_NUM_KEYS] = {0};
-static f32 _sound_buffer [MAX_NUM_SOUND_FRAMES] = {0};
+static f32 _sound_buffer [MAX_NUM_PRIMARY_SOUND_FRAMES] = {0};
static u8 _drop_buffer [DROP_FILES_BUFFER_SIZE] = {0};
-i64 p_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
+void shutdown_all_systems(void) {
+ g_platform.done = 1;
+}
+
+i64 network_recv(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port, IP_Address *remote_address) {
LOG_ERROR("Web sockets are not implemented.");
return 0;
}
-i64 p_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
+i64 network_send(u16 slot, IP_Address address, i64 size, u8 *data, u16 *local_port) {
LOG_ERROR("Web sockets are not implemented.");
return 0;
}
-i64 p_time(void);
+i64 current_utc_time_in_milliseconds(void);
-void p_sleep_for(i64 duration) {
+void suspend_thread_for_milliseconds(i64 duration) {
if (duration <= 0)
return;
- i64 t = p_time();
+ i64 t = current_utc_time_in_milliseconds();
if (_timeout < t)
_timeout = t + duration;
@@ -3152,7 +3234,7 @@ void p_sleep_for(i64 duration) {
_timeout += duration;
}
-void p_init(void) {
+void init_main_window(void) {
(void) rgb_f32_from_u32_;
++_num_events;
@@ -3162,10 +3244,10 @@ void p_init(void) {
for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i)
_frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2;
- _sound_read = (MAX_NUM_SOUND_FRAMES + ((-SOUND_AVAIL_MIN) % MAX_NUM_SOUND_FRAMES)) % MAX_NUM_SOUND_FRAMES;
+ _sound_read = (MAX_NUM_PRIMARY_SOUND_FRAMES + ((-PRIMARY_SOUND_AVAIL_MIN) % MAX_NUM_PRIMARY_SOUND_FRAMES)) % MAX_NUM_PRIMARY_SOUND_FRAMES;
}
-i32 p_handle_events(void) {
+i32 handle_main_window_events(void) {
if (g_platform.files_dropped)
drop_files_clean_();
@@ -3198,13 +3280,13 @@ i32 p_handle_events(void) {
return n;
}
-i32 p_wait_events(void) {
+i32 wait_main_window_events(void) {
_wait_events = 1;
- return p_handle_events();
+ return handle_main_window_events();
}
-void p_render_frame(void) {
+void render_main_window_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)
@@ -3224,9 +3306,9 @@ void p_render_frame(void) {
}
}
-void p_clipboard_write_text_impl(i32 size, c8 *data);
+void write_clipboard_text_impl(i32 size, c8 *data);
-void p_clipboard_write_text(i64 size, c8 *data) {
+void write_clipboard_text(i64 size, c8 *data) {
if (size < 0 || data == NULL)
return;
if (size > MAX_CLIPBOARD_SIZE)
@@ -3236,10 +3318,10 @@ void p_clipboard_write_text(i64 size, c8 *data) {
for (i64 i = 0; i < size; ++i)
g_platform.clipboard[i] = data[i];
- p_clipboard_write_text_impl((i32) size, data);
+ write_clipboard_text_impl((i32) size, data);
}
-void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
+void take_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels) {
if (width == NULL || height == NULL) {
LOG_ERROR("Invalid arguments.");
return;
@@ -3249,17 +3331,17 @@ void p_screenshot(i64 max_num_pixels, i64 *width, i64 *height, vec4_f32 *pixels)
*height = 0;
}
-void p_handle_sound(void) {
+void handle_primary_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;
+ _sound_position = (_sound_position + g_platform.num_sound_samples_elapsed * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES;
}
-void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
+void queue_primary_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (frames == NULL)
return;
if (delay_in_samples < 0) {
- frames += -delay_in_samples * NUM_SOUND_CHANNELS;
+ frames += -delay_in_samples * NUM_PRIMARY_SOUND_CHANNELS;
num_samples -= delay_in_samples;
delay_in_samples = 0;
}
@@ -3267,19 +3349,19 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
if (num_samples <= 0)
return;
- i64 num_frames = num_samples * NUM_SOUND_CHANNELS;
- if (num_frames > MAX_NUM_SOUND_FRAMES) {
+ i64 num_frames = num_samples * NUM_PRIMARY_SOUND_CHANNELS;
+ if (num_frames > MAX_NUM_PRIMARY_SOUND_FRAMES) {
LOG_ERROR("Sound buffer overflow.");
return;
}
- i64 begin = (_sound_position + delay_in_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ i64 begin = (_sound_position + delay_in_samples * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES;
- if (num_frames <= MAX_NUM_SOUND_FRAMES - begin)
+ if (num_frames <= MAX_NUM_PRIMARY_SOUND_FRAMES - begin)
for (i64 i = 0; i < num_frames; ++i)
_sound_ring[begin + i] += frames[i];
else {
- i64 part_one = MAX_NUM_SOUND_FRAMES - begin;
+ i64 part_one = MAX_NUM_PRIMARY_SOUND_FRAMES - begin;
i64 part_two = num_frames - part_one;
for (i64 i = 0; i < part_one; ++i)
@@ -3290,7 +3372,7 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) {
}
__attribute__((export_name("js_max_num_sound_frames"))) i32 js_max_num_sound_frames(void) {
- return MAX_NUM_SOUND_FRAMES;
+ return MAX_NUM_PRIMARY_SOUND_FRAMES;
}
__attribute__((export_name("js_sound_buffer"))) void *js_sound_buffer(void) {
@@ -3318,7 +3400,7 @@ __attribute__((export_name("js_pixels"))) void *js_pixels(void) {
}
__attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 frame_height, i32 num_samples) {
- i64 frame_time = p_time();
+ i64 frame_time = current_utc_time_in_milliseconds();
if (frame_width > 0 && frame_height > 0 && frame_width * frame_height <= MAX_NUM_PIXELS) {
_frame_width = frame_width;
@@ -3337,17 +3419,17 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
}
// Convert interleaved frames to non-interleaved.
- for (i64 j = 0; j < NUM_SOUND_CHANNELS; ++j)
+ for (i64 j = 0; j < NUM_PRIMARY_SOUND_CHANNELS; ++j)
for (i64 i = 0; i < num_samples; ++i) {
- i64 n = (_sound_read + i * NUM_SOUND_CHANNELS + j) % MAX_NUM_SOUND_FRAMES;
+ i64 n = (_sound_read + i * NUM_PRIMARY_SOUND_CHANNELS + j) % MAX_NUM_PRIMARY_SOUND_FRAMES;
_sound_buffer[j * num_samples + i] = _sound_ring[n];
_sound_ring[n] = 0.f;
}
- _sound_read = (_sound_read + num_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
+ _sound_read = (_sound_read + num_samples * NUM_PRIMARY_SOUND_CHANNELS) % MAX_NUM_PRIMARY_SOUND_FRAMES;
if (do_render)
- pixel_size_calubrate_(p_time() - frame_time);
+ pixel_size_calubrate_(current_utc_time_in_milliseconds() - frame_time);
}
__attribute__((export_name("js_mousemove"))) void js_mousemove(i32 x, i32 y) {