// ::Platform::Functions::pLibrary::Start:: b32 pLibraryLoad(const char *name, pLibrary *out_lib) { if (!name) { return false; } out_lib->lib = dlopen(name, RTLD_NOW); if (!out_lib->lib) { return false; } return true; } b32 pFunctionLoad(const char *name, pLibrary *lib, pFunction *out_fn) { if (!name) { return false; } out_fn->fn = dlsym(lib->lib, name); if (!out_fn->fn) { Printf("unable to find function\n"); return false; } return true; } // ::Platform::Functions::pLibrary::End:: // ::Platform::Functions::Print::Start:: // ::Platform::Functions::Print::End:: // ::Platform::Functions::Memory::Start:: rawptr pMemAlloc(usize size) { rawptr addr = mmap( NULL, size, PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0 ); if (pSyscallErrCheck(addr)) addr = NULL; return addr; } rawptr pMemAllocZeroed(usize size) { rawptr ptr = pMemAlloc(size); MemZero(ptr, size); return ptr; } rawptr pMemRealloc(rawptr ptr, usize old_size, usize new_size) { rawptr addr = mremap( ptr, old_size, new_size, MAP_ANON | MAP_PRIVATE ); if (pSyscallErrCheck(addr)) addr = NULL; return addr; } void pMemFree(rawptr ptr, usize size) { Assert(munmap(ptr, size) == 0, "munmap failed"); } usize pPageSize() { return (usize)sysconf(_SC_PAGESIZE); } // ::Platform::Functions::Memory::End:: // ::Platform::Functions::Window::Start:: b32 pWindowInit(const char *window_name) { pPlatformWindow *window = &linux_window; window->display = XOpenDisplay(NULL); if (!window->display) return false; window->connection = XGetXCBConnection(window->display); if (!window->connection) return false; xcb_void_cookie_t cookie; xcb_generic_error_t *error; const xcb_setup_t *setup = xcb_get_setup(window->connection); xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup); xcb_screen_t *screen = iter.data; const int event_mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION | XCB_EVENT_MASK_STRUCTURE_NOTIFY; const int val_win[] = {screen->black_pixel, event_mask}; const int val_mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; window->window = xcb_generate_id(window->connection); cookie = xcb_create_window( window->connection, XCB_COPY_FROM_PARENT, window->window, screen->root, 0, // x pos 0, // y pos window->w, // width window->h, // height 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, screen->root_visual, val_mask, val_win ); XCB_CHECK_ERROR(window, cookie, error, "Failed to create window."); cookie = xcb_map_window_checked(window->connection, window->window); XCB_CHECK_ERROR(window, cookie, error, "Failed to map window."); cookie = xcb_change_property_checked( window->connection, XCB_PROP_MODE_REPLACE, window->window, XCB_ATOM_WM_NAME, XCB_ATOM_STRING, 8, StrLen(window_name), window_name ); XCB_CHECK_ERROR(window, cookie, error, "Failed to rename window."); xcb_intern_atom_cookie_t c_proto = xcb_intern_atom(window->connection, 1, 12, "WM_PROTOCOLS"); xcb_intern_atom_reply_t *r_proto = xcb_intern_atom_reply(window->connection, c_proto, &error); XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_PROTOCOLS."); xcb_intern_atom_cookie_t c_close = xcb_intern_atom(window->connection, 0, 16, "WM_DELETE_WINDOW"); xcb_intern_atom_reply_t *r_close = xcb_intern_atom_reply(window->connection, c_close, &error); XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get WM_DELETE_WINDOW."); xcb_intern_atom_cookie_t c_minimize = xcb_intern_atom(window->connection, 0, 20, "_NET_WM_STATE_HIDDEN"); xcb_intern_atom_reply_t *r_minimize = xcb_intern_atom_reply(window->connection, c_minimize, &error); XCB_CHECK_CURRENT_ERROR(window, error, "Failed to get _NET_WM_STATE_HIDDEN"); cookie = xcb_change_property_checked( window->connection, XCB_PROP_MODE_REPLACE, window->window, r_proto->atom, XCB_ATOM_ATOM, 32, 1, &r_close->atom ); XCB_CHECK_ERROR(window, cookie, error, "Failed to set window close event."); window->close_event = r_close->atom; window->minimize_event = r_minimize->atom; free(r_proto); free(r_close); free(r_minimize); xcb_map_window(window->connection, window->window); i32 stream_result = xcb_flush(window->connection); if (stream_result <= 0) { Printfln("Error flushing the stream: %d", stream_result); return false; } return true; } pWindowSize pWindowGetSize() { return (pWindowSize) { .w = linux_window.w, .h = linux_window.h, }; } pPlatformWindow *pWindowGet() { return &linux_window; } b32 pWindowShouldQuit() { return false; } // ::Platform::Functions::Window::End:: // ::Platform::Functions::SystemInfo::Start:: u32 pCPUCountGet() { cpu_set_t cpu_set; sched_getaffinity(0, sizeof(cpu_set), &cpu_set); return CPU_COUNT(&cpu_set); } // ::Platform::Functions::SystemInfo::StarEnd:: // ::Platform::Functions::Directory::Start:: b32 pDirNavigate(c8 *dir) { return chdir(dir); } c8 **pDirGetFileNames(Arena *arena, u32 *count) { struct dirent *dir; DIR *d = opendir("."); *count = 0; if (d) { while ((dir = readdir(d)) != NULL) { if (!StrEq(dir->d_name, ".") && !StrEq(dir->d_name, "..")) *count += 1; } } c8 **file_names = MakeArray(arena, u8*, *count); d = opendir("."); *count = 0; if (d) { while ((dir = readdir(d)) != NULL) { if (!StrEq(dir->d_name, ".") && !StrEq(dir->d_name, "..")) { i32 str_len = StrLen(dir->d_name); file_names[*count] = MakeArray(arena, u8, str_len); MemCpy(file_names[*count], dir->d_name, str_len); *count += 1; } } } return (c8 **)file_names; } b8 pDirIsVisible(c8 *dir_name) { b8 found = false; struct dirent *dir; DIR *d = opendir("."); if (d) { while ((dir = readdir(d)) != NULL) { if (StrEq(dir_name, dir->d_name) && dir->d_type == DT_DIR) { found = true; break; } } } return found; } // ::Platform::Functions::Directory::End:: // ::Platform::Profiling::Functions::Start:: static u64 pOSTimerFreq() { return 1000000; } static u64 pOSTimerRead() { struct timeval value; gettimeofday(&value, 0); return pOSTimerFreq() * u64(value.tv_sec) + u64(value.tv_usec); } static inline u64 pCPUTimerRead() { return __rdtsc(); } // ::Platform::Profiling::Functions::End:: // ::Platform::Atomics::Functions::Start:: static inline void AtomicSignalFenceSeqCst() { __atomic_signal_fence(__ATOMIC_SEQ_CST); } DefScalarImpl(AtomicFetchIncr); DefScalarImpl(AtomicIncr); DefScalarImpl(AtomicStore); DefScalarImpl(AtomicLoad); DefScalarImpl(AtomicFetchSub); DefScalarImpl(AtomicCompareExchange); // ::Platform::Atomics::Functions::End::