summaryrefslogtreecommitdiff
path: root/reduced_system_layer.c
diff options
context:
space:
mode:
authorMitya Selivanov <automainint@guattari.tech>2025-01-17 01:43:36 +0100
committerMitya Selivanov <automainint@guattari.tech>2025-01-17 01:43:36 +0100
commitf5ed02329aed6d455257e0932a194161d88efdd6 (patch)
treeeda08fac35bbf0ceba4138d92d10efd01ab4d954 /reduced_system_layer.c
parente8972a0c2f344e109a9763a396f3ef54a646dfaa (diff)
downloadreduced_system_layer-f5ed02329aed6d455257e0932a194161d88efdd6.zip
Web framerate calibration; Julia Set example update
Diffstat (limited to 'reduced_system_layer.c')
-rw-r--r--reduced_system_layer.c84
1 files changed, 56 insertions, 28 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c
index 4043f58..219d360 100644
--- a/reduced_system_layer.c
+++ b/reduced_system_layer.c
@@ -196,27 +196,35 @@ i32 main(i32 argc, c8 **argv);
#endif
#ifndef MIN_PIXEL_SIZE
-#define MIN_PIXEL_SIZE 1
+#define MIN_PIXEL_SIZE (1.0)
#endif
#ifndef MAX_PIXEL_SIZE
-#define MAX_PIXEL_SIZE 16
+#define MAX_PIXEL_SIZE (16.0)
+#endif
+
+#ifndef PIXEL_SIZE_DELTA
+#define PIXEL_SIZE_DELTA (0.1)
#endif
#ifndef DEFAULT_PIXEL_SIZE
-#define DEFAULT_PIXEL_SIZE 3
+#define DEFAULT_PIXEL_SIZE (3.0)
#endif
#ifndef MIN_FRAME_DURATION
-#define MIN_FRAME_DURATION 9
+#define MIN_FRAME_DURATION 8
#endif
#ifndef MAX_FRAME_DURATION
-#if defined(__wasm__)
-#define MAX_FRAME_DURATION 83
-#else
-#define MAX_FRAME_DURATION 41
+#define MAX_FRAME_DURATION 34
#endif
+
+#ifndef NUM_FRAMES_AVERAGED
+#define NUM_FRAMES_AVERAGED 400
+#endif
+
+#ifndef AVERAGE_FRAME_BIAS
+#define AVERAGE_FRAME_BIAS (0.00)
#endif
#ifndef NUM_SOUND_CHANNELS
@@ -519,7 +527,7 @@ typedef struct {
c8 *title;
i32 frame_width;
i32 frame_height;
- i32 pixel_size;
+ f64 pixel_size;
b8 exact_resolution;
b8 graceful_exit;
@@ -610,9 +618,11 @@ 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 f32 _sound_ring [MAX_NUM_SOUND_FRAMES] = {0};
static u8 _drop_files_buffer [DROP_FILES_BUFFER_SIZE] = {0};
+static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0};
void p_event_loop(void) {
p_init();
@@ -719,7 +729,7 @@ i8 utf8_write(c32 c, c8 *buffer) {
return 0;
}
-u32 rgb_u32_from_f32_(vec3_f32 c) {
+static 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);
@@ -731,6 +741,22 @@ u32 rgb_u32_from_f32_(vec3_f32 c) {
return (r << 16) | (g << 8) | b;
}
+static i64 average_frame_duration_(i64 duration) {
+ _frame_duration[_frame_index] = duration;
+ _frame_index = (_frame_index + 1) % NUM_FRAMES_AVERAGED;
+
+ i64 durs[NUM_FRAMES_AVERAGED + 1];
+ for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i)
+ durs[i] = _frame_duration[i];
+
+ // FIXME: Use better sorting algorithm.
+ for (i64 i = 0; i < (i64) NUM_FRAMES_AVERAGED; ++i)
+ for (i64 j = i + 1; j < NUM_FRAMES_AVERAGED; ++j)
+ if (durs[i] < durs[j]) { i64 t = durs[i]; durs[i] = durs[j]; durs[j] = t; }
+
+ return durs[(i64) ((NUM_FRAMES_AVERAGED - 1) * AVERAGE_FRAME_BIAS)];
+}
+
static i64 sound_samples_elapsed_(void) {
if (_sound_clock_time == 0) {
_sound_clock_time = p_time();
@@ -1396,6 +1422,9 @@ static b8 sub_str_eq_(c8 *a, c8 *b, i64 len) {
}
void p_init(void) {
+ for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i)
+ _frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2;
+
_display = XOpenDisplay(NULL);
if (_display == NULL) {
@@ -2078,13 +2107,11 @@ i32 p_handle_events(void) {
i32 width = _image.width;
i32 height = _image.height;
- if (g_platform.pixel_size <= 0)
- g_platform.pixel_size = DEFAULT_PIXEL_SIZE;
-
- if (g_platform.pixel_size <= MIN_PIXEL_SIZE)
- g_platform.pixel_size = MIN_PIXEL_SIZE;
+ if (g_platform.pixel_size <= 0.) g_platform.pixel_size = DEFAULT_PIXEL_SIZE;
+ if (g_platform.pixel_size < MIN_PIXEL_SIZE) g_platform.pixel_size = MIN_PIXEL_SIZE;
+ if (g_platform.pixel_size > MAX_PIXEL_SIZE) g_platform.pixel_size = MAX_PIXEL_SIZE;
- if (g_platform.pixel_size > 1) {
+ if (g_platform.pixel_size > 1.) {
width = (i32) floor(((f64) _image.width) / g_platform.pixel_size + .5);
height = (i32) floor(((f64) _image.height) / g_platform.pixel_size + .5);
}
@@ -2143,12 +2170,12 @@ void p_render_frame(void) {
XFlush(_display);
if (!g_platform.exact_resolution) {
- i64 frame_duration = p_time() - _frame_time;
+ i64 frame_duration = average_frame_duration_(p_time() - _frame_time);
if (g_platform.pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION)
- ++g_platform.pixel_size;
+ g_platform.pixel_size += PIXEL_SIZE_DELTA * (frame_duration - MAX_FRAME_DURATION);
else if (g_platform.pixel_size > MIN_PIXEL_SIZE && frame_duration < MIN_FRAME_DURATION)
- --g_platform.pixel_size;
+ g_platform.pixel_size -= PIXEL_SIZE_DELTA * (MIN_FRAME_DURATION - frame_duration);
}
}
@@ -2227,6 +2254,9 @@ void p_init(void) {
g_platform.done = 1;
+ 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;
}
@@ -2491,13 +2521,11 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
i32 width = _frame_width;
i32 height = _frame_height;
- if (g_platform.pixel_size <= 0)
- g_platform.pixel_size = DEFAULT_PIXEL_SIZE;
-
- if (g_platform.pixel_size <= MIN_PIXEL_SIZE)
- g_platform.pixel_size = MIN_PIXEL_SIZE;
+ if (g_platform.pixel_size <= 0.) g_platform.pixel_size = DEFAULT_PIXEL_SIZE;
+ if (g_platform.pixel_size < MIN_PIXEL_SIZE) g_platform.pixel_size = MIN_PIXEL_SIZE;
+ if (g_platform.pixel_size > MAX_PIXEL_SIZE) g_platform.pixel_size = MAX_PIXEL_SIZE;
- if (g_platform.pixel_size > 1) {
+ if (g_platform.pixel_size > 1.) {
width = (i32) floor(((f64) _frame_width) / g_platform.pixel_size + .5);
height = (i32) floor(((f64) _frame_height) / g_platform.pixel_size + .5);
}
@@ -2534,12 +2562,12 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram
_sound_read = (_sound_read + num_samples * NUM_SOUND_CHANNELS) % MAX_NUM_SOUND_FRAMES;
if (!g_platform.exact_resolution && do_render) {
- i64 frame_duration = p_time() - frame_time;
+ i64 frame_duration = average_frame_duration_(p_time() - frame_time);
if (g_platform.pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION)
- ++g_platform.pixel_size;
+ g_platform.pixel_size += PIXEL_SIZE_DELTA * (frame_duration - MAX_FRAME_DURATION);
else if (g_platform.pixel_size > MIN_PIXEL_SIZE && frame_duration < MIN_FRAME_DURATION)
- --g_platform.pixel_size;
+ g_platform.pixel_size -= PIXEL_SIZE_DELTA * (MIN_FRAME_DURATION - frame_duration);
}
}