renders
This commit is contained in:
parent
2a856634d0
commit
21625b646b
|
@ -100,6 +100,13 @@
|
|||
#define LINUX_FN_DEBUG(fmt, ...) do { \
|
||||
fprintf(stderr, "%s: " fmt "\n", __func__, ##__VA_ARGS__);\
|
||||
} while (0)
|
||||
|
||||
// I want to see a message
|
||||
#undef AssertBreak
|
||||
#define AssertBreak(m) ({\
|
||||
fprintf(stderr, "\n** ASSERTION FAILURE: %s:%d: %s\n\n", __FILE__, __LINE__, #m);\
|
||||
*((volatile u64*)0) = 0xba771e70ad5;\
|
||||
})
|
||||
#else
|
||||
#define LINUX_FN_DEBUG(...)
|
||||
#endif
|
||||
|
@ -107,6 +114,9 @@
|
|||
////////////////////////////
|
||||
|
||||
struct Linux_Vars {
|
||||
Thread_Context tctx;
|
||||
Arena *frame_arena;
|
||||
|
||||
Display* dpy;
|
||||
Window win;
|
||||
|
||||
|
@ -131,8 +141,6 @@ struct Linux_Vars {
|
|||
Node free_linux_objects;
|
||||
Node timer_objects;
|
||||
|
||||
Thread_Context tctx;
|
||||
|
||||
System_Mutex global_frame_mutex;
|
||||
|
||||
Arena clipboard_out_arena;
|
||||
|
@ -216,22 +224,31 @@ handle_to_object(Plat_Handle ph){
|
|||
internal Linux_Object*
|
||||
linux_alloc_object(Linux_Object_Kind kind){
|
||||
Linux_Object* result = NULL;
|
||||
|
||||
if (linuxvars.free_linux_objects.next != &linuxvars.free_linux_objects) {
|
||||
result = CastFromMember(Linux_Object, node, linuxvars.free_linux_objects.next);
|
||||
}
|
||||
|
||||
if (result == NULL) {
|
||||
i32 count = 512;
|
||||
|
||||
Linux_Object* objects = (Linux_Object*)system_memory_allocate(
|
||||
sizeof(Linux_Object), file_name_line_number_lit_u8);
|
||||
sizeof(Linux_Object) * count,
|
||||
file_name_line_number_lit_u8
|
||||
);
|
||||
|
||||
objects[0].node.prev = &linuxvars.free_linux_objects;
|
||||
linuxvars.free_linux_objects.next = &objects[0].node;
|
||||
for (i32 i = 1; i < count; ++i) {
|
||||
objects[i - 1].node.next = &objects[i].node;
|
||||
objects[i].node.prev = &objects[i - 1].node;
|
||||
}
|
||||
objects[count - 1].node.next = &linuxvars.free_linux_objects;
|
||||
linuxvars.free_linux_objects.prev = &objects[count - 1].node;
|
||||
|
||||
result = CastFromMember(Linux_Object, node, linuxvars.free_linux_objects.next);
|
||||
}
|
||||
|
||||
Assert(result != 0);
|
||||
dll_remove(&result->node);
|
||||
block_zero_struct(result);
|
||||
|
@ -462,6 +479,15 @@ graphics_fill_texture_sig(){
|
|||
internal
|
||||
font_make_face_sig() {
|
||||
Face* result = ft__font_make_face(arena, description, scale_factor);
|
||||
|
||||
if(!result) {
|
||||
// is this fatal? 4ed.cpp:277 (caller) does not check for null.
|
||||
String_Const_u8 s = description->font.file_name;
|
||||
char msg[4096];
|
||||
snprintf(msg, sizeof(msg), "Unable to load font: %.*s", (int)s.size, s.str);
|
||||
system_error_box(msg);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
|
@ -469,17 +495,123 @@ font_make_face_sig() {
|
|||
|
||||
internal b32
|
||||
glx_init(void) {
|
||||
int glx_maj, glx_min;
|
||||
|
||||
if(!glXQueryVersion(linuxvars.dpy, &glx_maj, &glx_min)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return glx_maj > 1 || (glx_maj == 1 && glx_min >= 3);
|
||||
}
|
||||
|
||||
internal b32
|
||||
glx_get_config(GLXFBConfig* fb_config, XVisualInfo* vi) {
|
||||
|
||||
static const int attrs[] = {
|
||||
GLX_X_RENDERABLE , True,
|
||||
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
|
||||
GLX_RENDER_TYPE , GLX_RGBA_BIT,
|
||||
GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR,
|
||||
GLX_RED_SIZE , 8,
|
||||
GLX_GREEN_SIZE , 8,
|
||||
GLX_BLUE_SIZE , 8,
|
||||
GLX_ALPHA_SIZE , 8,
|
||||
GLX_DEPTH_SIZE , 24,
|
||||
GLX_STENCIL_SIZE , 8,
|
||||
GLX_DOUBLEBUFFER , True,
|
||||
None
|
||||
};
|
||||
|
||||
int conf_count = 0;
|
||||
GLXFBConfig* conf_list = glXChooseFBConfig(linuxvars.dpy, DefaultScreen(linuxvars.dpy), attrs, &conf_count);
|
||||
if(!conf_count || conf_count <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*fb_config = *conf_list;
|
||||
XFree(conf_list);
|
||||
|
||||
XVisualInfo* xvi = glXGetVisualFromFBConfig(linuxvars.dpy, *fb_config);
|
||||
if(!xvi) {
|
||||
return false;
|
||||
}
|
||||
|
||||
*vi = *xvi;
|
||||
XFree(xvi);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
internal b32 glx_ctx_error;
|
||||
|
||||
internal int
|
||||
glx_error_handler(Display* dpy, XErrorEvent* ev){
|
||||
glx_ctx_error = true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
typedef GLXContext (glXCreateContextAttribsARB_Function)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
|
||||
typedef void (glXSwapIntervalEXT_Function) (Display *dpy, GLXDrawable drawable, int interval);
|
||||
typedef int (glXSwapIntervalMESA_Function) (unsigned int interval);
|
||||
typedef int (glXGetSwapIntervalMESA_Function) (void);
|
||||
typedef int (glXSwapIntervalSGI_Function) (int interval);
|
||||
|
||||
internal b32
|
||||
glx_create_context(GLXFBConfig* fb_config){
|
||||
glx_create_context(GLXFBConfig fb_config){
|
||||
const char *glx_exts = glXQueryExtensionsString(linuxvars.dpy, DefaultScreen(linuxvars.dpy));
|
||||
|
||||
glXCreateContextAttribsARB_Function *glXCreateContextAttribsARB = 0;
|
||||
glXSwapIntervalEXT_Function *glXSwapIntervalEXT = 0;
|
||||
glXSwapIntervalMESA_Function *glXSwapIntervalMESA = 0;
|
||||
glXGetSwapIntervalMESA_Function *glXGetSwapIntervalMESA = 0;
|
||||
glXSwapIntervalSGI_Function *glXSwapIntervalSGI = 0;
|
||||
|
||||
#define GLXLOAD(f) f = (f##_Function*) glXGetProcAddressARB((const GLubyte*) #f);
|
||||
GLXLOAD(glXCreateContextAttribsARB);
|
||||
|
||||
GLXContext ctx = NULL;
|
||||
int (*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(&glx_error_handler);
|
||||
|
||||
if (glXCreateContextAttribsARB == NULL){
|
||||
//LOG("glXCreateContextAttribsARB() not found, using old-style GLX context\n" );
|
||||
ctx = glXCreateNewContext(linuxvars.dpy, fb_config, GLX_RGBA_TYPE, 0, True);
|
||||
} else {
|
||||
static const int context_attribs[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, 2,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, 1,
|
||||
GLX_CONTEXT_PROFILE_MASK_ARB , GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
|
||||
#if defined(FRED_INTERNAL)
|
||||
GLX_CONTEXT_FLAGS_ARB , GLX_CONTEXT_DEBUG_BIT_ARB,
|
||||
#endif
|
||||
None
|
||||
};
|
||||
|
||||
//LOG("Creating GL 2.1 context... ");
|
||||
ctx = glXCreateContextAttribsARB(linuxvars.dpy, fb_config, 0, True, context_attribs);
|
||||
}
|
||||
|
||||
XSync(linuxvars.dpy, False);
|
||||
if(glx_ctx_error || !ctx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
XSync(linuxvars.dpy, False);
|
||||
XSetErrorHandler(old_handler);
|
||||
|
||||
//b32 direct = glXIsDirect(linuxvars.dpy, ctx);
|
||||
|
||||
//LOG("Making context current\n");
|
||||
glXMakeCurrent(linuxvars.dpy, linuxvars.win, ctx);
|
||||
|
||||
//glx_enable_vsync();
|
||||
|
||||
// NOTE(allen): Load gl functions
|
||||
#define GL_FUNC(f,R,P) GLXLOAD(f)
|
||||
#include "opengl/4ed_opengl_funcs.h"
|
||||
|
||||
#undef GLXLOAD
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////
|
||||
|
@ -513,8 +645,7 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
|
|||
#undef LOAD_ATOM
|
||||
|
||||
if (!glx_init()){
|
||||
//system_error_box("Your XServer's GLX version is too old. GLX 1.3+ is required.");
|
||||
system_error_box("TODO: Everything.");
|
||||
system_error_box("Your XServer's GLX version is too old. GLX 1.3+ is required.");
|
||||
}
|
||||
|
||||
GLXFBConfig fb_config;
|
||||
|
@ -529,6 +660,10 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
|
|||
int w = WINDOW_W_DEFAULT;
|
||||
int h = WINDOW_H_DEFAULT;
|
||||
|
||||
// TEMP
|
||||
render_target.width = w;
|
||||
render_target.height = h;
|
||||
|
||||
XSetWindowAttributes swa = {};
|
||||
swa.backing_store = WhenMapped;
|
||||
swa.event_mask = StructureNotifyMask;
|
||||
|
@ -593,7 +728,7 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
|
|||
// NOTE(inso): make the window visible
|
||||
XMapWindow(linuxvars.dpy, linuxvars.win);
|
||||
|
||||
if(!glx_create_context(&fb_config)) {
|
||||
if(!glx_create_context(fb_config)) {
|
||||
system_error_box("Unable to create GLX context.");
|
||||
}
|
||||
|
||||
|
@ -659,30 +794,35 @@ linux_x11_init(int argc, char** argv, Plat_Settings* settings) {
|
|||
}
|
||||
|
||||
XIMStyles *styles = NULL;
|
||||
XIMStyle got_style = None;
|
||||
const XIMStyle style_want = (XIMPreeditNothing | XIMStatusNothing);
|
||||
b32 found_style = false;
|
||||
|
||||
if (!XGetIMValues(linuxvars.xim, XNQueryInputStyle, &styles, NULL) && styles){
|
||||
for (i32 i = 0; i < styles->count_styles; ++i){
|
||||
XIMStyle style = styles->supported_styles[i];
|
||||
if (style == (XIMPreeditNothing | XIMStatusNothing)){
|
||||
got_style = true;
|
||||
if (style == style_want) {
|
||||
found_style = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(got_style == None) {
|
||||
if(!found_style) {
|
||||
system_error_box("Could not find supported X Input style.");
|
||||
}
|
||||
|
||||
XFree(styles);
|
||||
|
||||
linuxvars.xic = XCreateIC(linuxvars.xim,
|
||||
XNInputStyle, got_style,
|
||||
XNInputStyle, style_want,
|
||||
XNClientWindow, linuxvars.win,
|
||||
XNFocusWindow, linuxvars.win,
|
||||
NULL);
|
||||
|
||||
if(!linuxvars.xic) {
|
||||
system_error_box("Error creating X Input context.");
|
||||
}
|
||||
|
||||
int xim_event_mask;
|
||||
if (XGetICValues(linuxvars.xic, XNFilterEvents, &xim_event_mask, NULL)){
|
||||
xim_event_mask = 0;
|
||||
|
@ -779,9 +919,9 @@ main(int argc, char **argv){
|
|||
font_api_fill_vtable(&font_vtable);
|
||||
|
||||
// NOTE(allen): memory
|
||||
//win32vars.frame_arena = reserve_arena(win32vars.tctx);
|
||||
linuxvars.frame_arena = reserve_arena(&linuxvars.tctx);
|
||||
// TODO(allen): *arena;
|
||||
//target.arena = make_arena_system(KB(256));
|
||||
render_target.arena = make_arena_system(KB(256));
|
||||
|
||||
linuxvars.cursor_show = MouseCursorShow_Always;
|
||||
linuxvars.prev_cursor_show = MouseCursorShow_Always;
|
||||
|
@ -822,6 +962,8 @@ main(int argc, char **argv){
|
|||
|
||||
// NOTE(allen): send system vtable to core
|
||||
app.load_vtables(&system_vtable, &font_vtable, &graphics_vtable);
|
||||
// get_logger calls log_init which is needed.
|
||||
app.get_logger();
|
||||
//linuxvars.log_string = app.get_logger();
|
||||
|
||||
// NOTE(allen): init & command line parameters
|
||||
|
@ -942,7 +1084,7 @@ main(int argc, char **argv){
|
|||
{
|
||||
Scratch_Block scratch(&linuxvars.tctx, Scratch_Share);
|
||||
String_Const_u8 curdir = system_get_path(scratch, SystemPath_CurrentDirectory);
|
||||
//app.init(&linuxvars.tctx, &render_target, base_ptr, linuxvars.clipboard_contents, curdir, custom);
|
||||
app.init(&linuxvars.tctx, &render_target, base_ptr, linuxvars.clipboard_contents, curdir, custom);
|
||||
}
|
||||
|
||||
linuxvars.global_frame_mutex = system_mutex_make();
|
||||
|
@ -1031,6 +1173,9 @@ main(int argc, char **argv){
|
|||
linuxvars.cursor = result.mouse_cursor_type;
|
||||
}
|
||||
|
||||
gl_render(&render_target);
|
||||
glXSwapBuffers(linuxvars.dpy, linuxvars.win);
|
||||
|
||||
first_step = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ system_get_path(Arena* arena, System_Path_Code path_code){
|
|||
|
||||
internal String_Const_u8
|
||||
system_get_canonical(Arena* arena, String_Const_u8 name){
|
||||
LINUX_FN_DEBUG("%.*s", (int)name.size, name.str);
|
||||
// TODO(andrew): Resolve symlinks ?
|
||||
// TODO(andrew): Resolve . and .. in paths
|
||||
// TODO(andrew): Use realpath(3)
|
||||
|
@ -61,6 +62,7 @@ system_get_canonical(Arena* arena, String_Const_u8 name){
|
|||
|
||||
internal File_List
|
||||
system_get_file_list(Arena* arena, String_Const_u8 directory){
|
||||
LINUX_FN_DEBUG("%.*s", (int)directory.size, directory.str);
|
||||
File_List result = {};
|
||||
String_Const_u8 search_pattern = {};
|
||||
|
||||
|
@ -103,6 +105,7 @@ system_get_file_list(Arena* arena, String_Const_u8 directory){
|
|||
|
||||
internal File_Attributes
|
||||
system_quick_file_attributes(Arena* scratch, String_Const_u8 file_name){
|
||||
LINUX_FN_DEBUG("%.*s", (int)file_name.size, file_name.str);
|
||||
struct stat file_stat;
|
||||
stat((const char*)file_name.str, &file_stat);
|
||||
return linux_file_attributes_from_struct_stat(file_stat);
|
||||
|
@ -110,6 +113,7 @@ system_quick_file_attributes(Arena* scratch, String_Const_u8 file_name){
|
|||
|
||||
internal b32
|
||||
system_load_handle(Arena* scratch, char* file_name, Plat_Handle* out){
|
||||
LINUX_FN_DEBUG("%s", file_name);
|
||||
int fd = open(file_name, O_RDONLY);
|
||||
if (fd != -1) {
|
||||
*(int*)out = fd;
|
||||
|
@ -120,6 +124,7 @@ system_load_handle(Arena* scratch, char* file_name, Plat_Handle* out){
|
|||
|
||||
internal File_Attributes
|
||||
system_load_attributes(Plat_Handle handle){
|
||||
LINUX_FN_DEBUG();
|
||||
struct stat file_stat;
|
||||
fstat(*(int*)&handle, &file_stat);
|
||||
return linux_file_attributes_from_struct_stat(file_stat);
|
||||
|
@ -127,6 +132,7 @@ system_load_attributes(Plat_Handle handle){
|
|||
|
||||
internal b32
|
||||
system_load_file(Plat_Handle handle, char* buffer, u32 size){
|
||||
LINUX_FN_DEBUG("%.*s", size, buffer);
|
||||
int fd = *(int*)&handle;
|
||||
int bytes_read = read(fd, buffer, size);
|
||||
if (bytes_read == size) {
|
||||
|
@ -137,12 +143,14 @@ system_load_file(Plat_Handle handle, char* buffer, u32 size){
|
|||
|
||||
internal b32
|
||||
system_load_close(Plat_Handle handle){
|
||||
LINUX_FN_DEBUG();
|
||||
int fd = *(int*)&handle;
|
||||
return close(fd) == 0;
|
||||
}
|
||||
|
||||
internal File_Attributes
|
||||
system_save_file(Arena* scratch, char* file_name, String_Const_u8 data){
|
||||
LINUX_FN_DEBUG("%s", file_name);
|
||||
File_Attributes result = {};
|
||||
int fd = open(file_name, O_WRONLY, O_CREAT);
|
||||
if (fd != -1) {
|
||||
|
@ -158,6 +166,7 @@ system_save_file(Arena* scratch, char* file_name, String_Const_u8 data){
|
|||
|
||||
internal b32
|
||||
system_load_library(Arena* scratch, String_Const_u8 file_name, System_Library* out){
|
||||
LINUX_FN_DEBUG("%.*s", (int)file_name.size, file_name.str);
|
||||
void* library = dlopen((const char*)file_name.str, RTLD_LAZY);
|
||||
if (library != NULL) {
|
||||
*(void**)out = library;
|
||||
|
@ -168,16 +177,19 @@ system_load_library(Arena* scratch, String_Const_u8 file_name, System_Library* o
|
|||
|
||||
internal b32
|
||||
system_release_library(System_Library handle){
|
||||
LINUX_FN_DEBUG();
|
||||
return dlclose(*(void**)&handle) == 0;
|
||||
}
|
||||
|
||||
internal Void_Func*
|
||||
system_get_proc(System_Library handle, char* proc_name){
|
||||
LINUX_FN_DEBUG("%s", proc_name);
|
||||
return (Void_Func*)dlsym(*(void**)&handle, proc_name);
|
||||
}
|
||||
|
||||
internal u64
|
||||
system_now_time(void){
|
||||
LINUX_FN_DEBUG();
|
||||
struct timespec time;
|
||||
clock_gettime(CLOCK_MONOTONIC_RAW, &time);
|
||||
return linux_u64_from_timespec(time);
|
||||
|
@ -185,6 +197,7 @@ system_now_time(void){
|
|||
|
||||
internal Plat_Handle
|
||||
system_wake_up_timer_create(void){
|
||||
LINUX_FN_DEBUG();
|
||||
Linux_Object* object = linux_alloc_object(LinuxObjectKind_Timer);
|
||||
dll_insert(&linuxvars.timer_objects, &object->node);
|
||||
|
||||
|
@ -194,6 +207,7 @@ system_wake_up_timer_create(void){
|
|||
|
||||
internal void
|
||||
system_wake_up_timer_release(Plat_Handle handle){
|
||||
LINUX_FN_DEBUG();
|
||||
Linux_Object* object = handle_to_object(handle);
|
||||
if (object->kind == LinuxObjectKind_Timer){
|
||||
if(object->timer.fd != -1) {
|
||||
|
@ -207,6 +221,7 @@ system_wake_up_timer_release(Plat_Handle handle){
|
|||
|
||||
internal void
|
||||
system_wake_up_timer_set(Plat_Handle handle, u32 time_milliseconds){
|
||||
LINUX_FN_DEBUG("%d", time_milliseconds);
|
||||
Linux_Object* object = handle_to_object(handle);
|
||||
|
||||
if (object->kind == LinuxObjectKind_Timer){
|
||||
|
@ -229,11 +244,13 @@ system_wake_up_timer_set(Plat_Handle handle, u32 time_milliseconds){
|
|||
|
||||
internal void
|
||||
system_signal_step(u32 code){
|
||||
LINUX_FN_DEBUG("%d", code);
|
||||
linux_schedule_step();
|
||||
}
|
||||
|
||||
internal void
|
||||
system_sleep(u64 microseconds){
|
||||
LINUX_FN_DEBUG("%" PRIu64, microseconds);
|
||||
struct timespec requested;
|
||||
struct timespec remaining;
|
||||
u64 seconds = microseconds / Million(1);
|
||||
|
@ -244,6 +261,7 @@ system_sleep(u64 microseconds){
|
|||
|
||||
internal void
|
||||
system_post_clipboard(String_Const_u8 str){
|
||||
LINUX_FN_DEBUG("%.*s", (int)str.size, str.str);
|
||||
linalloc_clear(&linuxvars.clipboard_out_arena);
|
||||
char* p = push_array(&linuxvars.clipboard_out_arena, char, str.size + 1);
|
||||
block_copy(p, str.data, str.size);
|
||||
|
@ -253,6 +271,7 @@ system_post_clipboard(String_Const_u8 str){
|
|||
|
||||
internal b32
|
||||
system_cli_call(Arena* scratch, char* path, char* script, CLI_Handles* cli_out){
|
||||
LINUX_FN_DEBUG("%s / %s", path, script);
|
||||
int pipe_fds[2];
|
||||
if (pipe(pipe_fds) == -1){
|
||||
perror("system_cli_call: pipe");
|
||||
|
@ -304,10 +323,12 @@ system_cli_call(Arena* scratch, char* path, char* script, CLI_Handles* cli_out){
|
|||
internal void
|
||||
system_cli_begin_update(CLI_Handles* cli){
|
||||
// NOTE(inso): I don't think anything needs to be done here.
|
||||
LINUX_FN_DEBUG();
|
||||
}
|
||||
|
||||
internal b32
|
||||
system_cli_update_step(CLI_Handles* cli, char* dest, u32 max, u32* amount){
|
||||
LINUX_FN_DEBUG();
|
||||
int pipe_read_fd = *(int*)&cli->out_read;
|
||||
|
||||
fd_set fds;
|
||||
|
@ -338,6 +359,7 @@ system_cli_update_step(CLI_Handles* cli, char* dest, u32 max, u32* amount){
|
|||
|
||||
internal b32
|
||||
system_cli_end_update(CLI_Handles* cli){
|
||||
LINUX_FN_DEBUG();
|
||||
pid_t pid = *(pid_t*)&cli->proc;
|
||||
b32 close_me = false;
|
||||
|
||||
|
@ -359,10 +381,12 @@ system_cli_end_update(CLI_Handles* cli){
|
|||
internal void
|
||||
system_open_color_picker(Color_Picker* picker){
|
||||
// TODO?
|
||||
LINUX_FN_DEBUG();
|
||||
}
|
||||
|
||||
internal f32
|
||||
system_get_screen_scale_factor(void){
|
||||
LINUX_FN_DEBUG();
|
||||
// TODO: correct screen number somehow
|
||||
int dpi = linux_get_xsettings_dpi(linuxvars.dpy, 0);
|
||||
if(dpi == -1){
|
||||
|
@ -380,6 +404,7 @@ system_get_screen_scale_factor(void){
|
|||
|
||||
internal System_Thread
|
||||
system_thread_launch(Thread_Function* proc, void* ptr){
|
||||
LINUX_FN_DEBUG();
|
||||
System_Thread result = {};
|
||||
|
||||
Linux_Object* thread_info = linux_alloc_object(LinuxObjectKind_Thread);
|
||||
|
@ -408,6 +433,7 @@ system_thread_launch(Thread_Function* proc, void* ptr){
|
|||
|
||||
internal void
|
||||
system_thread_join(System_Thread thread){
|
||||
LINUX_FN_DEBUG();
|
||||
Linux_Object* object = *(Linux_Object**)&thread;
|
||||
void* retval_ignored;
|
||||
int result = pthread_join(object->thread.pthread, &retval_ignored);
|
||||
|
@ -415,6 +441,7 @@ system_thread_join(System_Thread thread){
|
|||
|
||||
internal void
|
||||
system_thread_free(System_Thread thread){
|
||||
LINUX_FN_DEBUG();
|
||||
Linux_Object* object = *(Linux_Object**)&thread;
|
||||
Assert(object->kind == LinuxObjectKind_Thread);
|
||||
linux_free_object(object);
|
||||
|
@ -422,13 +449,18 @@ system_thread_free(System_Thread thread){
|
|||
|
||||
internal i32
|
||||
system_thread_get_id(void){
|
||||
LINUX_FN_DEBUG();
|
||||
pthread_t tid = pthread_self();
|
||||
Assert(tid <= (u64)max_i32);
|
||||
return (i32)tid;
|
||||
|
||||
// WELP hope it doesn't collide
|
||||
i32 shorter_id = ((u64)tid >> 32) ^ ((u32)tid & bitmask_32);
|
||||
|
||||
return shorter_id;
|
||||
}
|
||||
|
||||
internal void
|
||||
system_acquire_global_frame_mutex(Thread_Context* tctx){
|
||||
LINUX_FN_DEBUG();
|
||||
if (tctx->kind == ThreadKind_AsyncTasks){
|
||||
system_mutex_acquire(linuxvars.global_frame_mutex);
|
||||
}
|
||||
|
@ -436,6 +468,7 @@ system_acquire_global_frame_mutex(Thread_Context* tctx){
|
|||
|
||||
internal void
|
||||
system_release_global_frame_mutex(Thread_Context* tctx){
|
||||
LINUX_FN_DEBUG();
|
||||
if (tctx->kind == ThreadKind_AsyncTasks){
|
||||
system_mutex_release(linuxvars.global_frame_mutex);
|
||||
}
|
||||
|
@ -447,12 +480,14 @@ system_mutex_make(void){
|
|||
Linux_Object* object = linux_alloc_object(LinuxObjectKind_Mutex);
|
||||
pthread_mutex_init(&object->mutex, NULL);
|
||||
*(Linux_Object**)&result = object;
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal void
|
||||
system_mutex_acquire(System_Mutex mutex){
|
||||
Linux_Object* object = *(Linux_Object**)&mutex;
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
Assert(object->kind == LinuxObjectKind_Mutex);
|
||||
pthread_mutex_lock(&object->mutex);
|
||||
}
|
||||
|
@ -460,6 +495,7 @@ system_mutex_acquire(System_Mutex mutex){
|
|||
internal void
|
||||
system_mutex_release(System_Mutex mutex){
|
||||
Linux_Object* object = *(Linux_Object**)&mutex;
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
Assert(object->kind == LinuxObjectKind_Mutex);
|
||||
pthread_mutex_unlock(&object->mutex);
|
||||
}
|
||||
|
@ -467,6 +503,7 @@ system_mutex_release(System_Mutex mutex){
|
|||
internal void
|
||||
system_mutex_free(System_Mutex mutex){
|
||||
Linux_Object* object = *(Linux_Object**)&mutex;
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
Assert(object->kind == LinuxObjectKind_Mutex);
|
||||
pthread_mutex_destroy(&object->mutex);
|
||||
linux_free_object(object);
|
||||
|
@ -476,6 +513,7 @@ internal System_Condition_Variable
|
|||
system_condition_variable_make(void){
|
||||
System_Condition_Variable result = {};
|
||||
Linux_Object* object = linux_alloc_object(LinuxObjectKind_ConditionVariable);
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
pthread_cond_init(&object->condition_variable, NULL);
|
||||
*(Linux_Object**)&result = object;
|
||||
return result;
|
||||
|
@ -485,6 +523,7 @@ internal void
|
|||
system_condition_variable_wait(System_Condition_Variable cv, System_Mutex mutex){
|
||||
Linux_Object* cv_object = *(Linux_Object**)&cv;
|
||||
Linux_Object* mutex_object = *(Linux_Object**)&mutex;
|
||||
LINUX_FN_DEBUG("%p / %p", cv_object, mutex_object);
|
||||
Assert(cv_object->kind == LinuxObjectKind_ConditionVariable);
|
||||
Assert(mutex_object->kind == LinuxObjectKind_Mutex);
|
||||
pthread_cond_wait(&cv_object->condition_variable, &mutex_object->mutex);
|
||||
|
@ -493,6 +532,7 @@ system_condition_variable_wait(System_Condition_Variable cv, System_Mutex mutex)
|
|||
internal void
|
||||
system_condition_variable_signal(System_Condition_Variable cv){
|
||||
Linux_Object* object = *(Linux_Object**)&cv;
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
Assert(object->kind == LinuxObjectKind_ConditionVariable);
|
||||
pthread_cond_signal(&object->condition_variable);
|
||||
}
|
||||
|
@ -500,6 +540,7 @@ system_condition_variable_signal(System_Condition_Variable cv){
|
|||
internal void
|
||||
system_condition_variable_free(System_Condition_Variable cv){
|
||||
Linux_Object* object = *(Linux_Object**)&cv;
|
||||
LINUX_FN_DEBUG("%p", object);
|
||||
Assert(object->kind == LinuxObjectKind_ConditionVariable);
|
||||
pthread_cond_destroy(&object->condition_variable);
|
||||
linux_free_object(object);
|
||||
|
@ -507,14 +548,17 @@ system_condition_variable_free(System_Condition_Variable cv){
|
|||
|
||||
internal void*
|
||||
system_memory_allocate(u64 size, String_Const_u8 location){
|
||||
|
||||
void* result = mmap(
|
||||
NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
// TODO(andrew): Allocation tracking?
|
||||
LINUX_FN_DEBUG("%" PRIu64 ", %.*s %p", size, (int)location.size, location.str, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
internal b32
|
||||
system_memory_set_protection(void* ptr, u64 size, u32 flags){
|
||||
LINUX_FN_DEBUG("%p / %ld / %d", ptr, size, flags);
|
||||
int protect = 0;
|
||||
MovFlag(flags, MemProtect_Read, protect, PROT_READ);
|
||||
MovFlag(flags, MemProtect_Write, protect, PROT_WRITE);
|
||||
|
@ -525,16 +569,20 @@ system_memory_set_protection(void* ptr, u64 size, u32 flags){
|
|||
|
||||
internal void
|
||||
system_memory_free(void* ptr, u64 size){
|
||||
LINUX_FN_DEBUG("%p / %ld", ptr, size);
|
||||
munmap(ptr, size);
|
||||
}
|
||||
|
||||
internal Memory_Annotation
|
||||
system_memory_annotation(Arena* arena){
|
||||
LINUX_FN_DEBUG();
|
||||
// TODO;
|
||||
}
|
||||
|
||||
internal void
|
||||
system_show_mouse_cursor(i32 show){
|
||||
LINUX_FN_DEBUG("%d", show);
|
||||
|
||||
linuxvars.cursor_show = show;
|
||||
|
||||
XDefineCursor(
|
||||
|
@ -545,17 +593,21 @@ system_show_mouse_cursor(i32 show){
|
|||
|
||||
internal b32
|
||||
system_set_fullscreen(b32 full_screen){
|
||||
LINUX_FN_DEBUG("%d", full_screen);
|
||||
|
||||
linuxvars.should_be_full_screen = full_screen;
|
||||
return true;
|
||||
}
|
||||
|
||||
internal b32
|
||||
system_is_fullscreen(void){
|
||||
LINUX_FN_DEBUG();
|
||||
return linuxvars.is_full_screen;
|
||||
}
|
||||
|
||||
internal Input_Modifier_Set
|
||||
system_get_keyboard_modifiers(Arena* arena){
|
||||
LINUX_FN_DEBUG();
|
||||
// TODO:
|
||||
//return(copy_modifier_set(arena, &linuxvars.input_chunk.pers.modifiers));
|
||||
}
|
||||
|
|
|
@ -76,13 +76,12 @@ system_error_box(char *msg, b32 shutdown = true){
|
|||
|
||||
int button_trigger = 0;
|
||||
int button_hi = 0;
|
||||
int redraw = 1;
|
||||
|
||||
XEvent ev;
|
||||
while (1){
|
||||
XNextEvent(dpy, &ev);
|
||||
|
||||
int redraw = 0;
|
||||
|
||||
if (ev.type == Expose) redraw = 1;
|
||||
|
||||
if (ev.type == ConfigureNotify){
|
||||
|
@ -137,6 +136,7 @@ system_error_box(char *msg, b32 shutdown = true){
|
|||
XDrawString(dpy, w, gc1, (x) , (y) , (str), (len))
|
||||
|
||||
if (redraw){
|
||||
redraw = 0;
|
||||
XClearWindow(dpy, w);
|
||||
|
||||
const char* line_start = msg;
|
||||
|
|
Loading…
Reference in New Issue