ogl_beamforming

Ultrasound Beamforming Implemented with OpenGL
git clone anongit@rnpnr.xyz:ogl_beamforming.git
Log | Files | Refs | Feed | Submodules | LICENSE

Commit: 41b9f675f70e1b35f9b52b733470f807b913109d
Parent: a8dcf08697052f39a683fab4206e45d10bf77ef5
Author: Randy Palamar
Date:   Mon, 24 Feb 2025 21:28:16 -0700

core: utf16 helpers, set thread name on w32

Diffstat:
Mmain_linux.c | 2+-
Mmain_w32.c | 24+++++++++---------------
Mos_unix.c | 20++++++++------------
Mos_win32.c | 17++++++-----------
Mstatic.c | 4++--
Mutil.c | 126++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mutil.h | 37+++++++++++++++++++++----------------
7 files changed, 169 insertions(+), 61 deletions(-)

diff --git a/main_linux.c b/main_linux.c @@ -37,7 +37,7 @@ dispatch_file_watch_events(Platform *platform, Arena arena) if (event->wd != dir->handle) continue; - s8 file = cstr_to_s8(event->name); + s8 file = c_str_to_s8(event->name); u64 hash = s8_hash(file); for (u32 i = 0; i < dir->file_watch_count; i++) { FileWatch *fw = dir->file_watches + i; diff --git a/main_w32.c b/main_w32.c @@ -35,23 +35,17 @@ typedef struct { #include "static.c" static void -w32_wide_char_to_mb(Stream *s, u16 *wstr, u32 wide_char_length) -{ - /* NOTE(rnp): this assumes the wstr is strictly ASCII */ - s->errors |= (s->cap - s->widx) < wide_char_length; - if (!s->errors) { - for (u32 i = 0; i < wide_char_length; i++) - s->data[s->widx++] = wstr[i] & 0xFF; - } -} - -static void dispatch_file_watch(Platform *platform, FileWatchDirectory *fw_dir, u8 *buf, Arena arena) { i64 offset = 0; - Stream path = stream_alloc(&arena, 256); + TempArena save_point = {0}; w32_file_notify_info *fni = (w32_file_notify_info *)buf; do { + end_temp_arena(save_point); + save_point = begin_temp_arena(&arena); + + Stream path = {.data = arena_commit(&arena, KB(1)), .cap = KB(1)}; + if (fni->action != FILE_ACTION_MODIFIED) { path.widx = 0; stream_append_s8(&path, s8("unknown file watch event: ")); @@ -60,12 +54,12 @@ dispatch_file_watch(Platform *platform, FileWatchDirectory *fw_dir, u8 *buf, Are os_write_err_msg(stream_to_s8(&path)); } - path.widx = 0; stream_append_s8(&path, fw_dir->name); stream_append_byte(&path, '\\'); - s8 file_name = {.data = path.data + path.widx, .len = fni->filename_size / 2}; - w32_wide_char_to_mb(&path, fni->filename, fni->filename_size / 2); + s8 file_name = s16_to_s8(&arena, (s16){.data = fni->filename, + .len = fni->filename_size / 2}); + stream_append_s8(&path, file_name); stream_append_byte(&path, 0); path.widx--; diff --git a/os_unix.c b/os_unix.c @@ -80,7 +80,7 @@ static PLATFORM_READ_WHOLE_FILE_FN(os_read_whole_file) struct stat sb; i32 fd = open(file, O_RDONLY); if (fd >= 0 && fstat(fd, &sb) >= 0) { - result = s8alloc(arena, sb.st_size); + result = s8_alloc(arena, sb.st_size); size rlen = read(fd, result.data, result.len); if (rlen != result.len) result = (s8){0}; @@ -186,8 +186,8 @@ os_load_library(char *name, char *temp_name, Stream *e) } void *res = dlopen(name, RTLD_NOW|RTLD_LOCAL); if (!res && e) { - s8 errs[] = {s8("WARNING: os_load_library("), cstr_to_s8(name), s8("): "), - cstr_to_s8(dlerror()), s8("\n")}; + s8 errs[] = {s8("WARNING: os_load_library("), c_str_to_s8(name), s8("): "), + c_str_to_s8(dlerror()), s8("\n")}; stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); os_write_err_msg(stream_to_s8(e)); e->widx = 0; @@ -206,8 +206,8 @@ os_lookup_dynamic_symbol(void *h, char *name, Stream *e) return 0; void *res = dlsym(h, name); if (!res && e) { - s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), cstr_to_s8(name), s8("): "), - cstr_to_s8(dlerror()), s8("\n")}; + s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), c_str_to_s8(name), s8("): "), + c_str_to_s8(dlerror()), s8("\n")}; stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); os_write_err_msg(stream_to_s8(e)); e->widx = 0; @@ -238,11 +238,7 @@ static PLATFORM_ADD_FILE_WATCH_FN(os_add_file_watch) dir = fwctx->directory_watches + fwctx->directory_watch_count++; dir->hash = hash; - - dir->name = push_s8(a, directory); - arena_commit(a, 1); - dir->name.data[dir->name.len] = 0; - + dir->name = push_s8_zero(a, directory); i32 mask = IN_MOVED_TO|IN_CLOSE_WRITE; dir->handle = inotify_add_watch(fwctx->handle, (c8 *)dir->name.data, mask); } @@ -252,11 +248,11 @@ static PLATFORM_ADD_FILE_WATCH_FN(os_add_file_watch) i32 pthread_setname_np(pthread_t, char *); static iptr -os_create_thread(iptr user_context, char *name, platform_thread_entry_point_fn *fn) +os_create_thread(Arena arena, iptr user_context, s8 name, platform_thread_entry_point_fn *fn) { pthread_t result; pthread_create(&result, 0, (void *(*)(void *))fn, (void *)user_context); - pthread_setname_np(result, name); + pthread_setname_np(result, (char *)name.data); return (iptr)result; } diff --git a/os_win32.c b/os_win32.c @@ -182,7 +182,7 @@ static PLATFORM_READ_WHOLE_FILE_FN(os_read_whole_file) if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) { size filesize = (size)fileinfo.nFileSizeHigh << 32; filesize |= (size)fileinfo.nFileSizeLow; - result = s8alloc(arena, filesize); + result = s8_alloc(arena, filesize); ASSERT(filesize <= (size)U32_MAX); @@ -254,7 +254,7 @@ os_load_library(char *name, char *temp_name, Stream *e) void *res = LoadLibraryA(name); if (!res && e) { - s8 errs[] = {s8("WARNING: os_load_library("), cstr_to_s8(name), s8("): ")}; + s8 errs[] = {s8("WARNING: os_load_library("), c_str_to_s8(name), s8("): ")}; stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); stream_append_i64(e, GetLastError()); stream_append_byte(e, '\n'); @@ -275,7 +275,7 @@ os_lookup_dynamic_symbol(void *h, char *name, Stream *e) return 0; void *res = GetProcAddress(h, name); if (!res && e) { - s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), cstr_to_s8(name), s8("): ")}; + s8 errs[] = {s8("WARNING: os_lookup_dynamic_symbol("), c_str_to_s8(name), s8("): ")}; stream_append_s8_array(e, errs, ARRAY_COUNT(errs)); stream_append_i64(e, GetLastError()); stream_append_byte(e, '\n'); @@ -305,11 +305,7 @@ static PLATFORM_ADD_FILE_WATCH_FN(os_add_file_watch) dir = fwctx->directory_watches + fwctx->directory_watch_count++; dir->hash = hash; - - dir->name = push_s8(a, directory); - arena_commit(a, 1); - dir->name.data[dir->name.len] = 0; - + dir->name = push_s8_zero(a, directory); dir->handle = CreateFileA((c8 *)dir->name.data, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 0); @@ -332,11 +328,10 @@ static PLATFORM_ADD_FILE_WATCH_FN(os_add_file_watch) } static iptr -os_create_thread(iptr user_context, char *name, platform_thread_entry_point_fn *fn) +os_create_thread(Arena arena, iptr user_context, s8 name, platform_thread_entry_point_fn *fn) { iptr result = CreateThread(0, 0, (iptr)fn, user_context, 0, 0); - /* TODO(rnp): name needs to be utf16 encoded */ - //SetThreadDescription(result, s8_to_16(arena, name).data); + SetThreadDescription(result, s8_to_s16(&arena, name).data); return result; } diff --git a/static.c b/static.c @@ -89,7 +89,7 @@ get_gl_params(GLParams *gl, Stream *err) case 'M': gl->vendor_id = GL_VENDOR_ARM; break; default: stream_append_s8(err, s8("Unknown GL Vendor: ")); - stream_append_s8(err, cstr_to_s8(vendor)); + stream_append_s8(err, c_str_to_s8(vendor)); stream_append_byte(err, '\n'); os_fatal(stream_to_s8(err)); break; @@ -276,7 +276,7 @@ setup_beamformer(BeamformerCtx *ctx, Arena *memory) GLWorkerThreadContext *worker = &ctx->platform.compute_worker; worker->window_handle = glfwCreateWindow(320, 240, "", 0, raylib_window_handle); worker->sync_handle = os_create_sync_object(memory); - worker->handle = os_create_thread((iptr)worker, "[compute]", + worker->handle = os_create_thread(*memory, (iptr)worker, s8("[compute]"), compute_worker_thread_entry_point); /* TODO(rnp): we should lock this down after we have something working */ worker->user_context = (iptr)ctx; diff --git a/util.c b/util.c @@ -39,11 +39,19 @@ mem_move(u8 *src, u8 *dest, size n) } -static void +static u8 * arena_commit(Arena *a, size size) { ASSERT(a->end - a->beg >= size); + u8 *result = a->beg; a->beg += size; + return result; +} + +static void +arena_pop(Arena *a, size length) +{ + a->beg -= length; } #define alloc(a, t, n) (t *)alloc_(a, sizeof(t), _Alignof(t), n) @@ -95,6 +103,67 @@ end_temp_arena(TempArena ta) } } +static u32 +utf8_encode(u8 *out, u32 cp) +{ + u32 result = 1; + if (cp <= 0x7F) { + out[0] = cp & 0x7F; + } else if (cp <= 0x7FF) { + result = 2; + out[0] = ((cp >> 6) & 0x1F) | 0xC0; + out[1] = ((cp >> 0) & 0x3F) | 0x80; + } else if (cp <= 0xFFFF) { + result = 3; + out[0] = ((cp >> 12) & 0x0F) | 0xE0; + out[1] = ((cp >> 6) & 0x3F) | 0x80; + out[2] = ((cp >> 0) & 0x3F) | 0x80; + } else if (cp <= 0x10FFFF) { + result = 4; + out[0] = ((cp >> 18) & 0x07) | 0xF0; + out[1] = ((cp >> 12) & 0x3F) | 0x80; + out[2] = ((cp >> 6) & 0x3F) | 0x80; + out[3] = ((cp >> 0) & 0x3F) | 0x80; + } else { + out[0] = '?'; + } + return result; +} + +static UnicodeDecode +utf16_decode(u16 *data, size length) +{ + UnicodeDecode result = {.cp = U32_MAX}; + if (length) { + result.consumed = 1; + result.cp = data[0]; + if (length > 1 && BETWEEN(data[0], 0xD800, 0xDBFF) + && BETWEEN(data[1], 0xDC00, 0xDFFF)) + { + result.consumed = 2; + result.cp = ((data[0] - 0xD800) << 10) | ((data[1] - 0xDC00) + 0x10000); + } + } + return result; +} + +static u32 +utf16_encode(u16 *out, u32 cp) +{ + u32 result = 1; + if (cp == U32_MAX) { + out[0] = '?'; + } else if (cp < 0x10000) { + out[0] = cp; + } else { + u32 value = cp - 0x10000; + out[0] = 0xD800 + (value >> 10u); + out[1] = 0xDC00 + (value & 0x3FFu); + result = 2; + } + return result; +} + static Stream arena_stream(Arena *a) { @@ -270,7 +339,7 @@ s8_hash(s8 v) } static s8 -cstr_to_s8(char *cstr) +c_str_to_s8(char *cstr) { s8 result = {.data = (u8 *)cstr}; while (*cstr) { result.len++; cstr++; } @@ -299,15 +368,64 @@ s8_cut_head(s8 s, size cut) } static s8 -s8alloc(Arena *a, size len) +s8_alloc(Arena *a, size len) { return (s8){ .data = alloc(a, u8, len), .len = len }; } static s8 +s16_to_s8(Arena *a, s16 in) +{ + s8 result = {0}; + if (in.len) { + size commit = in.len * 4; + size length = 0; + u8 *data = arena_commit(a, commit + 1); + u16 *beg = in.data; + u16 *end = in.data + in.len; + while (beg < end) { + UnicodeDecode decode = utf16_decode(beg, end - beg); + length += utf8_encode(data + length, decode.cp); + beg += decode.consumed; + } + data[length] = 0; + result = (s8){.len = length, .data = data}; + arena_pop(a, commit - length); + } + return result; +} + +static s16 +s8_to_s16(Arena *a, s8 in) +{ + s16 result = {0}; + if (in.len) { + size required = 2 * in.len + 1; + u16 *data = alloc(a, u16, required); + size length = 0; + /* TODO(rnp): utf8_decode */ + for (size i = 0; i < in.len; i++) { + u32 cp = in.data[i]; + length += utf16_encode(data + length, cp); + } + result = (s16){.len = length, .data = data}; + arena_pop(a, required - length); + } + return result; +} + +static s8 push_s8(Arena *a, s8 str) { - s8 result = s8alloc(a, str.len); + s8 result = s8_alloc(a, str.len); + mem_copy(str.data, result.data, result.len); + return result; +} + +static s8 +push_s8_zero(Arena *a, s8 str) +{ + s8 result = s8_alloc(a, str.len + 1); mem_copy(str.data, result.data, result.len); return result; } diff --git a/util.h b/util.h @@ -37,22 +37,23 @@ #define static_assert _Static_assert -#define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) -#define ABS(x) ((x) < 0 ? (-x) : (x)) -#define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) -#define CLAMP01(x) CLAMP(x, 0, 1) -#define ISPOWEROF2(a) (((a) & ((a) - 1)) == 0) -#define MIN(a, b) ((a) < (b) ? (a) : (b)) -#define MAX(a, b) ((a) > (b) ? (a) : (b)) -#define ORONE(x) ((x)? (x) : 1) -#define SIGN(x) ((x) < 0? -1 : 1) - -#define KB(a) ((a) << 10ULL) -#define MB(a) ((a) << 20ULL) -#define GB(a) ((a) << 30ULL) - -#define U32_MAX (0xFFFFFFFFUL) -#define F32_INFINITY (__builtin_inff()) +#define ARRAY_COUNT(a) (sizeof(a) / sizeof(*a)) +#define ABS(x) ((x) < 0 ? (-x) : (x)) +#define BETWEEN(x, a, b) ((x) >= (a) && (x) <= (b)) +#define CLAMP(x, a, b) ((x) < (a) ? (a) : (x) > (b) ? (b) : (x)) +#define CLAMP01(x) CLAMP(x, 0, 1) +#define ISPOWEROF2(a) (((a) & ((a) - 1)) == 0) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define ORONE(x) ((x)? (x) : 1) +#define SIGN(x) ((x) < 0? -1 : 1) + +#define KB(a) ((a) << 10ULL) +#define MB(a) ((a) << 20ULL) +#define GB(a) ((a) << 30ULL) + +#define U32_MAX (0xFFFFFFFFUL) +#define F32_INFINITY (__builtin_inff()) typedef char c8; typedef uint8_t u8; @@ -78,6 +79,10 @@ typedef struct { Arena *arena; u8 *old_beg; } TempArena; typedef struct { size len; u8 *data; } s8; #define s8(s) (s8){.len = ARRAY_COUNT(s) - 1, .data = (u8 *)s} +typedef struct { size len; u16 *data; } s16; + +typedef struct { u32 cp, consumed; } UnicodeDecode; + /* NOTE: raylib stubs */ #ifndef RAYLIB_H typedef struct { f32 x, y; } Vector2;