ogl_beamforming

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

os_win32.c (9673B)


      1 /* See LICENSE for license details. */
      2 #include "util.h"
      3 
      4 #define STD_OUTPUT_HANDLE -11
      5 #define STD_ERROR_HANDLE  -12
      6 
      7 #define PAGE_READWRITE 0x04
      8 #define MEM_COMMIT     0x1000
      9 #define MEM_RESERVE    0x2000
     10 #define MEM_RELEASE    0x8000
     11 
     12 #define GENERIC_WRITE  0x40000000
     13 #define GENERIC_READ   0x80000000
     14 
     15 #define PIPE_WAIT      0x00
     16 #define PIPE_NOWAIT    0x01
     17 
     18 #define PIPE_TYPE_BYTE      0x00
     19 #define PIPE_ACCESS_INBOUND 0x01
     20 
     21 #define FILE_SHARE_READ            0x00000001
     22 #define FILE_MAP_ALL_ACCESS        0x000F001F
     23 #define FILE_FLAG_BACKUP_SEMANTICS 0x02000000
     24 #define FILE_FLAG_OVERLAPPED       0x40000000
     25 
     26 #define FILE_NOTIFY_CHANGE_LAST_WRITE 0x00000010
     27 
     28 #define FILE_ACTION_MODIFIED 0x00000003
     29 
     30 #define CREATE_ALWAYS  2
     31 #define OPEN_EXISTING  3
     32 
     33 #define ERROR_NO_DATA            232L
     34 #define ERROR_PIPE_NOT_CONNECTED 233L
     35 #define ERROR_PIPE_LISTENING     536L
     36 
     37 #define THREAD_SET_LIMITED_INFORMATION 0x0400
     38 
     39 typedef struct {
     40 	u16  wProcessorArchitecture;
     41 	u16  _pad1;
     42 	u32  dwPageSize;
     43 	iz   lpMinimumApplicationAddress;
     44 	iz   lpMaximumApplicationAddress;
     45 	u64  dwActiveProcessorMask;
     46 	u32  dwNumberOfProcessors;
     47 	u32  dwProcessorType;
     48 	u32  dwAllocationGranularity;
     49 	u16  wProcessorLevel;
     50 	u16  wProcessorRevision;
     51 } w32_sys_info;
     52 
     53 /* NOTE: this is packed because the w32 api designers are dumb and ordered the members
     54  * incorrectly. They worked around it be making the ft* members a struct {u32, u32} which
     55  * is aligned on a 4-byte boundary. Then in their documentation they explicitly tell you not
     56  * to cast to u64 because "it can cause alignment faults on 64-bit Windows" - go figure */
     57 typedef struct __attribute__((packed)) {
     58 	u32 dwFileAttributes;
     59 	u64 ftCreationTime;
     60 	u64 ftLastAccessTime;
     61 	u64 ftLastWriteTime;
     62 	u32 dwVolumeSerialNumber;
     63 	u32 nFileSizeHigh;
     64 	u32 nFileSizeLow;
     65 	u32 nNumberOfLinks;
     66 	u32 nFileIndexHigh;
     67 	u32 nFileIndexLow;
     68 } w32_file_info;
     69 
     70 typedef struct {
     71 	u32 next_entry_offset;
     72 	u32 action;
     73 	u32 filename_size;
     74 	u16 filename[];
     75 } w32_file_notify_info;
     76 
     77 typedef struct {
     78 	uptr internal, internal_high;
     79 	union {
     80 		struct {u32 off, off_high;};
     81 		iptr pointer;
     82 	};
     83 	iptr event_handle;
     84 } w32_overlapped;
     85 
     86 #define W32(r) __declspec(dllimport) r __stdcall
     87 W32(b32)    CloseHandle(iptr);
     88 W32(b32)    CopyFileA(c8 *, c8 *, b32);
     89 W32(iptr)   CreateFileA(c8 *, u32, u32, void *, u32, u32, void *);
     90 W32(iptr)   CreateFileMappingA(iptr, void *, u32, u32, u32, c8 *);
     91 W32(iptr)   CreateIoCompletionPort(iptr, iptr, uptr, u32);
     92 W32(iptr)   CreateNamedPipeA(c8 *, u32, u32, u32, u32, u32, u32, void *);
     93 W32(iptr)   CreateSemaphoreA(iptr, i64, i64, c8 *);
     94 W32(iptr)   CreateThread(iptr, uz, iptr, iptr, u32, u32 *);
     95 W32(b32)    DeleteFileA(c8 *);
     96 W32(b32)    DisconnectNamedPipe(iptr);
     97 W32(void)   ExitProcess(i32);
     98 W32(b32)    FreeLibrary(void *);
     99 W32(i32)    GetFileAttributesA(c8 *);
    100 W32(b32)    GetFileInformationByHandle(iptr, w32_file_info *);
    101 W32(i32)    GetLastError(void);
    102 W32(void *) GetModuleHandleA(c8 *);
    103 W32(void *) GetProcAddress(void *, c8 *);
    104 W32(b32)    GetQueuedCompletionStatus(iptr, u32 *, uptr *, w32_overlapped **, u32);
    105 W32(iptr)   GetStdHandle(i32);
    106 W32(void)   GetSystemInfo(void *);
    107 W32(void *) LoadLibraryA(c8 *);
    108 W32(void *) MapViewOfFile(iptr, u32, u32, u32, u64);
    109 W32(b32)    ReadDirectoryChangesW(iptr, u8 *, u32, b32, u32, u32 *, void *, void *);
    110 W32(b32)    ReadFile(iptr, u8 *, i32, i32 *, void *);
    111 W32(b32)    ReleaseSemaphore(iptr, i64, i64 *);
    112 W32(i32)    SetThreadDescription(iptr, u16 *);
    113 W32(u32)    WaitForSingleObjectEx(iptr, u32, b32);
    114 W32(b32)    WriteFile(iptr, u8 *, i32, i32 *, void *);
    115 W32(void *) VirtualAlloc(u8 *, iz, u32, u32);
    116 W32(b32)    VirtualFree(u8 *, iz, u32);
    117 
    118 #ifdef _DEBUG
    119 static void *
    120 os_get_module(char *name, Stream *e)
    121 {
    122 	void *result = GetModuleHandleA(name);
    123 	if (!result && e) {
    124 		s8 errs[] = {s8("os_get_module(\""), c_str_to_s8(name), s8("\"): ")};
    125 		stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    126 		stream_append_i64(e, GetLastError());
    127 		stream_append_byte(e, '\n');
    128 	}
    129 	return result;
    130 }
    131 #endif
    132 
    133 static OS_WRITE_FILE_FN(os_write_file)
    134 {
    135 	i32 wlen = 0;
    136 	if (raw.len) WriteFile(file, raw.data, raw.len, &wlen, 0);
    137 	return raw.len == wlen;
    138 }
    139 
    140 static void __attribute__((noreturn))
    141 os_fatal(s8 msg)
    142 {
    143 	os_write_file(GetStdHandle(STD_ERROR_HANDLE), msg);
    144 	ExitProcess(1);
    145 	unreachable();
    146 }
    147 
    148 static OS_ALLOC_ARENA_FN(os_alloc_arena)
    149 {
    150 	Arena result;
    151 	w32_sys_info Info;
    152 	GetSystemInfo(&Info);
    153 
    154 	if (capacity % Info.dwPageSize != 0)
    155 		capacity += (Info.dwPageSize - capacity % Info.dwPageSize);
    156 
    157 	iz oldsize = old.end - old.beg;
    158 	if (oldsize > capacity)
    159 		return old;
    160 
    161 	if (old.beg)
    162 		VirtualFree(old.beg, oldsize, MEM_RELEASE);
    163 
    164 	result.beg = VirtualAlloc(0, capacity, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
    165 	if (result.beg == NULL)
    166 		os_fatal(s8("os_alloc_arena: couldn't allocate memory\n"));
    167 	result.end = result.beg + capacity;
    168 	return result;
    169 }
    170 
    171 static OS_CLOSE_FN(os_close)
    172 {
    173 	CloseHandle(file);
    174 }
    175 
    176 static OS_OPEN_FOR_WRITE_FN(os_open_for_write)
    177 {
    178 	iptr result = CreateFileA(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
    179 	return result;
    180 }
    181 
    182 static OS_READ_WHOLE_FILE_FN(os_read_whole_file)
    183 {
    184 	s8 result = {0};
    185 
    186 	w32_file_info fileinfo;
    187 	iptr h = CreateFileA(file, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0);
    188 	if (h >= 0 && GetFileInformationByHandle(h, &fileinfo)) {
    189 		iz filesize  = (iz)fileinfo.nFileSizeHigh << 32;
    190 		filesize    |= (iz)fileinfo.nFileSizeLow;
    191 		result       = s8_alloc(arena, filesize);
    192 
    193 		ASSERT(filesize <= (iz)U32_MAX);
    194 
    195 		i32 rlen;
    196 		if (!ReadFile(h, result.data, result.len, &rlen, 0) || rlen != result.len)
    197 			result = (s8){0};
    198 	}
    199 	if (h >= 0) CloseHandle(h);
    200 
    201 	return result;
    202 }
    203 
    204 static OS_READ_FILE_FN(os_read_file)
    205 {
    206 	i32 total_read = 0;
    207 	ReadFile(file, buf, size, &total_read, 0);
    208 	return total_read;
    209 }
    210 
    211 static OS_WRITE_NEW_FILE_FN(os_write_new_file)
    212 {
    213 	if (raw.len > (iz)U32_MAX) {
    214 		os_write_file(GetStdHandle(STD_ERROR_HANDLE),
    215 		              s8("os_write_file: files >4GB are not yet handled on win32\n"));
    216 		return 0;
    217 	}
    218 
    219 	iptr h = CreateFileA(fname, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
    220 	if (h == INVALID_FILE)
    221 		return  0;
    222 
    223 	b32 ret = os_write_file(h, raw);
    224 	CloseHandle(h);
    225 
    226 	return ret;
    227 }
    228 
    229 static b32
    230 os_file_exists(char *path)
    231 {
    232 	b32 result = GetFileAttributesA(path) != -1;
    233 	return result;
    234 }
    235 
    236 static Pipe
    237 os_open_named_pipe(char *name)
    238 {
    239 	iptr h = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND, PIPE_TYPE_BYTE|PIPE_NOWAIT, 1,
    240 	                          0, MB(1), 0, 0);
    241 	return (Pipe){.file = h, .name = name};
    242 }
    243 
    244 static void *
    245 os_open_shared_memory_area(char *name, iz cap)
    246 {
    247 	iptr h = CreateFileMappingA(-1, 0, PAGE_READWRITE, 0, cap, name);
    248 	if (h == INVALID_FILE)
    249 		return NULL;
    250 
    251 	return MapViewOfFile(h, FILE_MAP_ALL_ACCESS, 0, 0, cap);
    252 }
    253 
    254 static void *
    255 os_load_library(char *name, char *temp_name, Stream *e)
    256 {
    257 	if (temp_name) {
    258 		if (CopyFileA(name, temp_name, 0))
    259 			name = temp_name;
    260 	}
    261 
    262 	void *result = LoadLibraryA(name);
    263 	if (!result && e) {
    264 		s8 errs[] = {s8("os_load_library(\""), c_str_to_s8(name), s8("\"): ")};
    265 		stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    266 		stream_append_i64(e, GetLastError());
    267 		stream_append_byte(e, '\n');
    268 	}
    269 
    270 	if (temp_name)
    271 		DeleteFileA(temp_name);
    272 
    273 	return result;
    274 }
    275 
    276 static void *
    277 os_lookup_dynamic_symbol(void *h, char *name, Stream *e)
    278 {
    279 	void *result = 0;
    280 	if (h) {
    281 		result = GetProcAddress(h, name);
    282 		if (!result && e) {
    283 			s8 errs[] = {s8("os_lookup_dynamic_symbol(\""), c_str_to_s8(name), s8("\"): ")};
    284 			stream_append_s8_array(e, errs, ARRAY_COUNT(errs));
    285 			stream_append_i64(e, GetLastError());
    286 			stream_append_byte(e, '\n');
    287 		}
    288 	}
    289 	return result;
    290 }
    291 
    292 static void
    293 os_unload_library(void *h)
    294 {
    295 	FreeLibrary(h);
    296 }
    297 
    298 static OS_ADD_FILE_WATCH_FN(os_add_file_watch)
    299 {
    300 	s8 directory  = path;
    301 	directory.len = s8_scan_backwards(path, '\\');
    302 	ASSERT(directory.len > 0);
    303 
    304 	u64 hash = s8_hash(directory);
    305 	FileWatchContext *fwctx = &os->file_watch_context;
    306 	FileWatchDirectory *dir = lookup_file_watch_directory(fwctx, hash);
    307 	if (!dir) {
    308 		ASSERT(path.data[directory.len] == '\\');
    309 
    310 		dir         = fwctx->directory_watches + fwctx->directory_watch_count++;
    311 		dir->hash   = hash;
    312 		dir->name   = push_s8_zero(a, directory);
    313 		dir->handle = CreateFileA((c8 *)dir->name.data, GENERIC_READ, FILE_SHARE_READ, 0,
    314 		                          OPEN_EXISTING,
    315 		                          FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OVERLAPPED, 0);
    316 
    317 		w32_context *ctx = (w32_context *)os->context;
    318 		w32_io_completion_event *event = push_struct(a, typeof(*event));
    319 		event->tag     = W32_IO_FILE_WATCH;
    320 		event->context = (iptr)dir;
    321 		CreateIoCompletionPort(dir->handle, ctx->io_completion_handle, (uptr)event, 0);
    322 
    323 		dir->buffer = sub_arena(a, 4096 + sizeof(w32_overlapped), 64);
    324 		w32_overlapped *overlapped = (w32_overlapped *)(dir->buffer.beg + 4096);
    325 		zero_struct(overlapped);
    326 
    327 		ReadDirectoryChangesW(dir->handle, dir->buffer.beg, 4096, 0,
    328 		                      FILE_NOTIFY_CHANGE_LAST_WRITE, 0, overlapped, 0);
    329 	}
    330 
    331 	insert_file_watch(dir, s8_cut_head(path, dir->name.len + 1), user_data, callback);
    332 }
    333 
    334 static iptr
    335 os_create_thread(Arena arena, iptr user_context, s8 name, os_thread_entry_point_fn *fn)
    336 {
    337 	iptr result = CreateThread(0, 0, (iptr)fn, user_context, 0, 0);
    338 	SetThreadDescription(result, s8_to_s16(&arena, name).data);
    339 	return result;
    340 }
    341 
    342 static iptr
    343 os_create_sync_object(Arena *arena)
    344 {
    345 	iptr result = CreateSemaphoreA(0, 0, 1, 0);
    346 	return result;
    347 }
    348 
    349 static void
    350 os_sleep_thread(iptr sync_handle)
    351 {
    352 	WaitForSingleObjectEx(sync_handle, 0xFFFFFFFF, 0);
    353 }
    354 
    355 static OS_WAKE_THREAD_FN(os_wake_thread)
    356 {
    357 	ReleaseSemaphore(sync_handle, 1, 0);
    358 }
    359 
    360 iptr glfwGetWGLContext(iptr);
    361 
    362 static iptr
    363 os_get_native_gl_context(iptr window)
    364 {
    365 	return glfwGetWGLContext(window);
    366 }