350 lines
6.7 KiB
C
350 lines
6.7 KiB
C
// ::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::
|