diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2025-01-12 23:25:53 +0100 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2025-01-12 23:25:53 +0100 |
commit | a3cf8790cb4547288c9d395609738c4a1eb838a2 (patch) | |
tree | dd2a3785479d9ba6e77f14bb89a22d784582642c /reduced_system_layer.c | |
parent | 29d736aecc5db0deb67053931e5b1cf03a9defc3 (diff) | |
download | reduced_system_layer-a3cf8790cb4547288c9d395609738c4a1eb838a2.zip |
Dynamic resolution
Diffstat (limited to 'reduced_system_layer.c')
-rwxr-xr-x | reduced_system_layer.c | 156 |
1 files changed, 125 insertions, 31 deletions
diff --git a/reduced_system_layer.c b/reduced_system_layer.c index af49453..9eabca9 100755 --- a/reduced_system_layer.c +++ b/reduced_system_layer.c @@ -44,6 +44,7 @@ #/ - Networking #/ - Windows sockets #/ - Graphics +#/ - Relative coordinates #/ - Self-contained impl #/ - UI #/ - Icons @@ -73,6 +74,7 @@ #/ - Testing #/ - Graphics #/ - Font +#/ - Adaptive resolution #/ #/ ---------------------------------------------------------------- #/ @@ -169,11 +171,15 @@ extern "C" { #endif enum { - MAX_NUM_PIXELS = 10 * 1024 * 1024, - MAX_INPUT_SIZE = 256, - MAX_CLIPBOARD_SIZE = 10 * 1024 * 1024, - MAX_NUM_SOCKETS = 64, - MAX_NUM_KEYS = 512, + MAX_NUM_PIXELS = 10 * 1024 * 1024, + MAX_INPUT_SIZE = 256, + MAX_CLIPBOARD_SIZE = 10 * 1024 * 1024, + MAX_NUM_SOCKETS = 64, + MAX_NUM_KEYS = 512, + MAX_PIXEL_SIZE = 16, + + MIN_FRAME_DURATION = 9, + MAX_FRAME_DURATION = 38, AUDIO_NUM_CHANNELS = 2, AUDIO_SAMPLE_RATE = 44100, @@ -331,6 +337,7 @@ typedef struct { i64 clipboard_size; c8 * clipboard; b8 done; + b8 exact_resolution; // TODO b8 graceful_exit; b8 has_focus; b8 has_cursor; @@ -488,8 +495,6 @@ i32 main(i32 argc, c8 **argv) { Platform g_platform = {0}; void p_event_loop(void) { - (void) sqrt; // For the compiler. - p_init(); #if !defined(__wasm__) while (!g_platform.done) update_and_render_frame(); @@ -1064,7 +1069,10 @@ void p_queue_sound(i64 delay_in_samples, i64 num_samples, f32 *frames) { static i16 _key_table[MAX_NUM_KEYS] = {0}; static b8 _key_repeat[MAX_NUM_KEYS] = {0}; +static i64 _frame_time = 0; static vec3_f32 _pixels[MAX_NUM_PIXELS] = {0}; +static i32 _pixel_size = 0; +static u32 _pixels_scaled[MAX_NUM_PIXELS] = {0}; static u32 _pixels_internal[MAX_NUM_PIXELS] = {0}; static Input_Key _input[MAX_INPUT_SIZE] = {0}; static c8 _clipboard_buffer[MAX_CLIPBOARD_SIZE] = {0}; @@ -1246,7 +1254,7 @@ void p_init(void) { .bitmap_bit_order = LSBFirst, .bitmap_pad = 32, .bits_per_pixel = 32, - .bytes_per_line = 4 * g_platform.frame_width, + .bytes_per_line = _image.width * 4, .red_mask = 0xff0000, .green_mask = 0x00ff00, .blue_mask = 0x0000ff, @@ -1267,7 +1275,7 @@ void p_init(void) { XMapWindow(_display, _window); - XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, g_platform.frame_width, g_platform.frame_height); + XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, _image.width, _image.height); XFlush(_display); } @@ -1291,6 +1299,8 @@ i32 p_handle_events(void) { if (_display == NULL) return 0; + _frame_time = p_time(); + i32 num_events = 0; memset(g_platform.key_pressed, 0, sizeof g_platform.key_pressed); @@ -1550,15 +1560,26 @@ i32 p_handle_events(void) { XWindowAttributes attrs; XGetWindowAttributes(_display, _window, &attrs); - if ((g_platform.frame_width != attrs.width || g_platform.frame_height != attrs.height) && attrs.width * attrs.height * 4 <= (i32) sizeof _pixels_internal) { - if (attrs.width > 0 && attrs.height > 0) { - _image.width = attrs.width; - _image.height = attrs.height; - _image.bytes_per_line = 4 * attrs.width; + if (attrs.width > 0 && attrs.height > 0 && attrs.width * attrs.height <= MAX_NUM_PIXELS) { + _image.width = attrs.width; + _image.height = attrs.height; + _image.bytes_per_line = _image.width * 4; + + i32 width = _image.width; + i32 height = _image.height; + + if (_pixel_size <= 1) + _pixel_size = 1; + else { + width = (i32) floor(((f64) _image.width) / _pixel_size + .5); + height = (i32) floor(((f64) _image.height) / _pixel_size + .5); } - g_platform.frame_width = attrs.width; - g_platform.frame_height = attrs.height; + if (g_platform.frame_width != width || g_platform.frame_height != height) { + ++num_events; + g_platform.frame_width = width; + g_platform.frame_height = height; + } } return num_events; @@ -1567,10 +1588,12 @@ i32 p_handle_events(void) { i32 p_wait_events(void) { i32 num_events = 0; - do { + for (;;) { num_events = p_handle_events(); + if (num_events != 0) + break; usleep(0); - } while (num_events == 0); + } return num_events; } @@ -1579,12 +1602,35 @@ void p_render_frame(void) { if (g_platform.done) return; - i64 size = g_platform.frame_width * g_platform.frame_height; - for (i64 i = 0; i < size; ++i) - _pixels_internal[i] = rgb_u32_from_f32(_pixels[i]); + 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(_pixels[i]); + } 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(_pixels[i]); + + for (i64 j = 0; j < _image.height; ++j) { + i64 j0 = (j * g_platform.frame_height) / _image.height; + for (i64 i = 0; i < _image.width; ++i) { + i64 i0 = (i * g_platform.frame_width) / _image.width; + _pixels_internal[j * _image.width + i] = _pixels_scaled[j0 * g_platform.frame_width + i0]; + } + } + } - XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, g_platform.frame_width, g_platform.frame_height); + XPutImage(_display, _window, _gc, &_image, 0, 0, 0, 0, _image.width, _image.height); XFlush(_display); + + if (!g_platform.exact_resolution) { + i64 frame_duration = p_time() - _frame_time; + + if (_pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION) + ++_pixel_size; + else if (_pixel_size > 1 && frame_duration < MIN_FRAME_DURATION) + --_pixel_size; + } } void p_clipboard_write(i64 size, c8 *data) { @@ -1610,7 +1656,11 @@ void p_clipboard_write(i64 size, c8 *data) { #ifdef __wasm__ +static i32 _frame_width = 0; +static i32 _frame_height = 0; static vec3_f32 _pixels[MAX_NUM_PIXELS] = {0}; +static i32 _pixel_size = 0; +static u32 _pixels_scaled[MAX_NUM_PIXELS] = {0}; static u32 _pixels_internal[MAX_NUM_PIXELS] = {0}; static Input_Key _input[MAX_INPUT_SIZE] = {0}; static c8 _clipboard_buffer[MAX_CLIPBOARD_SIZE] = {0}; @@ -1645,11 +1695,13 @@ void p_init(void) { i32 p_handle_events(void) { g_platform.input_size = _input_size; - _input_size = 0; + _input_size = 0; + for (i64 i = 0; i < MAX_NUM_KEYS; ++i) g_platform.key_pressed[i] = _key_pressed[i]; for (i64 i = 0; i < MAX_NUM_KEYS; ++i) _key_pressed[i] = 0; + i32 n = _num_events; _num_events = 0; return n; @@ -1662,9 +1714,23 @@ i32 p_wait_events(void) { } void p_render_frame(void) { - 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(_pixels[i]); + 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(_pixels[i]); + } 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(_pixels[i]); + + for (i64 j = 0; j < _frame_height; ++j) { + i64 j0 = (j * g_platform.frame_height) / _frame_height; + for (i64 i = 0; i < _frame_width; ++i) { + i64 i0 = (i * g_platform.frame_width) / _frame_width; + _pixels_internal[j * _frame_width + i] = 0xff000000u | _pixels_scaled[j0 * g_platform.frame_width + i0]; + } + } + } } void p_clipboard_write_impl(i32 size, c8 *data); @@ -1735,15 +1801,34 @@ __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) { - if (g_platform.frame_width != frame_width || g_platform.frame_height != frame_height) { - ++_num_events; - g_platform.frame_width = frame_width; - g_platform.frame_height = frame_height; + i64 frame_time = p_time(); + + if (frame_width > 0 && frame_height > 0 && frame_width * frame_height <= MAX_NUM_PIXELS) { + _frame_width = frame_width; + _frame_height = frame_height; + + i32 width = _frame_width; + i32 height = _frame_height; + + if (_pixel_size <= 1) + _pixel_size = 1; + else { + width = (i32) floor(((f64) _frame_width) / _pixel_size + .5); + height = (i32) floor(((f64) _frame_height) / _pixel_size + .5); + } + + if (g_platform.frame_width != width || g_platform.frame_height != height) { + ++_num_events; + g_platform.frame_width = width; + g_platform.frame_height = height; + } } g_platform.done = 0; - if (_num_events > 0 || !_wait_events) { + b8 do_render = _num_events > 0 || !_wait_events; + + if (do_render) { _wait_events = 0; update_and_render_frame(); } @@ -1757,6 +1842,15 @@ __attribute__((export_name("js_frame"))) void js_frame(i32 frame_width, i32 fram } _sound_read = (_sound_read + num_samples * AUDIO_NUM_CHANNELS) % MAX_NUM_AUDIO_FRAMES; + + if (!g_platform.exact_resolution && do_render) { + i64 frame_duration = p_time() - frame_time; + + if (_pixel_size < MAX_PIXEL_SIZE && frame_duration > MAX_FRAME_DURATION) + ++_pixel_size; + else if (_pixel_size > 1 && frame_duration < MIN_FRAME_DURATION) + --_pixel_size; + } } __attribute__((export_name("js_mousemove"))) void js_mousemove(i32 x, i32 y) { |