diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2025-02-11 11:06:28 +0100 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2025-02-11 11:06:28 +0100 |
commit | 2d71f1099f0eb3ef6e17316a520d3d710dec1ac0 (patch) | |
tree | 32d2db34046c1496f20650e1d3857aa5d3f9c2d7 | |
parent | ed275e1296defb6cc5450cf5996cf97c1fa32dfa (diff) | |
download | reduced_system_layer-2d71f1099f0eb3ef6e17316a520d3d710dec1ac0.zip |
Memory buffer fixes
-rw-r--r-- | examples/screenshot.c | 31 | ||||
-rwxr-xr-x | graphics.c | 42 | ||||
-rwxr-xr-x | reduced_system_layer.c | 218 |
3 files changed, 123 insertions, 168 deletions
diff --git a/examples/screenshot.c b/examples/screenshot.c index c3c0ebd..11b2385 100644 --- a/examples/screenshot.c +++ b/examples/screenshot.c @@ -1,23 +1,34 @@ #include "../graphics.c" -i64 width = 0; -i64 height = 0; -b8 has_screenshot = 0; +enum { + MAX_NUM_PIXELS = 10 * 1024 * 1024, +}; + +b8 has_screenshot = 0; +i64 width = 0; +i64 height = 0; +vec4_f32 pixels[MAX_NUM_PIXELS] = {0}; void update_and_render_frame(void) { if (!has_screenshot) { - take_screenshot(MAX_NUM_PIXELS, &width, &height, g_platform.sketch); + take_screenshot(MAX_NUM_PIXELS, &width, &height, pixels); has_screenshot = 1; } handle_main_window_events(); - draw_pixels((Brush) { .quick = 1, }, 0, 0, g_platform.real_width, g_platform.real_height, (Pixel_Buffer) { - .width = width, - .height = height, - .stride = width, - .pixels = g_platform.sketch, - }); + draw_pixels_quick( + (Box) { + .width = g_platform.real_width, + .height = g_platform.real_height, + }, + (Pixel_Buffer) { + .width = width, + .height = height, + .stride = width, + .pixels = pixels, + } + ); render_main_window_frame(); } @@ -248,6 +248,10 @@ enum { CHAR_NUM_BITS_ = CHAR_NUM_BITS_X_ * CHAR_NUM_BITS_Y_, }; +static i64 min2_i64_(i64 x, i64 y) { + return x < y ? x : y; +} + static f32 max2_f32_(f32 a, f32 b) { return a < b ? b : a; } @@ -344,11 +348,25 @@ void draw_pixels_to_buffer(Pixel_Buffer dst, Box area, Pixel_Buffer src) { for (i64 j = j0; j < j1; ++j) { i64 src_j = (i64) floor(((j - area.y + .5) * src.height) * h_inv); if (src_j < 0 || src_j >= src.height) continue; - i64 src_n = src_j * src.stride; + vec4_f32 *q = src.pixels + src_j * src.stride; + vec4_f32 *p = dst.pixels + j * dst.stride + i0; for (i64 i = i0; i < i1; ++i) { i64 src_i = (i64) floor(((i - area.x + .5) * src.width) * w_inv); if (src_i < 0 || src_i >= src.width) continue; - put_pixel_(dst, src.pixels[src_n + src_i], i, j); + vec4_f32 color = q[src_i]; + if (color.w == 1.f) + *p = color; + else { + vec4_f32 dst_color = *p; + f32 dst_amount = 1. - color.w; + *p = (vec4_f32) { + .x = dst_color.x * dst_amount + color.x * color.w, + .y = dst_color.y * dst_amount + color.y * color.w, + .z = dst_color.z * dst_amount + color.z * color.w, + .w = max2_f32_(dst_color.w, color.w), + }; + } + ++p; } } } @@ -1948,8 +1966,10 @@ static void scale_and_perform_graphics_request_(Graphics_Context context, Graphi static Graphics_Context graphics_context_defaults_(Graphics_Context context) { if (context.dst.pixels == NULL) { + i64 max_height = g_platform.num_pixels / g_platform.frame_width; + context.dst.width = g_platform.frame_width; - context.dst.height = g_platform.frame_height; + context.dst.height = min2_i64_(max_height, g_platform.frame_height); context.dst.stride = g_platform.frame_width; context.dst.pixels = g_platform.pixels; @@ -2076,19 +2096,19 @@ TEST("colors") { REQUIRE_EQ((purple.z + 2e-7) * 100, 100); } -Pixel_Buffer pixels = { +static Pixel_Buffer _test_pixels = { .width = 1280, .height = 720, .stride = 1280, .pixels = (vec4_f32[1280 * 720]) {0}, }; -vec4_f32 color = { 1., 1., 1., 1., }; +static vec4_f32 _test_color = { 1., 1., 1., 1., }; BENCHMARK("fill rectangle") { BENCHMARK_BEGIN; { - fill_rectangle_to_buffer(pixels, color, (Box) { .x = 100, .y = 100, .width = 300, .height = 200, }); + fill_rectangle_to_buffer(_test_pixels, _test_color, (Box) { .x = 100, .y = 100, .width = 300, .height = 200, }); } BENCHMARK_END; } @@ -2096,7 +2116,7 @@ BENCHMARK("fill rectangle") { BENCHMARK("fill triangle") { BENCHMARK_BEGIN; { - fill_triangle_to_buffer(pixels, color, (vec2[3]) { + fill_triangle_to_buffer(_test_pixels, _test_color, (vec2[3]) { { 100, 100 }, { 300, 100 }, { 200, 250 }, @@ -2108,7 +2128,7 @@ BENCHMARK("fill triangle") { BENCHMARK("fill quad") { BENCHMARK_BEGIN; { - fill_quad_to_buffer(pixels, color, (vec2[4]) { + fill_quad_to_buffer(_test_pixels, _test_color, (vec2[4]) { { 100, 100 }, { 300, 100 }, { 300, 200 }, @@ -2121,7 +2141,7 @@ BENCHMARK("fill quad") { BENCHMARK("fill ellipse") { BENCHMARK_BEGIN; { - fill_ellipse_to_buffer(pixels, color, (Box) { .x = 80, .y = 80, .width = 340, .height = 240, }); + fill_ellipse_to_buffer(_test_pixels, _test_color, (Box) { .x = 80, .y = 80, .width = 340, .height = 240, }); } BENCHMARK_END; } @@ -2129,7 +2149,7 @@ BENCHMARK("fill ellipse") { BENCHMARK("fill line") { BENCHMARK_BEGIN; { - fill_line_to_buffer(pixels, color, (vec2[2]) { + fill_line_to_buffer(_test_pixels, _test_color, (vec2[2]) { { 100, 100 }, { 300, 200 }, }, 40); @@ -2141,7 +2161,7 @@ BENCHMARK("draw text area") { BENCHMARK_BEGIN; { c32 text[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'S', 'a', 'i', 'l', 'o', 'r', '!', }; - draw_text_area_to_buffer(pixels, color, (Box) { .x = 100, .y = 100, .width = 300, .height = 200, }, (vec2) { 100, 200 }, sizeof text / sizeof *text, text); + draw_text_area_to_buffer(_test_pixels, _test_color, (Box) { .x = 100, .y = 100, .width = 300, .height = 200, }, (vec2) { 100, 200 }, sizeof text / sizeof *text, text); } BENCHMARK_END; } diff --git a/reduced_system_layer.c b/reduced_system_layer.c index ad5e990..3d6a08d 100755 --- a/reduced_system_layer.c +++ b/reduced_system_layer.c @@ -111,6 +111,9 @@ #/ - macOS support #/ - Mobile devices support #/ +#/ Bugs +#/ - Buffer overflow after resizing the window. +#/ #/ Done #/ #/ - Examples @@ -249,7 +252,7 @@ i32 main(i32 argc, c8 **argv); #endif #ifndef STATIC_MEMORY_BUFFER_SIZE -#define STATIC_MEMORY_BUFFER_SIZE (10 * 1024 * 1024) +#define STATIC_MEMORY_BUFFER_SIZE (20 * 1024 * 1024) #endif #ifndef MEMORY_CHUNK_SIZE @@ -288,11 +291,11 @@ i32 main(i32 argc, c8 **argv); #endif #ifndef NUM_FRAMES_AVERAGED -#define NUM_FRAMES_AVERAGED 400 +#define NUM_FRAMES_AVERAGED 600 #endif #ifndef AVERAGE_FRAME_BIAS -#define AVERAGE_FRAME_BIAS (0.02) +#define AVERAGE_FRAME_BIAS (0.03) #endif #ifndef MAX_NUM_KEYS @@ -616,8 +619,8 @@ typedef struct { i64 num_sound_samples_elapsed; i64 num_pixels; - i64 sketch_len; i64 input_len; + i64 input_capacity; i64 num_drop_files; i64 clipboard_text_len; i64 clipboard_image_width; @@ -626,11 +629,7 @@ typedef struct { i64 num_clipboard_sound_samples; i64 clipboard_sound_len; - i64 pixels_capacity; - i64 input_capacity; - vec4_f32 *pixels; - f32 *sketch; Input_Key *input; Drop_File *drop_files; c8 *clipboard_text; @@ -713,12 +712,10 @@ extern Platform g_platform; 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 _drop_files_buffer_len = 0; -static u8 *_drop_files_buffer = NULL; +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_PRIMARY_SOUND_FRAMES] = {0}; static i64 _frame_duration [NUM_FRAMES_AVERAGED] = {0}; @@ -792,10 +789,13 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p g_platform.memory_buffer = memory_buffer_; } - i64 occupied_len = memory_buffer_occupied_len_(g_platform.memory_buffer_size); - u64 *occupied = (u64 *) g_platform.memory_buffer; + i64 occupied_len = memory_buffer_occupied_len_(g_platform.memory_buffer_size); + i64 occupied_len_bytes = occupied_len * 8; + i64 occupied_len_bits = occupied_len * 64; + + u64 *occupied = (u64 *) g_platform.memory_buffer; - if (g_platform.memory_buffer_size <= occupied_len * 64) { + if (g_platform.memory_buffer_size <= occupied_len_bytes) { LOG_ERROR("Memory buffer too small."); return NULL; } @@ -820,7 +820,7 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p return NULL; } - u8 *data = g_platform.memory_buffer + occupied_len * 64; + u8 *data = g_platform.memory_buffer + occupied_len_bytes; i64 prev_num_chunks = 0; i64 prev_chunk = 0; @@ -835,31 +835,26 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p // Search free space i64 i0 = 0; - while (i0 < occupied_len && occupied[i0] == ~0ull) - ++i0; - for (i64 i = i0; i < occupied_len * 64; ++i) { + while (i0 < occupied_len_bits && occupied[i0 / 64] == ~0ull) + i0 += 64; + for (i64 i = i0; i < occupied_len_bits; ++i) { b8 is_occupied = 0; - for (i64 j = i; j < i + num_chunks; ++j) { if (j >= prev_chunk && j < prev_chunk + prev_num_chunks) continue; - if ((occupied[j / 64] & (1ull << (j % 64))) == 0) continue; + if ((occupied[j / 64] & (1ull << (j % 64))) == 0) continue; is_occupied = 1; break; } - - if (is_occupied) { + if (!is_occupied) { chunk = i; break; } } - u8 *src = data + prev_chunk * MEMORY_CHUNK_SIZE; - u8 *dst = data + chunk * MEMORY_CHUNK_SIZE; - i64 len = size < previous_size ? size : previous_size; - // Check if out of memory + u8 *dst = data + chunk * MEMORY_CHUNK_SIZE; if (dst + size > g_platform.memory_buffer + g_platform.memory_buffer_size) { - LOG_ERROR("Out of memory."); + LOG_ERROR("Out of memory: %lld bytes", size - previous_size); return NULL; } @@ -868,6 +863,8 @@ void *memory_buffer_allocate(i64 size, i64 alignment, i64 previous_size, void *p occupied[j / 64] |= 1ull << (j % 64); // Copy data + u8 *src = data + prev_chunk * MEMORY_CHUNK_SIZE; + i64 len = size < previous_size ? size : previous_size; if (dst > src) for (i64 k = len - 1; k >= 0; --k) dst[k] = src[k]; @@ -901,6 +898,7 @@ void resize_dynamic_array_exact(i64 *num, void **data, i64 element_size, i64 new ); if (new_data == NULL && new_num > 0) + // Out of memory. return; *num = new_num; @@ -916,7 +914,8 @@ void resize_dynamic_array_capacity(i64 *num, i64 *capacity, void **data, i64 ele if (new_num > *capacity) resize_dynamic_array_exact(capacity, data, element_size, new_num); - *num = new_num; + if (new_num <= *capacity) + *num = new_num; } // ================================================================ @@ -982,19 +981,6 @@ static b8 native_little_endian_(void) { return ((u8 *) &(u32) { 1 })[0] == 1; } -static u32 load32_(void *src) { - if (native_little_endian_()) - return *( u32 * )( src ); - else { - u8 *p = ( u8 * )src; - u32 w = *p++; - w |= ( u32 )( *p++ ) << 8; - w |= ( u32 )( *p++ ) << 16; - w |= ( u32 )( *p++ ) << 24; - return w; - } -} - static u64 load64_(void *src) { if (native_little_endian_()) return *( u64 * )( src ); @@ -1040,39 +1026,6 @@ static void store64_(void *dst, u64 w) { } } -static u64 load48_(void *src) { - u8 *p = ( u8 * )src; - u64 w = *p++; - w |= ( u64 )( *p++ ) << 8; - w |= ( u64 )( *p++ ) << 16; - w |= ( u64 )( *p++ ) << 24; - w |= ( u64 )( *p++ ) << 32; - w |= ( u64 )( *p++ ) << 40; - return w; -} - -static void store48_(void *dst, u64 w) { - u8 *p = ( u8 * )dst; - *p++ = ( u8 )w; w >>= 8; - *p++ = ( u8 )w; w >>= 8; - *p++ = ( u8 )w; w >>= 8; - *p++ = ( u8 )w; w >>= 8; - *p++ = ( u8 )w; w >>= 8; - *p++ = ( u8 )w; -} - -static u32 rotl32_(u32 w, u32 c) { - return ( w << c ) | ( w >> ( 32 - c ) ); -} - -static u64 rotl64_(u64 w, u32 c) { - return ( w << c ) | ( w >> ( 64 - c ) ); -} - -static u32 rotr32_(u32 w, u32 c) { - return ( w >> c ) | ( w << ( 32 - c ) ); -} - static u64 rotr64_(u64 w, u32 c) { return ( w >> c ) | ( w << ( 64 - c ) ); } @@ -1087,11 +1040,6 @@ static i32 blake2b_set_lastnode_(Blake2b_State *S) { return 0; } -static i32 blake2b_clear_lastnode_(Blake2b_State *S) { - S->f[1] = 0ull; - return 0; -} - static i32 blake2b_set_lastblock_(Blake2b_State *S) { if( S->last_node ) blake2b_set_lastnode_( S ); @@ -1099,64 +1047,12 @@ static i32 blake2b_set_lastblock_(Blake2b_State *S) { return 0; } -static i32 blake2b_clear_lastblock_(Blake2b_State *S) { - if( S->last_node ) blake2b_clear_lastnode_( S ); - - S->f[0] = 0ull; - return 0; -} - static i32 blake2b_increment_counter_(Blake2b_State *S, u64 inc) { S->t[0] += inc; S->t[1] += ( S->t[0] < inc ); return 0; } -static i32 blake2b_param_set_digest_length_(Blake2b_Param *P, u8 digest_length) { - P->digest_length = digest_length; - return 0; -} - -static i32 blake2b_param_set_fanout_(Blake2b_Param *P, u8 fanout) { - P->fanout = fanout; - return 0; -} - -static i32 blake2b_param_set_max_depth_(Blake2b_Param *P, u8 depth) { - P->depth = depth; - return 0; -} - -static i32 blake2b_param_set_leaf_length_(Blake2b_Param *P, u32 leaf_length) { - store32_( &P->leaf_length, leaf_length ); - return 0; -} - -static i32 blake2b_param_set_node_offset_(Blake2b_Param *P, u64 node_offset) { - store64_( &P->node_offset, node_offset ); - return 0; -} - -static i32 blake2b_param_set_node_depth_(Blake2b_Param *P, u8 node_depth) { - P->node_depth = node_depth; - return 0; -} - -static i32 blake2b_param_set_inner_length_(Blake2b_Param *P, u8 inner_length) { - P->inner_length = inner_length; - return 0; -} - -static i32 blake2b_param_set_salt_(Blake2b_Param *P, u8 salt[BLAKE2B_SALTBYTES]) { - mem_cpy_( P->salt, salt, BLAKE2B_SALTBYTES ); - return 0; -} - -static i32 blake2b_param_set_personal_(Blake2b_Param *P, u8 personal[BLAKE2B_PERSONALBYTES]) { - mem_cpy_( P->personal, personal, BLAKE2B_PERSONALBYTES ); - return 0; -} - static i32 blake2b_init0_(Blake2b_State *S) { i32 i; mem_set_( S, 0, sizeof( Blake2b_State ) ); @@ -1511,11 +1407,6 @@ static void drop_files_clean_(void) { } resize_dynamic_array_exact(&g_platform.num_drop_files, (void **) &g_platform.drop_files, sizeof *g_platform.drop_files, 0); - resize_dynamic_array_exact(&_drop_files_buffer_len, (void **) &_drop_files_buffer, 1, 0); -} - -static i64 align_size_(i64 x) { - return (x + 7) & ~7ll; } static void drop_files_set_num_(i64 num) { @@ -1693,6 +1584,8 @@ static void network_cleanup_(void) { close(_sockets[i].socket); _sockets[i].ready = 0; } + + resize_dynamic_array_exact(&_num_sockets, (void **) &_sockets, sizeof *_sockets, 0); } static b8 network_open_(u16 slot, IP_Address address, u16 *local_port) { @@ -2674,6 +2567,19 @@ static i32 x11_error_handler_(Display *display, XErrorEvent *event) { return 0; } +void update_main_window_frame_(void) { + i64 num_pixels = g_platform.frame_width * g_platform.frame_height; + + if (g_platform.num_pixels < num_pixels) + resize_dynamic_array_exact(&g_platform.num_pixels, (void **) &g_platform.pixels, sizeof *g_platform.pixels, num_pixels); + if (_pixels_scaled_len < num_pixels) + resize_dynamic_array_exact(&_pixels_scaled_len, (void **) &_pixels_scaled, sizeof *_pixels_scaled, num_pixels); + if (_pixels_internal_len < num_pixels) + resize_dynamic_array_exact(&_pixels_internal_len, (void **) &_pixels_internal, sizeof *_pixels_internal, num_pixels); + + _image.data = (c8 *) _pixels_internal; +} + void init_main_window(void) { for (i64 i = 0; i < NUM_FRAMES_AVERAGED; ++i) _frame_duration[i] = (MIN_FRAME_DURATION + MAX_FRAME_DURATION) / 2; @@ -2851,9 +2757,7 @@ void init_main_window(void) { .width = g_platform.frame_width, .height = g_platform.frame_height, .depth = depth, - .xoffset = 0, .format = ZPixmap, - .data = (c8 *) _pixels_internal, .byte_order = LSBFirst, .bitmap_unit = 32, .bitmap_bit_order = LSBFirst, @@ -2865,6 +2769,8 @@ void init_main_window(void) { .blue_mask = 0x0000ff, }; + update_main_window_frame_(); + XInitImage(&_image); _wm_delete_window = XInternAtom(_display, "WM_DELETE_WINDOW", False); @@ -2915,6 +2821,15 @@ void shutdown_all_systems(void) { _window = 0; _display = NULL; + drop_files_clean_(); + g_platform.input_len = 0; + + resize_dynamic_array_exact(&_pixels_scaled_len, (void **) &_pixels_scaled, sizeof *_pixels_scaled, 0); + resize_dynamic_array_exact(&_pixels_internal_len, (void **) &_pixels_internal, sizeof *_pixels_internal, 0); + resize_dynamic_array_exact(&g_platform.num_pixels, (void **) &g_platform.pixels, sizeof *g_platform.pixels, 0); + resize_dynamic_array_exact(&g_platform.input_capacity, (void **) &g_platform.input, sizeof *g_platform.input, 0); + resize_dynamic_array_exact(&g_platform.clipboard_text_len, (void **) &g_platform.clipboard_text, 1, 0); + network_cleanup_(); sound_cleanup_(); } @@ -3466,11 +3381,7 @@ void render_main_window_frame(void) { _mapped = 1; } - i64 num_pixels = g_platform.frame_width * g_platform.frame_height; - if (_pixels_scaled_len < num_pixels) - resize_dynamic_array_exact(&_pixels_scaled_len, (void **) &_pixels_scaled, sizeof *_pixels_scaled, num_pixels); - if (_pixels_internal_len < num_pixels) - resize_dynamic_array_exact(&_pixels_internal_len, (void **) &_pixels_internal, sizeof *_pixels_internal, num_pixels); + update_main_window_frame_(); if (g_platform.frame_width == _image.width && g_platform.frame_height == _image.height) { i64 size = g_platform.frame_width * g_platform.frame_height; @@ -3815,18 +3726,31 @@ i32 wait_main_window_events(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; + if (size > g_platform.num_pixels) + size = g_platform.num_pixels; + if (size > _pixels_internal_len) + size = _pixels_internal_len; + 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 }); } else { i64 size = g_platform.frame_width * g_platform.frame_height; + if (size > g_platform.num_pixels) + size = g_platform.num_pixels; + if (size > _pixels_scaled_len) + size = _pixels_scaled_len; + 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 }); for (i64 j = 0; j < _frame_height; ++j) { i64 j0 = (j * g_platform.frame_height) / _frame_height; + if ((j0 + 1) * _frame_width > _pixels_internal_len) break; 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]; + i64 n0 = j0 * g_platform.frame_width + i0; + if (n0 > _pixels_scaled_len) break; + _pixels_internal[j * _frame_width + i] = 0xff000000u | _pixels_scaled[n0]; } } } |