497 lines
14 KiB
C
497 lines
14 KiB
C
/* date = March 22nd 2022 2:05 am */
|
|
|
|
#ifndef LUMENARIUM_PLATFORM_H
|
|
#define LUMENARIUM_PLATFORM_H
|
|
|
|
// This is a file that defines the things that every platform
|
|
// must expose to the entire program
|
|
|
|
///////////////////////////////////////
|
|
// Memory
|
|
|
|
u64 platform_page_size();
|
|
|
|
u8* platform_mem_reserve(u64 size);
|
|
u8* platform_mem_commit(u8* base, u64 size);
|
|
bool platform_mem_decommit(u8* base, u64 size);
|
|
bool platform_mem_release(u8* base, u64 size);
|
|
|
|
///////////////////////////////////////
|
|
// File I/O
|
|
|
|
struct Platform_File_Handle
|
|
{
|
|
u64 value;
|
|
};
|
|
|
|
typedef u32 Platform_File_Access_Flags;
|
|
enum
|
|
{
|
|
FileAccess_None = 0,
|
|
FileAccess_Read = 1,
|
|
FileAccess_Write = 2,
|
|
};
|
|
|
|
typedef u32 Platform_File_Create_Flags;
|
|
enum
|
|
{
|
|
// these match https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilea
|
|
FileCreate_None = 0,
|
|
FileCreate_New = 1,
|
|
FileCreate_CreateAlways = 2,
|
|
FileCreate_OpenExisting = 3,
|
|
FileCreate_OpenAlways = 4,
|
|
};
|
|
|
|
typedef u32 Platform_File_Flags;
|
|
enum
|
|
{
|
|
FileFlag_IsFile = 0,
|
|
FileFlag_IsDir = 1,
|
|
};
|
|
|
|
struct Platform_File_Info
|
|
{
|
|
String path;
|
|
String path_abs;
|
|
u64 size;
|
|
u64 time_created;
|
|
u64 time_last_write;
|
|
Platform_File_Flags flags;
|
|
};
|
|
|
|
struct Platform_File_Info_List_Ele
|
|
{
|
|
Platform_File_Info info;
|
|
Platform_File_Info_List_Ele* next;
|
|
};
|
|
|
|
struct Platform_File_Info_List
|
|
{
|
|
Platform_File_Info_List_Ele* first;
|
|
Platform_File_Info_List_Ele* last;
|
|
};
|
|
|
|
Platform_File_Handle platform_file_open(String path, Platform_File_Access_Flags flags_access, Platform_File_Create_Flags flags_create);
|
|
void platform_file_close(Platform_File_Handle file_handle);
|
|
Platform_File_Info platform_file_get_info(Platform_File_Handle file_handle, Allocator* allocator);
|
|
Data platform_file_read_all(Platform_File_Handle file_handle, Allocator* allocator);
|
|
bool platform_file_write_all(Platform_File_Handle file_handle, Data file_data);
|
|
String platform_get_exe_path(Allocator* allocator);
|
|
bool platform_pwd_set(String path);
|
|
|
|
// For Cross Platform File Operations use these:
|
|
|
|
typedef u32 Platform_File_Async_Job_Flags;
|
|
enum
|
|
{
|
|
PlatformFileAsyncJob_Invalid = 0,
|
|
PlatformFileAsyncJob_Read = 1 << 0,
|
|
PlatformFileAsyncJob_Write = 1 << 1,
|
|
PlatformFileAsyncJob_InFlight = 1 << 2,
|
|
PlatformFileAsyncJob_Success = 1 << 3,
|
|
PlatformFileAsyncJob_Failed = 1 << 4,
|
|
};
|
|
|
|
struct Platform_File_Async_Job_Args
|
|
{
|
|
String path;
|
|
Data data;
|
|
Platform_File_Async_Job_Flags flags;
|
|
u32 error;
|
|
};
|
|
|
|
typedef void Platform_File_Async_Cb(Platform_File_Async_Job_Args args, u8* user_data);
|
|
|
|
struct Platform_File_Async_Job
|
|
{
|
|
Data job_memory;
|
|
Platform_File_Async_Job_Args args;
|
|
Platform_File_Async_Cb* cb;
|
|
};
|
|
|
|
global Allocator* platform_file_jobs_arena = 0;
|
|
#define PLATFORM_FILE_ASYNC_MAX_JOBS 32
|
|
global Platform_File_Async_Job platform_file_async_jobs[PLATFORM_FILE_ASYNC_MAX_JOBS];
|
|
global u32 platform_file_async_jobs_len = 0;
|
|
|
|
void
|
|
platform_file_jobs_init()
|
|
{
|
|
platform_file_jobs_arena = paged_allocator_create_reserve(MB(4), 256);
|
|
}
|
|
|
|
bool
|
|
platform_file_async_job_add(Platform_File_Async_Job job)
|
|
{
|
|
if (platform_file_async_jobs_len >= PLATFORM_FILE_ASYNC_MAX_JOBS) return false;
|
|
|
|
// Copy data to job local memory
|
|
u64 size_needed = job.args.path.len + job.args.data.size + 1;
|
|
u8* job_mem = allocator_alloc(platform_file_jobs_arena, size_needed);
|
|
String job_path = string_create(job_mem, 0, job.args.path.len + 1);
|
|
u64 copied = string_copy_to(&job_path, job.args.path);
|
|
Data job_data = data_create(job_mem + job_path.cap + 1, size_needed - (job_path.cap + 1));
|
|
memory_copy(job.args.data.base, job_data.base, job.args.data.size);
|
|
job.args.path = job_path;
|
|
job.args.data = job_data;
|
|
job.job_memory = data_create(job_mem, size_needed);
|
|
|
|
platform_file_async_jobs[platform_file_async_jobs_len++] = job;
|
|
return true;
|
|
}
|
|
|
|
Platform_File_Async_Job
|
|
platform_file_async_job_rem(u64 index)
|
|
{
|
|
assert(index < platform_file_async_jobs_len);
|
|
Platform_File_Async_Job result = platform_file_async_jobs[index];
|
|
|
|
platform_file_async_jobs_len -= 1;
|
|
if (platform_file_async_jobs_len > 0)
|
|
{
|
|
u32 last_job = platform_file_async_jobs_len;
|
|
platform_file_async_jobs[index] = platform_file_async_jobs[last_job];
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
platform_file_async_read(String path, Platform_File_Async_Cb* cb)
|
|
{
|
|
Platform_File_Async_Job job = {};
|
|
job.args.path = path;
|
|
job.args.flags = (
|
|
PlatformFileAsyncJob_Read |
|
|
PlatformFileAsyncJob_InFlight
|
|
);
|
|
job.cb = cb;
|
|
bool result = platform_file_async_job_add(job);
|
|
return result;
|
|
}
|
|
|
|
bool
|
|
platform_file_async_write(String path, Data data, Platform_File_Async_Cb* cb)
|
|
{
|
|
Platform_File_Async_Job job = {};
|
|
job.args.path = path;
|
|
job.args.data = data;
|
|
job.args.flags = (
|
|
PlatformFileAsyncJob_Write |
|
|
PlatformFileAsyncJob_InFlight
|
|
);
|
|
job.cb = cb;
|
|
bool result = platform_file_async_job_add(job);
|
|
return result;
|
|
}
|
|
|
|
void
|
|
platform_file_async_job_complete(Platform_File_Async_Job* job, u8* user_data)
|
|
{
|
|
job->cb(job->args, user_data);
|
|
allocator_free(platform_file_jobs_arena, job->job_memory.base, job->job_memory.size);
|
|
if (has_flag(job->args.flags, PlatformFileAsyncJob_Write))
|
|
{
|
|
allocator_free(platform_file_jobs_arena, job->args.data.base, job->args.data.size);
|
|
}
|
|
}
|
|
|
|
void platform_file_async_work_on_job(Platform_File_Async_Job* job);
|
|
|
|
void
|
|
platform_file_async_jobs_do_work(u64 max_jobs, u8* user_data)
|
|
{
|
|
u64 to_do = max_jobs;
|
|
if (max_jobs > platform_file_async_jobs_len) to_do = platform_file_async_jobs_len;
|
|
|
|
Platform_File_Async_Job_Flags completed = (
|
|
PlatformFileAsyncJob_Success |
|
|
PlatformFileAsyncJob_Failed
|
|
);
|
|
|
|
for (u64 i = to_do - 1; i < to_do; i--)
|
|
{
|
|
Platform_File_Async_Job* job = platform_file_async_jobs + i;
|
|
platform_file_async_work_on_job(job);
|
|
if (has_flag(job->args.flags, completed))
|
|
{
|
|
platform_file_async_job_complete(job, user_data);
|
|
platform_file_async_job_rem(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
typedef u32 Platform_Enum_Dir_Flags;
|
|
enum
|
|
{
|
|
EnumDir_Recursive = 1,
|
|
EnumDir_IncludeDirectories = 2,
|
|
};
|
|
|
|
Platform_File_Info_List platform_dir_enum(String path, Platform_Enum_Dir_Flags flags, Allocator* allocator);
|
|
|
|
String platform_get_exe_path(Allocator* allocator);
|
|
bool platform_pwd_set(String path);
|
|
|
|
///////////////////////////////////////
|
|
// Windows & Events
|
|
|
|
enum Platform_Window_Event_Kind
|
|
{
|
|
WindowEvent_Invalid = 0,
|
|
|
|
WindowEvent_MouseScroll,
|
|
WindowEvent_MouseMoved,
|
|
WindowEvent_ButtonDown,
|
|
WindowEvent_ButtonUp,
|
|
WindowEvent_Char,
|
|
WindowEvent_WindowClosed,
|
|
|
|
WindowEvent_Count,
|
|
};
|
|
|
|
typedef u32 Platform_Key_Code;
|
|
enum
|
|
{
|
|
KeyCode_Invalid = 0,
|
|
|
|
KeyCode_Esc,
|
|
|
|
KeyCode_Space,
|
|
KeyCode_Tab,
|
|
KeyCode_CapsLock,
|
|
KeyCode_LeftShift, KeyCode_RightShift,
|
|
KeyCode_LeftCtrl, KeyCode_RightCtrl,
|
|
KeyCode_Fn,
|
|
KeyCode_Alt,
|
|
KeyCode_PageUp, KeyCode_PageDown,
|
|
KeyCode_Backspace, KeyCode_Delete,
|
|
KeyCode_Enter,
|
|
|
|
// Function Keys
|
|
KeyCode_F0, KeyCode_F1, KeyCode_F2, KeyCode_F3, KeyCode_F4, KeyCode_F5, KeyCode_F6, KeyCode_F7,
|
|
KeyCode_F8, KeyCode_F9, KeyCode_F10, KeyCode_F11, KeyCode_F12,
|
|
|
|
// Letters
|
|
KeyCode_a, KeyCode_b, KeyCode_c, KeyCode_d, KeyCode_e, KeyCode_f, KeyCode_g, KeyCode_h,
|
|
KeyCode_i, KeyCode_j, KeyCode_k, KeyCode_l, KeyCode_m, KeyCode_n, KeyCode_o, KeyCode_p,
|
|
KeyCode_q, KeyCode_r, KeyCode_s, KeyCode_t, KeyCode_u, KeyCode_v, KeyCode_w, KeyCode_x,
|
|
KeyCode_y, KeyCode_z,
|
|
|
|
KeyCode_A, KeyCode_B, KeyCode_C, KeyCode_D, KeyCode_E, KeyCode_F, KeyCode_G, KeyCode_H,
|
|
KeyCode_I, KeyCode_J, KeyCode_K, KeyCode_L, KeyCode_M, KeyCode_N, KeyCode_O, KeyCode_P,
|
|
KeyCode_Q, KeyCode_R, KeyCode_S, KeyCode_T, KeyCode_U, KeyCode_V, KeyCode_W, KeyCode_X,
|
|
KeyCode_Y, KeyCode_Z,
|
|
|
|
// Numbers
|
|
KeyCode_0, KeyCode_1, KeyCode_2, KeyCode_3, KeyCode_4, KeyCode_5, KeyCode_6, KeyCode_7,
|
|
KeyCode_8, KeyCode_9,
|
|
|
|
KeyCode_Num0, KeyCode_Num1, KeyCode_Num2, KeyCode_Num3, KeyCode_Num4, KeyCode_Num5,
|
|
KeyCode_Num6, KeyCode_Num7, KeyCode_Num8, KeyCode_Num9,
|
|
|
|
// Symbols
|
|
KeyCode_Bang, KeyCode_At, KeyCode_Pound, KeyCode_Dollar, KeyCode_Percent, KeyCode_Carrot,
|
|
KeyCode_Ampersand, KeyCode_Star, KeyCode_LeftParen, KeyCode_RightParen, KeyCode_Minus, KeyCode_Plus,
|
|
KeyCode_Equals, KeyCode_Underscore, KeyCode_LeftBrace, KeyCode_RightBrace, KeyCode_LeftBracket,
|
|
KeyCode_RightBracket, KeyCode_Colon, KeyCode_SemiColon, KeyCode_SingleQuote, KeyCode_DoubleQuote,
|
|
KeyCode_ForwardSlash, KeyCode_Backslash, KeyCode_Pipe, KeyCode_Comma, KeyCode_Period,
|
|
KeyCode_QuestionMark, KeyCode_LessThan, KeyCode_GreaterThan, KeyCode_Tilde, KeyCode_BackQuote,
|
|
|
|
// Arrows
|
|
KeyCode_UpArrow,
|
|
KeyCode_DownArrow,
|
|
KeyCode_LeftArrow,
|
|
KeyCode_RightArrow,
|
|
|
|
// Mouse
|
|
// NOTE(Peter): Including this here so we can utilize the same KeyDown, KeyUp etc. functions
|
|
KeyCode_MouseLeftButton,
|
|
KeyCode_MouseMiddleButton,
|
|
KeyCode_MouseRightButton,
|
|
|
|
KeyCode_Count,
|
|
};
|
|
|
|
typedef u8 Platform_Key_Flags;
|
|
enum
|
|
{
|
|
KeyFlag_None = 0,
|
|
|
|
KeyFlag_Mod_Shift = 1,
|
|
KeyFlag_Mod_Ctrl = 2,
|
|
KeyFlag_Mod_Alt = 4,
|
|
KeyFlag_Mod_Sys = 8,
|
|
|
|
KeyFlag_State_WasDown = 16,
|
|
KeyFlag_State_IsDown = 32,
|
|
};
|
|
|
|
struct Platform_Window_Event
|
|
{
|
|
Platform_Window_Event_Kind kind;
|
|
Platform_Key_Code key_code;
|
|
Platform_Key_Flags key_flags;
|
|
s32 mouse_x;
|
|
s32 mouse_y;
|
|
s32 scroll_amt;
|
|
char char_value;
|
|
};
|
|
|
|
enum Platform_Cursor_Kind
|
|
{
|
|
Cursor_Arrow,
|
|
Cursor_Pointer,
|
|
Cursor_Loading,
|
|
Cursor_HArrows,
|
|
Cursor_VArrows,
|
|
Cursor_DTopLeftArrows,
|
|
Cursor_DTopRightArrows,
|
|
Cursor_Count,
|
|
};
|
|
|
|
///////////////////////////////////////
|
|
// Time
|
|
|
|
global r64 target_seconds_per_frame = 1.0 / 30.0f;
|
|
|
|
struct Platform_Ticks
|
|
{
|
|
s64 value;
|
|
};
|
|
|
|
Platform_Ticks platform_get_ticks();
|
|
r64 platform_ticks_to_seconds(Platform_Ticks ticks);
|
|
|
|
Platform_Ticks
|
|
get_ticks_elapsed(Platform_Ticks start, Platform_Ticks end)
|
|
{
|
|
Platform_Ticks result = {};
|
|
result.value = end.value - start.value;
|
|
return result;
|
|
}
|
|
|
|
r64
|
|
get_seconds_elapsed(Platform_Ticks start, Platform_Ticks end)
|
|
{
|
|
Platform_Ticks diff = get_ticks_elapsed(start, end);
|
|
return platform_ticks_to_seconds(diff);
|
|
}
|
|
|
|
// TODO(PS): we have some stuff in v1 around system time, probably
|
|
// for timestamps etc.
|
|
|
|
///////////////////////////////////////
|
|
// Threads
|
|
|
|
struct Platform_Thread_Handle
|
|
{
|
|
u64 value;
|
|
};
|
|
|
|
struct Platform_Thread_Result
|
|
{
|
|
u32 code;
|
|
};
|
|
|
|
typedef struct Platform_Thread_Data Platform_Thread_Data;
|
|
typedef Platform_Thread_Result Platform_Thread_Proc(Platform_Thread_Data* thread_data);
|
|
|
|
struct Platform_Thread_Data
|
|
{
|
|
Platform_Thread_Handle thread_handle;
|
|
u32 thread_id;
|
|
Platform_Thread_Proc* thread_proc;
|
|
Allocator* thread_memory;
|
|
u8* user_data;
|
|
};
|
|
|
|
Platform_Thread_Handle platform_thread_begin(Platform_Thread_Proc* proc, u8* user_data);
|
|
void platform_thread_end(Platform_Thread_Handle thread_handle);
|
|
|
|
u32 platform_interlocked_increment(volatile u32* value);
|
|
u32 platform_interlocked_cmp_exchg(volatile u32* dest, u32 new_value, u32 old_value);
|
|
|
|
///////////////////////////////////////
|
|
// Network Access
|
|
|
|
// TODO(PS):
|
|
|
|
struct Platform_Socket_Handle
|
|
{
|
|
u64 value;
|
|
};
|
|
|
|
Platform_Socket_Handle platform_socket_create();
|
|
bool platform_socket_bind();
|
|
bool platform_socket_connect();
|
|
bool platform_socket_close();
|
|
Data platform_socket_recv();
|
|
s32 platform_Socket_set_listening();
|
|
s32 platform_Socket_send();
|
|
s32 platform_Socket_send_to();
|
|
s32 platform_Socket_set_opt();
|
|
|
|
///////////////////////////////////////
|
|
// Graphics Integration
|
|
|
|
#define PLATFORM_SHADER_MAX_ATTRS 8
|
|
#define PLATFORM_SHADER_ATTR_LAST (u32)(1 << 31)
|
|
struct Platform_Shader
|
|
{
|
|
u32 id;
|
|
u32 attrs[PLATFORM_SHADER_MAX_ATTRS];
|
|
u32 uniforms[PLATFORM_SHADER_MAX_ATTRS];
|
|
};
|
|
|
|
struct Platform_Geometry_Buffer
|
|
{
|
|
u32 buffer_id_vao;
|
|
u32 buffer_id_vertices;
|
|
u32 buffer_id_indices;
|
|
u32 vertices_len;
|
|
u32 indices_len;
|
|
};
|
|
|
|
struct Platform_Texture
|
|
{
|
|
u32 id;
|
|
|
|
u32 w, h, s;
|
|
};
|
|
|
|
struct Platform_Graphics_Frame_Desc
|
|
{
|
|
v4 clear_color;
|
|
v2 viewport_min;
|
|
v2 viewport_max;
|
|
};
|
|
|
|
void platform_frame_begin(Platform_Graphics_Frame_Desc desc);
|
|
void platform_frame_clear();
|
|
|
|
// Geometry
|
|
Platform_Geometry_Buffer platform_geometry_buffer_create(r32* vertices, u32 vertices_len, u32* indices, u32 indices_len);
|
|
Platform_Shader platform_shader_create(
|
|
String code_vert, String code_frag, String* attribs, u32 attribs_len, String* uniforms, u32 uniforms_len
|
|
);
|
|
void platform_geometry_buffer_update(Platform_Geometry_Buffer* buffer, r32* verts, u32 verts_offset, u32 verts_len, u32* indices, u32 indices_offset, u32 indices_len);
|
|
|
|
// Shaders
|
|
void platform_geometry_bind(Platform_Geometry_Buffer geo);
|
|
void platform_shader_bind(Platform_Shader shader);
|
|
void platform_geometry_draw(Platform_Geometry_Buffer geo, u32 indices);
|
|
void platform_geometry_draw(Platform_Geometry_Buffer geo);
|
|
void platform_vertex_attrib_pointer(
|
|
Platform_Geometry_Buffer geo, Platform_Shader shader, u32 count, u32 attr_index, u32 stride, u32 offset
|
|
);
|
|
void platform_set_uniform(Platform_Shader shader, u32 index, m44 u);
|
|
|
|
// Textures
|
|
Platform_Texture platform_texture_create(u8* pixels, u32 width, u32 height, u32 stride);
|
|
void platform_texture_bind(Platform_Texture tex);
|
|
void platform_texture_update(Platform_Texture tex, u8* new_pixels, u32 width, u32 height, u32 stride);
|
|
|
|
#endif //LUMENARIUM_PLATFORM_H
|