ogl_beamforming

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

base_win32.c (11138B)


      1 /* See LICENSE for license details. */
      2 
      3 /* NOTE(rnp): provides the platform layer for everything in this repo. */
      4 
      5 #define OS_SHARED_MEMORY_NAME "Local\\ogl_beamformer_parameters"
      6 
      7 #define OS_PATH_SEPARATOR_CHAR '\\'
      8 #define OS_PATH_SEPARATOR      "\\"
      9 
     10 #include "base_platform.h"
     11 
     12 #include "util.h"
     13 
     14 #define STD_INPUT_HANDLE  -10
     15 #define STD_OUTPUT_HANDLE -11
     16 #define STD_ERROR_HANDLE  -12
     17 
     18 #define PAGE_READONLY  0x02
     19 #define PAGE_READWRITE 0x04
     20 #define MEM_COMMIT     0x1000
     21 #define MEM_RESERVE    0x2000
     22 #define MEM_DECOMMIT   0x4000
     23 #define MEM_RELEASE    0x8000
     24 
     25 #define GENERIC_WRITE  0x40000000
     26 #define GENERIC_READ   0x80000000
     27 
     28 #define FILE_SHARE_READ            0x00000001
     29 #define FILE_MAP_ALL_ACCESS        0x000F001F
     30 #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
     31 #define FILE_FLAG_OVERLAPPED       0x40000000
     32 
     33 #define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
     34 
     35 #define FILE_ACTION_MODIFIED 0x00000003
     36 
     37 #define CREATE_ALWAYS  2
     38 #define OPEN_EXISTING  3
     39 
     40 #define THREAD_SET_LIMITED_INFORMATION 0x0400
     41 
     42 /* NOTE: this is packed because the w32 api designers are dumb and ordered the members
     43  * incorrectly. They worked around it be making the ft* members a struct {u32, u32} which
     44  * is aligned on a 4-byte boundary. Then in their documentation they explicitly tell you not
     45  * to cast to u64 because "it can cause alignment faults on 64-bit Windows" - go figure */
     46 typedef struct w32_file_info w32_file_info;
     47 pack_struct(struct w32_file_info {
     48 	u32 dwFileAttributes;
     49 	u64 ftCreationTime;
     50 	u64 ftLastAccessTime;
     51 	u64 ftLastWriteTime;
     52 	u32 dwVolumeSerialNumber;
     53 	u32 nFileSizeHigh;
     54 	u32 nFileSizeLow;
     55 	u32 nNumberOfLinks;
     56 	u32 nFileIndexHigh;
     57 	u32 nFileIndexLow;
     58 });
     59 
     60 typedef struct {
     61 	u32 next_entry_offset;
     62 	u32 action;
     63 	u32 filename_size;
     64 	u16 filename[];
     65 } w32_file_notify_info;
     66 
     67 typedef struct {
     68 	u16  architecture;
     69 	u16  _pad1;
     70 	u32  page_size;
     71 	i64  minimum_application_address;
     72 	i64  maximum_application_address;
     73 	u64  active_processor_mask;
     74 	u32  number_of_processors;
     75 	u32  processor_type;
     76 	u32  allocation_granularity;
     77 	u16  processor_level;
     78 	u16  processor_revision;
     79 } w32_system_info;
     80 
     81 typedef struct {
     82 	uptr internal, internal_high;
     83 	union {
     84 		struct {u32 off, off_high;};
     85 		iptr pointer;
     86 	};
     87 	iptr event_handle;
     88 } w32_overlapped;
     89 
     90 typedef struct {
     91 	u32 reserved1;
     92 	u32 reserved2;
     93 	u64 Reserved3[2];
     94 	u32 reserved4;
     95 	u32 reserved5;
     96 } w32_synchronization_barrier;
     97 
     98 typedef enum {
     99 	W32IOEvent_FileWatch,
    100 } W32IOEvent;
    101 
    102 typedef struct {
    103 	u64  tag;
    104 	iptr context;
    105 } w32_io_completion_event;
    106 
    107 #define W32(r) __declspec(dllimport) r __stdcall
    108 W32(b32)    CloseHandle(iptr);
    109 W32(b32)    CopyFileA(c8 *, c8 *, b32);
    110 W32(iptr)   CreateFileA(c8 *, u32, u32, void *, u32, u32, void *);
    111 W32(iptr)   CreateFileMappingA(iptr, void *, u32, u32, u32, c8 *);
    112 W32(iptr)   CreateIoCompletionPort(iptr, iptr, uptr, u32);
    113 W32(iptr)   CreateSemaphoreA(iptr, i32, i32, c8 *);
    114 W32(u64)    CreateThread(iptr, u64, iptr, iptr, u32, u32 *);
    115 W32(b32)    DeleteFileA(c8 *);
    116 W32(b32)    EnterSynchronizationBarrier(w32_synchronization_barrier *, u32);
    117 W32(void)   ExitProcess(i32);
    118 W32(i32)    GetFileAttributesA(c8 *);
    119 W32(b32)    GetFileInformationByHandle(iptr, void *);
    120 W32(i32)    GetLastError(void);
    121 W32(b32)    GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32);
    122 W32(iptr)   GetStdHandle(i32);
    123 W32(void)   GetSystemInfo(w32_system_info *);
    124 W32(b32)    InitializeSynchronizationBarrier(w32_synchronization_barrier *, i32, i32);
    125 W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64);
    126 W32(b32)    QueryPerformanceCounter(u64 *);
    127 W32(b32)    QueryPerformanceFrequency(u64 *);
    128 W32(b32)    ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *);
    129 W32(b32)    ReadFile(iptr, u8 *, i32, i32 *, void *);
    130 W32(b32)    ReleaseSemaphore(iptr, i32, i32 *);
    131 W32(i32)    SetThreadDescription(u64, u16 *);
    132 W32(u32)    WaitForSingleObject(iptr, u32);
    133 W32(b32)    WaitOnAddress(void *, void *, u64, u32);
    134 W32(i32)    WakeByAddressAll(void *);
    135 W32(b32)    WriteFile(iptr, u8 *, i32, i32 *, void *);
    136 W32(void *) VirtualAlloc(u8 *, i64, u32, u32);
    137 W32(b32)    VirtualFree(void *, u64, u32);
    138 
    139 enum {OSW32_FileWatchDirectoryBufferSize = KB(4)};
    140 
    141 typedef struct OSW32Entity OSW32Entity;
    142 typedef struct {
    143 	void *handle;
    144 	OSW32Entity *prev, *next;
    145 } OSW32Window;
    146 
    147 typedef enum {
    148 	OSW32FileWatchKind_Platform,
    149 	OSW32FileWatchKind_User,
    150 } OSW32FileWatchKind;
    151 
    152 typedef struct OSW32FileWatchDirectory OSW32FileWatchDirectory;
    153 typedef struct OSW32FileWatch OSW32FileWatch;
    154 struct OSW32FileWatch {
    155 	OSW32FileWatchKind  kind;
    156 	u64                 hash;
    157 	u64                 update_time;
    158 	void               *user_context;
    159 
    160 	OSW32FileWatchDirectory *parent;
    161 	OSW32FileWatch *prev, *next;
    162 };
    163 
    164 struct OSW32FileWatchDirectory {
    165 	u64  hash;
    166 	i64  handle;
    167 	str8 name;
    168 
    169 	OSW32FileWatch *first_child;
    170 	OSW32FileWatch *last_child;
    171 	OSW32FileWatchDirectory *prev, *next;
    172 
    173 	w32_overlapped          overlapped;
    174   w32_io_completion_event event;
    175 
    176 	void *buffer;
    177 };
    178 
    179 typedef enum {
    180 	OSW32EntityKind_Window,
    181 	OSW32EntityKind_FileWatch,
    182 	OSW32EntityKind_FileWatchDirectory,
    183 } OSW32EntityKind;
    184 
    185 struct OSW32Entity {
    186 	OSW32EntityKind kind;
    187 	union {
    188 		OSW32FileWatch          file_watch;
    189 		OSW32FileWatchDirectory file_watch_directory;
    190 		OSW32Window             window;
    191 	} as;
    192 	OSW32Entity *next;
    193 };
    194 
    195 typedef struct {
    196 	OSSystemInfo  system_info;
    197 
    198 	Arena        *arena;
    199 	i32           arena_lock;
    200 	i64           error_handle;
    201 	i64           io_completion_handle;
    202 
    203 	struct {
    204 		OSW32FileWatchDirectory *first;
    205 		OSW32FileWatchDirectory *last;
    206 	} file_watch_directories;
    207 
    208 	struct {
    209 		OSW32Entity *first;
    210 		OSW32Entity *last;
    211 	} windows;
    212 
    213 	OSW32Entity *entity_freelist;
    214 } OSW32_Context;
    215 global OSW32_Context os_w32_context;
    216 
    217 function b32
    218 os_write_file(iptr file, void *data, i64 length)
    219 {
    220 	i32 wlen = 0;
    221 	if (length > 0 && length <= (i64)U32_MAX) WriteFile(file, data, (i32)length, &wlen, 0);
    222 	return length == wlen;
    223 }
    224 
    225 BASE_EXPORT no_return void
    226 os_exit(i32 code)
    227 {
    228 	ExitProcess(code);
    229 	unreachable();
    230 }
    231 
    232 function u64
    233 os_timer_frequency(void)
    234 {
    235 	u64 result;
    236 	QueryPerformanceFrequency(&result);
    237 	return result;
    238 }
    239 
    240 BASE_EXPORT u64
    241 os_timer_count(void)
    242 {
    243 	u64 result;
    244 	QueryPerformanceCounter(&result);
    245 	return result;
    246 }
    247 
    248 function void
    249 os_system_info_init(void)
    250 {
    251 	w32_system_info info = {0};
    252 	GetSystemInfo(&info);
    253 
    254 	os_w32_context.system_info.timer_frequency         = os_timer_frequency();
    255 	os_w32_context.system_info.logical_processor_count = info.number_of_processors;
    256 	os_w32_context.system_info.page_size               = info.page_size;
    257 	os_w32_context.system_info.path_separator_byte     = '\\';
    258 }
    259 
    260 BASE_EXPORT OSSystemInfo *
    261 os_system_info(void)
    262 {
    263 	#if BASE_PLATFORM_NO_MAIN
    264 	if unlikely(os_w32_context.system_info.path_separator_byte == 0)
    265 		os_system_info_init();
    266 	#endif
    267 	return &os_w32_context.system_info;
    268 }
    269 
    270 BASE_EXPORT void *
    271 os_memory_reserve(u64 size)
    272 {
    273 	void *result = VirtualAlloc(0, size, MEM_RESERVE, PAGE_READWRITE);
    274 	return result;
    275 }
    276 
    277 BASE_EXPORT void
    278 os_memory_release(void *base, u64 size)
    279 {
    280 	// NOTE(rnp): size must be 0 on w32, no partial releasing
    281 	VirtualFree(base, 0, MEM_RELEASE);
    282 }
    283 
    284 BASE_EXPORT b32
    285 os_memory_commit(void *base, u64 size)
    286 {
    287 	b32 result = VirtualAlloc(base, size, MEM_COMMIT, PAGE_READWRITE) != 0;
    288 	return result;
    289 }
    290 
    291 BASE_EXPORT OSW32Semaphore
    292 os_w32_create_semaphore(const char *name, i32 initial_count, i32 maximum_count)
    293 {
    294 	OSW32Semaphore result = {(u64)CreateSemaphoreA(0, initial_count, maximum_count, (c8 *)name)};
    295 	return result;
    296 }
    297 
    298 BASE_EXPORT u32
    299 os_w32_semaphore_wait(OSW32Semaphore handle, u32 timeout_ms)
    300 {
    301 	b32 result = !WaitForSingleObject(handle.value[0], timeout_ms);
    302 	return result;
    303 }
    304 
    305 BASE_EXPORT void
    306 os_w32_semaphore_release(OSW32Semaphore handle, i32 count)
    307 {
    308 	ReleaseSemaphore(handle.value[0], count, 0);
    309 }
    310 
    311 BASE_EXPORT str8
    312 os_read_entire_file(Arena *arena, const char *file)
    313 {
    314 	str8 result = {0};
    315 	w32_file_info fileinfo;
    316 	iptr h = CreateFileA((c8 *)file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
    317 	if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) {
    318 		i64 filesize  = (i64)fileinfo.nFileSizeHigh << 32;
    319 		filesize     |= (i64)fileinfo.nFileSizeLow;
    320 		result.data   = push_array(arena, u8, filesize);
    321 		result.length = filesize;
    322 		i32 rlen;
    323 		if (!ReadFile(h, result.data, (i32)filesize, &rlen, 0) || rlen != filesize) {
    324 			arena_pop(arena, filesize);
    325 			zero_struct(&result);
    326 		}
    327 	}
    328 	if (h >= 0) CloseHandle(h);
    329 
    330 	return result;
    331 }
    332 
    333 function b32
    334 os_write_new_file(char *fname, str8 raw)
    335 {
    336 	b32 result = 0;
    337 	iptr h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    338 	if (h >= 0) {
    339 		while (raw.length > 0) {
    340 			i64 length = Min(raw.length, (i64)GB(2));
    341 			result     = os_write_file(h, raw.data, length);
    342 			if (!result) break;
    343 			raw = str8_cut_head(raw, length);
    344 		}
    345 		CloseHandle(h);
    346 	}
    347 	return result;
    348 }
    349 
    350 function b32
    351 os_file_exists(char *path)
    352 {
    353 	b32 result = GetFileAttributesA(path) != -1;
    354 	return result;
    355 }
    356 
    357 function b32
    358 os_copy_file(char *name, char *new)
    359 {
    360 	return CopyFileA(name, new, 0);
    361 }
    362 
    363 function OSW32Entity *
    364 os_entity_allocate(OSW32EntityKind kind)
    365 {
    366 	OSW32Entity *result = 0;
    367 	DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
    368 	{
    369 		result = SLLPopFreelist(os_w32_context.entity_freelist);
    370 		if (!result) result = push_struct_no_zero(os_w32_context.arena, OSW32Entity);
    371 	}
    372 
    373 	zero_struct(result);
    374 	result->kind = kind;
    375 	return result;
    376 }
    377 
    378 BASE_EXPORT OSThread
    379 os_create_thread(const char *name, void *user_context, os_thread_entry_point_fn *fn)
    380 {
    381 	OSThread result = {(u64)CreateThread(0, 0, (iptr)fn, (iptr)user_context, 0, 0)};
    382 	if (result.value[0]) {
    383 		Temp scratch;
    384 		DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
    385 		DeferLoop(scratch = temp_begin(os_w32_context.arena), temp_end(scratch))
    386 		{
    387 			SetThreadDescription(result.value[0], str16_from_str8(scratch.arena, str8_from_c_str((c8 *)name)).data);
    388 		}
    389 	} else {
    390 		result.value[0] = OSInvalidHandleValue;
    391 	}
    392 	return result;
    393 }
    394 
    395 BASE_EXPORT OSBarrier
    396 os_barrier_alloc(u32 count)
    397 {
    398 	OSBarrier result = {0};
    399 	DeferLoop(take_lock(&os_w32_context.arena_lock, -1), release_lock(&os_w32_context.arena_lock))
    400 	{
    401 		w32_synchronization_barrier *barrier = push_struct(os_w32_context.arena, w32_synchronization_barrier);
    402 		InitializeSynchronizationBarrier(barrier, (i32)count, -1);
    403 		result.value[0] = (u64)barrier;
    404 	}
    405 	return result;
    406 }
    407 
    408 BASE_EXPORT void
    409 os_barrier_enter(OSBarrier barrier)
    410 {
    411 	w32_synchronization_barrier *b = (w32_synchronization_barrier *)barrier.value[0];
    412 	if (b) EnterSynchronizationBarrier(b, 0);
    413 }
    414 
    415 BASE_EXPORT b32
    416 os_wait_on_address(i32 *value, i32 current, u32 timeout_ms)
    417 {
    418 	return WaitOnAddress(value, &current, sizeof(*value), timeout_ms);
    419 }
    420 
    421 BASE_EXPORT void
    422 os_wake_all_waiters(i32 *sync)
    423 {
    424 	if (sync) {
    425 		atomic_store_u32(sync, 0);
    426 		WakeByAddressAll(sync);
    427 	}
    428 }
    429 
    430 #if !BASE_PLATFORM_NO_MAIN
    431 BASE_IMPORT void entry_point(i32 argc, char *argv[]);
    432 
    433 extern i32
    434 main(i32 argc, char *argv[])
    435 {
    436 	os_system_info_init();
    437 	os_w32_context.arena        = arena_create(.name = "Platform Arena");
    438 	os_w32_context.error_handle = GetStdHandle(STD_ERROR_HANDLE);
    439 
    440 	entry_point(argc, argv);
    441 
    442 	return 0;
    443 }
    444 #endif