switched app.step over to a big input struct so that the signature does not have to change if I want to pass in more parameters in the future
parent
c56703cbc8
commit
93a1d3931f
82
4ed.cpp
82
4ed.cpp
|
@ -3631,51 +3631,53 @@ consume_input(Available_Input *available, i32 input_type){
|
||||||
App_Step_Sig(app_step){
|
App_Step_Sig(app_step){
|
||||||
Application_Step_Result app_result = *result;
|
Application_Step_Result app_result = *result;
|
||||||
app_result.animating = 0;
|
app_result.animating = 0;
|
||||||
|
|
||||||
App_Vars *vars = (App_Vars*)memory->vars_memory;
|
App_Vars *vars = (App_Vars*)memory->vars_memory;
|
||||||
Models *models = &vars->models;
|
Models *models = &vars->models;
|
||||||
target->partition = &models->mem.part;
|
target->partition = &models->mem.part;
|
||||||
|
|
||||||
// NOTE(allen): OS clipboard event handling
|
// NOTE(allen): OS clipboard event handling
|
||||||
|
String clipboard = input->clipboard;
|
||||||
|
|
||||||
if (clipboard.str){
|
if (clipboard.str){
|
||||||
String *dest = working_set_next_clipboard_string(&models->mem.general, &models->working_set, clipboard.size);
|
String *dest = working_set_next_clipboard_string(&models->mem.general, &models->working_set, clipboard.size);
|
||||||
dest->size = eol_convert_in(dest->str, clipboard.str, clipboard.size);
|
dest->size = eol_convert_in(dest->str, clipboard.str, clipboard.size);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): check files are up to date
|
// NOTE(allen): check files are up to date
|
||||||
{
|
{
|
||||||
File_Node *node, *used_nodes;
|
File_Node *node, *used_nodes;
|
||||||
Editing_File *file;
|
Editing_File *file;
|
||||||
u64 time_stamp;
|
u64 time_stamp;
|
||||||
|
|
||||||
used_nodes = &models->working_set.used_sentinel;
|
used_nodes = &models->working_set.used_sentinel;
|
||||||
for (dll_items(node, used_nodes)){
|
for (dll_items(node, used_nodes)){
|
||||||
file = (Editing_File*)node;
|
file = (Editing_File*)node;
|
||||||
|
|
||||||
time_stamp = system->file_time_stamp(make_c_str(file->name.source_path));
|
time_stamp = system->file_time_stamp(make_c_str(file->name.source_path));
|
||||||
|
|
||||||
if (time_stamp > 0){
|
if (time_stamp > 0){
|
||||||
file->state.last_sys_write_time = time_stamp;
|
file->state.last_sys_write_time = time_stamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): reorganizing panels on screen
|
// NOTE(allen): reorganizing panels on screen
|
||||||
{
|
{
|
||||||
i32 prev_width = models->layout.full_width;
|
i32 prev_width = models->layout.full_width;
|
||||||
i32 prev_height = models->layout.full_height;
|
i32 prev_height = models->layout.full_height;
|
||||||
i32 current_width = target->width;
|
i32 current_width = target->width;
|
||||||
i32 current_height = target->height;
|
i32 current_height = target->height;
|
||||||
|
|
||||||
Panel *panel, *used_panels;
|
Panel *panel, *used_panels;
|
||||||
View *view;
|
View *view;
|
||||||
|
|
||||||
models->layout.full_width = current_width;
|
models->layout.full_width = current_width;
|
||||||
models->layout.full_height = current_height;
|
models->layout.full_height = current_height;
|
||||||
|
|
||||||
if (prev_width != current_width || prev_height != current_height){
|
if (prev_width != current_width || prev_height != current_height){
|
||||||
layout_refit(&models->layout, prev_width, prev_height);
|
layout_refit(&models->layout, prev_width, prev_height);
|
||||||
|
|
||||||
used_panels = &models->layout.used_sentinel;
|
used_panels = &models->layout.used_sentinel;
|
||||||
for (dll_items(panel, used_panels)){
|
for (dll_items(panel, used_panels)){
|
||||||
view = panel->view;
|
view = panel->view;
|
||||||
|
@ -3689,18 +3691,18 @@ App_Step_Sig(app_step){
|
||||||
|
|
||||||
// NOTE(allen): prepare input information
|
// NOTE(allen): prepare input information
|
||||||
Key_Summary key_summary = {0};
|
Key_Summary key_summary = {0};
|
||||||
for (i32 i = 0; i < input->press_count; ++i){
|
for (i32 i = 0; i < input->keys.press_count; ++i){
|
||||||
key_summary.keys[key_summary.count++] = input->press[i];
|
key_summary.keys[key_summary.count++] = input->keys.press[i];
|
||||||
}
|
}
|
||||||
for (i32 i = 0; i < input->hold_count; ++i){
|
for (i32 i = 0; i < input->keys.hold_count; ++i){
|
||||||
key_summary.keys[key_summary.count++] = input->hold[i];
|
key_summary.keys[key_summary.count++] = input->keys.hold[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
mouse->wheel = -mouse->wheel;
|
input->mouse.wheel = -input->mouse.wheel;
|
||||||
|
|
||||||
// NOTE(allen): detect mouse hover status
|
// NOTE(allen): detect mouse hover status
|
||||||
i32 mx = mouse->x;
|
i32 mx = input->mouse.x;
|
||||||
i32 my = mouse->y;
|
i32 my = input->mouse.y;
|
||||||
b32 mouse_in_edit_area = 0;
|
b32 mouse_in_edit_area = 0;
|
||||||
b32 mouse_in_margin_area = 0;
|
b32 mouse_in_margin_area = 0;
|
||||||
Panel *mouse_panel, *used_panels;
|
Panel *mouse_panel, *used_panels;
|
||||||
|
@ -3787,7 +3789,7 @@ App_Step_Sig(app_step){
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): update child processes
|
// NOTE(allen): update child processes
|
||||||
if (dt > 0){
|
if (input->dt > 0){
|
||||||
Temp_Memory temp = begin_temp_memory(&models->mem.part);
|
Temp_Memory temp = begin_temp_memory(&models->mem.part);
|
||||||
u32 max = Kbytes(32);
|
u32 max = Kbytes(32);
|
||||||
char *dest = push_array(&models->mem.part, char, max);
|
char *dest = push_array(&models->mem.part, char, max);
|
||||||
|
@ -3830,7 +3832,7 @@ App_Step_Sig(app_step){
|
||||||
Temp_Memory param_stack_temp = begin_temp_memory(&models->mem.part);
|
Temp_Memory param_stack_temp = begin_temp_memory(&models->mem.part);
|
||||||
cmd->part = partition_sub_part(&models->mem.part, 16 << 10);
|
cmd->part = partition_sub_part(&models->mem.part, 16 << 10);
|
||||||
|
|
||||||
if (first_step){
|
if (input->first_step){
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
{
|
{
|
||||||
|
@ -3954,7 +3956,7 @@ App_Step_Sig(app_step){
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE(allen): process the command_coroutine if it is unfinished
|
// NOTE(allen): process the command_coroutine if it is unfinished
|
||||||
Available_Input available_input = init_available_input(&key_summary, mouse);
|
Available_Input available_input = init_available_input(&key_summary, &input->mouse);
|
||||||
|
|
||||||
// NOTE(allen): Keyboard input to command coroutine.
|
// NOTE(allen): Keyboard input to command coroutine.
|
||||||
if (models->command_coroutine != 0){
|
if (models->command_coroutine != 0){
|
||||||
|
@ -4029,7 +4031,7 @@ App_Step_Sig(app_step){
|
||||||
|
|
||||||
User_Input user_in;
|
User_Input user_in;
|
||||||
user_in.type = UserInputMouse;
|
user_in.type = UserInputMouse;
|
||||||
user_in.mouse = *mouse;
|
user_in.mouse = input->mouse;
|
||||||
user_in.command = 0;
|
user_in.command = 0;
|
||||||
user_in.abort = 0;
|
user_in.abort = 0;
|
||||||
|
|
||||||
|
@ -4041,7 +4043,7 @@ App_Step_Sig(app_step){
|
||||||
consume_input(&available_input, Input_MouseMove);
|
consume_input(&available_input, Input_MouseMove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse->press_l || mouse->release_l || mouse->l){
|
if (input->mouse.press_l || input->mouse.release_l || input->mouse.l){
|
||||||
if (abort_flags & EventOnLeftButton){
|
if (abort_flags & EventOnLeftButton){
|
||||||
user_in.abort = 1;
|
user_in.abort = 1;
|
||||||
}
|
}
|
||||||
|
@ -4051,7 +4053,7 @@ App_Step_Sig(app_step){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse->press_r || mouse->release_r || mouse->r){
|
if (input->mouse.press_r || input->mouse.release_r || input->mouse.r){
|
||||||
if (abort_flags & EventOnRightButton){
|
if (abort_flags & EventOnRightButton){
|
||||||
user_in.abort = 1;
|
user_in.abort = 1;
|
||||||
}
|
}
|
||||||
|
@ -4061,7 +4063,7 @@ App_Step_Sig(app_step){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse->wheel != 0){
|
if (input->mouse.wheel != 0){
|
||||||
if (abort_flags & EventOnWheel){
|
if (abort_flags & EventOnWheel){
|
||||||
user_in.abort = 1;
|
user_in.abort = 1;
|
||||||
}
|
}
|
||||||
|
@ -4095,12 +4097,12 @@ App_Step_Sig(app_step){
|
||||||
// NOTE(allen): pass raw input to the panels
|
// NOTE(allen): pass raw input to the panels
|
||||||
|
|
||||||
Input_Summary dead_input = {};
|
Input_Summary dead_input = {};
|
||||||
dead_input.mouse.x = mouse->x;
|
dead_input.mouse.x = input->mouse.x;
|
||||||
dead_input.mouse.y = mouse->y;
|
dead_input.mouse.y = input->mouse.y;
|
||||||
|
|
||||||
Input_Summary active_input = {};
|
Input_Summary active_input = {};
|
||||||
active_input.mouse.x = mouse->x;
|
active_input.mouse.x = input->mouse.x;
|
||||||
active_input.mouse.y = mouse->y;
|
active_input.mouse.y = input->mouse.y;
|
||||||
|
|
||||||
active_input.keys = get_key_data(&available_input);
|
active_input.keys = get_key_data(&available_input);
|
||||||
|
|
||||||
|
@ -4110,7 +4112,7 @@ App_Step_Sig(app_step){
|
||||||
Panel *panel = 0, *used_panels = 0;
|
Panel *panel = 0, *used_panels = 0;
|
||||||
View *view = 0, *active_view = 0;
|
View *view = 0, *active_view = 0;
|
||||||
b32 active = 0;
|
b32 active = 0;
|
||||||
Input_Summary input = {0};
|
Input_Summary summary = {0};
|
||||||
Input_Process_Result result = {0};
|
Input_Process_Result result = {0};
|
||||||
|
|
||||||
active_view = cmd->panel->view;
|
active_view = cmd->panel->view;
|
||||||
|
@ -4118,8 +4120,8 @@ App_Step_Sig(app_step){
|
||||||
for (dll_items(panel, used_panels)){
|
for (dll_items(panel, used_panels)){
|
||||||
view = panel->view;
|
view = panel->view;
|
||||||
active = (panel == cmd->panel);
|
active = (panel == cmd->panel);
|
||||||
input = (active)?(active_input):(dead_input);
|
summary = (active)?(active_input):(dead_input);
|
||||||
if (step_file_view(system, view, active_view, input)){
|
if (step_file_view(system, view, active_view, summary)){
|
||||||
app_result.animating = 1;
|
app_result.animating = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4128,9 +4130,9 @@ App_Step_Sig(app_step){
|
||||||
view = panel->view;
|
view = panel->view;
|
||||||
Assert(view->current_scroll);
|
Assert(view->current_scroll);
|
||||||
active = (panel == cmd->panel);
|
active = (panel == cmd->panel);
|
||||||
input = (active)?(active_input):(dead_input);
|
summary = (active)?(active_input):(dead_input);
|
||||||
if (panel == mouse_panel && !mouse->out_of_window){
|
if (panel == mouse_panel && !input->mouse.out_of_window){
|
||||||
input.mouse = mouse_state;
|
summary.mouse = mouse_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -4138,7 +4140,7 @@ App_Step_Sig(app_step){
|
||||||
// TODO(allen): I feel like the scroll context should actually not
|
// TODO(allen): I feel like the scroll context should actually not
|
||||||
// be allowed to change in here at all.
|
// be allowed to change in here at all.
|
||||||
result = do_input_file_view(system, exchange, view, panel->inner, active,
|
result = do_input_file_view(system, exchange, view, panel->inner, active,
|
||||||
&input, *vars, view->scroll_region);
|
&summary, *vars, view->scroll_region);
|
||||||
if (result.is_animating){
|
if (result.is_animating){
|
||||||
app_result.animating = 1;
|
app_result.animating = 1;
|
||||||
}
|
}
|
||||||
|
@ -4219,7 +4221,7 @@ App_Step_Sig(app_step){
|
||||||
update_command_data(vars, cmd);
|
update_command_data(vars, cmd);
|
||||||
|
|
||||||
// NOTE(allen): initialize message
|
// NOTE(allen): initialize message
|
||||||
if (first_step){
|
if (input->first_step){
|
||||||
String welcome =
|
String welcome =
|
||||||
make_lit_string("Welcome to " VERSION "\n"
|
make_lit_string("Welcome to " VERSION "\n"
|
||||||
"If you're new to 4coder there's no tutorial yet :(\n"
|
"If you're new to 4coder there's no tutorial yet :(\n"
|
||||||
|
@ -4256,7 +4258,7 @@ App_Step_Sig(app_step){
|
||||||
switch (vars->state){
|
switch (vars->state){
|
||||||
case APP_STATE_EDIT:
|
case APP_STATE_EDIT:
|
||||||
{
|
{
|
||||||
if (mouse->press_l && mouse_on_divider){
|
if (input->mouse.press_l && mouse_on_divider){
|
||||||
vars->state = APP_STATE_RESIZING;
|
vars->state = APP_STATE_RESIZING;
|
||||||
Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id);
|
Divider_And_ID div = layout_get_divider(&models->layout, mouse_divider_id);
|
||||||
vars->resizing.divider = div.divider;
|
vars->resizing.divider = div.divider;
|
||||||
|
@ -4323,7 +4325,7 @@ App_Step_Sig(app_step){
|
||||||
|
|
||||||
case APP_STATE_RESIZING:
|
case APP_STATE_RESIZING:
|
||||||
{
|
{
|
||||||
if (mouse->l){
|
if (input->mouse.l){
|
||||||
Panel_Divider *divider = vars->resizing.divider;
|
Panel_Divider *divider = vars->resizing.divider;
|
||||||
if (divider->v_divider){
|
if (divider->v_divider){
|
||||||
divider->pos = mx;
|
divider->pos = mx;
|
||||||
|
@ -4347,7 +4349,7 @@ App_Step_Sig(app_step){
|
||||||
}break;
|
}break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mouse_in_edit_area && mouse_panel != 0 && mouse->press_l){
|
if (mouse_in_edit_area && mouse_panel != 0 && input->mouse.press_l){
|
||||||
models->layout.active_panel = (i32)(mouse_panel - models->layout.panels);
|
models->layout.active_panel = (i32)(mouse_panel - models->layout.panels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
28
4ed.h
28
4ed.h
|
@ -81,17 +81,19 @@ struct Plat_Settings{
|
||||||
|
|
||||||
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
typedef App_Read_Command_Line_Sig(App_Read_Command_Line);
|
||||||
|
|
||||||
|
|
||||||
#define App_Init_Sig(name) void \
|
#define App_Init_Sig(name) void \
|
||||||
name(System_Functions *system, \
|
name(System_Functions *system, \
|
||||||
Render_Target *target, \
|
Render_Target *target, \
|
||||||
Application_Memory *memory, \
|
Application_Memory *memory, \
|
||||||
Exchange *exchange, \
|
Exchange *exchange, \
|
||||||
String clipboard, \
|
String clipboard, \
|
||||||
String current_directory, \
|
String current_directory, \
|
||||||
Custom_API api)
|
Custom_API api)
|
||||||
|
|
||||||
typedef App_Init_Sig(App_Init);
|
typedef App_Init_Sig(App_Init);
|
||||||
|
|
||||||
|
|
||||||
enum Application_Mouse_Cursor{
|
enum Application_Mouse_Cursor{
|
||||||
APP_MOUSE_CURSOR_DEFAULT,
|
APP_MOUSE_CURSOR_DEFAULT,
|
||||||
APP_MOUSE_CURSOR_ARROW,
|
APP_MOUSE_CURSOR_ARROW,
|
||||||
|
@ -110,19 +112,25 @@ struct Application_Step_Result{
|
||||||
b32 animating;
|
b32 animating;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Application_Step_Input{
|
||||||
|
b32 first_step;
|
||||||
|
f32 dt;
|
||||||
|
Key_Input_Data keys;
|
||||||
|
Mouse_State mouse;
|
||||||
|
String clipboard;
|
||||||
|
};
|
||||||
|
|
||||||
#define App_Step_Sig(name) void \
|
#define App_Step_Sig(name) void \
|
||||||
name(System_Functions *system, \
|
name(System_Functions *system, \
|
||||||
Key_Input_Data *input, \
|
|
||||||
Mouse_State *mouse, \
|
|
||||||
Render_Target *target, \
|
Render_Target *target, \
|
||||||
Application_Memory *memory, \
|
Application_Memory *memory, \
|
||||||
Exchange *exchange, \
|
Exchange *exchange, \
|
||||||
String clipboard, \
|
Application_Step_Input *input, \
|
||||||
f32 dt, b32 first_step, \
|
|
||||||
Application_Step_Result *result)
|
Application_Step_Result *result)
|
||||||
|
|
||||||
typedef App_Step_Sig(App_Step);
|
typedef App_Step_Sig(App_Step);
|
||||||
|
|
||||||
|
|
||||||
struct App_Functions{
|
struct App_Functions{
|
||||||
App_Read_Command_Line *read_command_line;
|
App_Read_Command_Line *read_command_line;
|
||||||
App_Init *init;
|
App_Init *init;
|
||||||
|
|
586
win32_4ed.cpp
586
win32_4ed.cpp
|
@ -89,8 +89,6 @@ struct Win32_Input_Chunk_Persistent{
|
||||||
i32 mouse_x, mouse_y;
|
i32 mouse_x, mouse_y;
|
||||||
b8 mouse_l, mouse_r;
|
b8 mouse_l, mouse_r;
|
||||||
|
|
||||||
b8 keep_playing;
|
|
||||||
|
|
||||||
Control_Keys controls;
|
Control_Keys controls;
|
||||||
b8 control_keys[MDFR_INDEX_COUNT];
|
b8 control_keys[MDFR_INDEX_COUNT];
|
||||||
};
|
};
|
||||||
|
@ -124,13 +122,11 @@ struct Win32_Vars{
|
||||||
DLL_Loaded app_dll;
|
DLL_Loaded app_dll;
|
||||||
DLL_Loaded custom_dll;
|
DLL_Loaded custom_dll;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Plat_Settings settings;
|
Plat_Settings settings;
|
||||||
|
|
||||||
|
|
||||||
Thread_Group groups[THREAD_GROUP_COUNT];
|
Thread_Group groups[THREAD_GROUP_COUNT];
|
||||||
CRITICAL_SECTION locks[LOCK_COUNT];
|
CRITICAL_SECTION locks[LOCK_COUNT];
|
||||||
CRITICAL_SECTION DEBUG_sysmem_lock;
|
|
||||||
Thread_Memory *thread_memory;
|
Thread_Memory *thread_memory;
|
||||||
Win32_Coroutine coroutine_data[18];
|
Win32_Coroutine coroutine_data[18];
|
||||||
Win32_Coroutine *coroutine_free;
|
Win32_Coroutine *coroutine_free;
|
||||||
|
@ -161,6 +157,7 @@ struct Win32_Vars{
|
||||||
|
|
||||||
|
|
||||||
#if FRED_INTERNAL
|
#if FRED_INTERNAL
|
||||||
|
CRITICAL_SECTION DEBUG_sysmem_lock;
|
||||||
Sys_Bubble internal_bubble;
|
Sys_Bubble internal_bubble;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
@ -169,6 +166,11 @@ globalvar Win32_Vars win32vars;
|
||||||
globalvar Application_Memory memory_vars;
|
globalvar Application_Memory memory_vars;
|
||||||
globalvar Exchange exchange_vars;
|
globalvar Exchange exchange_vars;
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Helpers
|
||||||
|
//
|
||||||
|
|
||||||
internal HANDLE
|
internal HANDLE
|
||||||
Win32Handle(Plat_Handle h){
|
Win32Handle(Plat_Handle h){
|
||||||
HANDLE result;
|
HANDLE result;
|
||||||
|
@ -198,6 +200,7 @@ Win32Ptr(void *h){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Memory (not exposed to application, but needed in system_shared.cpp)
|
// Memory (not exposed to application, but needed in system_shared.cpp)
|
||||||
//
|
//
|
||||||
|
@ -259,8 +262,269 @@ INTERNAL_system_debug_message(char *message){
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// File
|
// Multithreading
|
||||||
|
//
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Acquire_Lock_Sig(system_acquire_lock){
|
||||||
|
EnterCriticalSection(&win32vars.locks[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Release_Lock_Sig(system_release_lock){
|
||||||
|
LeaveCriticalSection(&win32vars.locks[id]);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal DWORD
|
||||||
|
JobThreadProc(LPVOID lpParameter){
|
||||||
|
Thread_Context *thread = (Thread_Context*)lpParameter;
|
||||||
|
Work_Queue *queue = thread->queue;
|
||||||
|
|
||||||
|
for (;;){
|
||||||
|
u32 read_index = queue->read_position;
|
||||||
|
u32 write_index = queue->write_position;
|
||||||
|
|
||||||
|
if (read_index != write_index){
|
||||||
|
u32 next_read_index = (read_index + 1) % JOB_ID_WRAP;
|
||||||
|
u32 safe_read_index =
|
||||||
|
InterlockedCompareExchange(&queue->read_position,
|
||||||
|
next_read_index, read_index);
|
||||||
|
|
||||||
|
if (safe_read_index == read_index){
|
||||||
|
Full_Job_Data *full_job = queue->jobs + (safe_read_index % QUEUE_WRAP);
|
||||||
|
// NOTE(allen): This is interlocked so that it plays nice
|
||||||
|
// with the cancel job routine, which may try to cancel this job
|
||||||
|
// at the same time that we try to run it
|
||||||
|
|
||||||
|
i32 safe_running_thread =
|
||||||
|
InterlockedCompareExchange(&full_job->running_thread,
|
||||||
|
thread->id, THREAD_NOT_ASSIGNED);
|
||||||
|
|
||||||
|
if (safe_running_thread == THREAD_NOT_ASSIGNED){
|
||||||
|
thread->job_id = full_job->id;
|
||||||
|
thread->running = 1;
|
||||||
|
Thread_Memory *thread_memory = 0;
|
||||||
|
|
||||||
|
// TODO(allen): remove memory_request
|
||||||
|
if (full_job->job.memory_request != 0){
|
||||||
|
thread_memory = win32vars.thread_memory + thread->id - 1;
|
||||||
|
if (thread_memory->size < full_job->job.memory_request){
|
||||||
|
if (thread_memory->data){
|
||||||
|
Win32FreeMemory(thread_memory->data);
|
||||||
|
}
|
||||||
|
i32 new_size = LargeRoundUp(full_job->job.memory_request, Kbytes(4));
|
||||||
|
thread_memory->data = Win32GetMemory(new_size);
|
||||||
|
thread_memory->size = new_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
full_job->job.callback(&win32vars.system, thread, thread_memory,
|
||||||
|
&exchange_vars.thread, full_job->job.data);
|
||||||
|
PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0);
|
||||||
|
full_job->running_thread = 0;
|
||||||
|
thread->running = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
WaitForSingleObject(Win32Handle(queue->semaphore), INFINITE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Post_Job_Sig(system_post_job){
|
||||||
|
Work_Queue *queue = exchange_vars.thread.queues + group_id;
|
||||||
|
|
||||||
|
Assert((queue->write_position + 1) % QUEUE_WRAP != queue->read_position % QUEUE_WRAP);
|
||||||
|
|
||||||
|
b32 success = 0;
|
||||||
|
u32 result = 0;
|
||||||
|
while (!success){
|
||||||
|
u32 write_index = queue->write_position;
|
||||||
|
u32 next_write_index = (write_index + 1) % JOB_ID_WRAP;
|
||||||
|
u32 safe_write_index =
|
||||||
|
InterlockedCompareExchange(&queue->write_position,
|
||||||
|
next_write_index, write_index);
|
||||||
|
if (safe_write_index == write_index){
|
||||||
|
result = write_index;
|
||||||
|
write_index = write_index % QUEUE_WRAP;
|
||||||
|
queue->jobs[write_index].job = job;
|
||||||
|
queue->jobs[write_index].running_thread = THREAD_NOT_ASSIGNED;
|
||||||
|
queue->jobs[write_index].id = result;
|
||||||
|
success = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseSemaphore(Win32Handle(queue->semaphore), 1, 0);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(allen): I would like to get rid of job canceling
|
||||||
|
// but I still don't know what exactly I would do without it.
|
||||||
|
internal
|
||||||
|
Sys_Cancel_Job_Sig(system_cancel_job){
|
||||||
|
Work_Queue *queue = exchange_vars.thread.queues + group_id;
|
||||||
|
Thread_Group *group = win32vars.groups + group_id;
|
||||||
|
|
||||||
|
u32 job_index;
|
||||||
|
u32 thread_id;
|
||||||
|
Full_Job_Data *full_job;
|
||||||
|
Thread_Context *thread;
|
||||||
|
|
||||||
|
job_index = job_id % QUEUE_WRAP;
|
||||||
|
full_job = queue->jobs + job_index;
|
||||||
|
|
||||||
|
Assert(full_job->id == job_id);
|
||||||
|
thread_id =
|
||||||
|
InterlockedCompareExchange(&full_job->running_thread,
|
||||||
|
0, THREAD_NOT_ASSIGNED);
|
||||||
|
|
||||||
|
if (thread_id != THREAD_NOT_ASSIGNED){
|
||||||
|
system_acquire_lock(CANCEL_LOCK0 + thread_id - 1);
|
||||||
|
thread = group->threads + thread_id - 1;
|
||||||
|
TerminateThread(thread->handle, 0);
|
||||||
|
u32 creation_flag = 0;
|
||||||
|
thread->handle = CreateThread(0, 0, JobThreadProc, thread, creation_flag, (LPDWORD)&thread->windows_id);
|
||||||
|
system_release_lock(CANCEL_LOCK0 + thread_id - 1);
|
||||||
|
thread->running = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
system_grow_thread_memory(Thread_Memory *memory){
|
||||||
|
void *old_data;
|
||||||
|
i32 old_size, new_size;
|
||||||
|
|
||||||
|
system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
|
||||||
|
old_data = memory->data;
|
||||||
|
old_size = memory->size;
|
||||||
|
new_size = LargeRoundUp(memory->size*2, Kbytes(4));
|
||||||
|
memory->data = system_get_memory(new_size);
|
||||||
|
memory->size = new_size;
|
||||||
|
if (old_data){
|
||||||
|
memcpy(memory->data, old_data, old_size);
|
||||||
|
system_free_memory(old_data);
|
||||||
|
}
|
||||||
|
system_release_lock(CANCEL_LOCK0 + memory->id - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if FRED_INTERNAL
|
||||||
|
internal void
|
||||||
|
INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){
|
||||||
|
Work_Queue *queue = exchange_vars.thread.queues + id;
|
||||||
|
u32 write = queue->write_position;
|
||||||
|
u32 read = queue->read_position;
|
||||||
|
if (write < read) write += JOB_ID_WRAP;
|
||||||
|
*pending = (i32)(write - read);
|
||||||
|
|
||||||
|
Thread_Group *group = win32vars.groups + id;
|
||||||
|
for (i32 i = 0; i < group->count; ++i){
|
||||||
|
running[i] = (group->threads[i].running != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Coroutines
|
||||||
|
//
|
||||||
|
|
||||||
|
internal Win32_Coroutine*
|
||||||
|
Win32AllocCoroutine(){
|
||||||
|
Win32_Coroutine *result = win32vars.coroutine_free;
|
||||||
|
Assert(result != 0);
|
||||||
|
win32vars.coroutine_free = result->next;
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
Win32FreeCoroutine(Win32_Coroutine *data){
|
||||||
|
data->next = win32vars.coroutine_free;
|
||||||
|
win32vars.coroutine_free = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void
|
||||||
|
Win32CoroutineMain(void *arg_){
|
||||||
|
Win32_Coroutine *c = (Win32_Coroutine*)arg_;
|
||||||
|
c->coroutine.func(&c->coroutine);
|
||||||
|
c->done = 1;
|
||||||
|
Win32FreeCoroutine(c);
|
||||||
|
SwitchToFiber(c->coroutine.yield_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Create_Coroutine_Sig(system_create_coroutine){
|
||||||
|
Win32_Coroutine *c;
|
||||||
|
Coroutine *coroutine;
|
||||||
|
void *fiber;
|
||||||
|
|
||||||
|
c = Win32AllocCoroutine();
|
||||||
|
c->done = 0;
|
||||||
|
|
||||||
|
coroutine = &c->coroutine;
|
||||||
|
|
||||||
|
fiber = CreateFiber(0, Win32CoroutineMain, coroutine);
|
||||||
|
|
||||||
|
coroutine->plat_handle = Win32Handle(fiber);
|
||||||
|
coroutine->func = func;
|
||||||
|
|
||||||
|
return(coroutine);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal
|
||||||
|
Sys_Launch_Coroutine_Sig(system_launch_coroutine){
|
||||||
|
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
|
||||||
|
void *fiber;
|
||||||
|
|
||||||
|
fiber = Win32Handle(coroutine->plat_handle);
|
||||||
|
coroutine->yield_handle = GetCurrentFiber();
|
||||||
|
coroutine->in = in;
|
||||||
|
coroutine->out = out;
|
||||||
|
|
||||||
|
SwitchToFiber(fiber);
|
||||||
|
|
||||||
|
if (c->done){
|
||||||
|
DeleteFiber(fiber);
|
||||||
|
Win32FreeCoroutine(c);
|
||||||
|
coroutine = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(coroutine);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sys_Resume_Coroutine_Sig(system_resume_coroutine){
|
||||||
|
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
|
||||||
|
void *fiber;
|
||||||
|
|
||||||
|
Assert(c->done == 0);
|
||||||
|
|
||||||
|
coroutine->yield_handle = GetCurrentFiber();
|
||||||
|
coroutine->in = in;
|
||||||
|
coroutine->out = out;
|
||||||
|
|
||||||
|
fiber = Win32Ptr(coroutine->plat_handle);
|
||||||
|
|
||||||
|
SwitchToFiber(fiber);
|
||||||
|
|
||||||
|
if (c->done){
|
||||||
|
DeleteFiber(fiber);
|
||||||
|
Win32FreeCoroutine(c);
|
||||||
|
coroutine = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(coroutine);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sys_Yield_Coroutine_Sig(system_yield_coroutine){
|
||||||
|
SwitchToFiber(coroutine->yield_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// Files
|
||||||
//
|
//
|
||||||
|
|
||||||
internal
|
internal
|
||||||
|
@ -602,6 +866,7 @@ GET_4ED_PATH_SIG(system_get_4ed_path){
|
||||||
return(system_get_binary_path(&str));
|
return(system_get_binary_path(&str));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Clipboard
|
// Clipboard
|
||||||
//
|
//
|
||||||
|
@ -646,263 +911,6 @@ Win32ReadClipboardContents(){
|
||||||
return(result);
|
return(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Multithreading
|
|
||||||
//
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Acquire_Lock_Sig(system_acquire_lock){
|
|
||||||
EnterCriticalSection(&win32vars.locks[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Release_Lock_Sig(system_release_lock){
|
|
||||||
LeaveCriticalSection(&win32vars.locks[id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal DWORD
|
|
||||||
JobThreadProc(LPVOID lpParameter){
|
|
||||||
Thread_Context *thread = (Thread_Context*)lpParameter;
|
|
||||||
Work_Queue *queue = thread->queue;
|
|
||||||
|
|
||||||
for (;;){
|
|
||||||
u32 read_index = queue->read_position;
|
|
||||||
u32 write_index = queue->write_position;
|
|
||||||
|
|
||||||
if (read_index != write_index){
|
|
||||||
u32 next_read_index = (read_index + 1) % JOB_ID_WRAP;
|
|
||||||
u32 safe_read_index =
|
|
||||||
InterlockedCompareExchange(&queue->read_position,
|
|
||||||
next_read_index, read_index);
|
|
||||||
|
|
||||||
if (safe_read_index == read_index){
|
|
||||||
Full_Job_Data *full_job = queue->jobs + (safe_read_index % QUEUE_WRAP);
|
|
||||||
// NOTE(allen): This is interlocked so that it plays nice
|
|
||||||
// with the cancel job routine, which may try to cancel this job
|
|
||||||
// at the same time that we try to run it
|
|
||||||
|
|
||||||
i32 safe_running_thread =
|
|
||||||
InterlockedCompareExchange(&full_job->running_thread,
|
|
||||||
thread->id, THREAD_NOT_ASSIGNED);
|
|
||||||
|
|
||||||
if (safe_running_thread == THREAD_NOT_ASSIGNED){
|
|
||||||
thread->job_id = full_job->id;
|
|
||||||
thread->running = 1;
|
|
||||||
Thread_Memory *thread_memory = 0;
|
|
||||||
|
|
||||||
// TODO(allen): remove memory_request
|
|
||||||
if (full_job->job.memory_request != 0){
|
|
||||||
thread_memory = win32vars.thread_memory + thread->id - 1;
|
|
||||||
if (thread_memory->size < full_job->job.memory_request){
|
|
||||||
if (thread_memory->data){
|
|
||||||
Win32FreeMemory(thread_memory->data);
|
|
||||||
}
|
|
||||||
i32 new_size = LargeRoundUp(full_job->job.memory_request, Kbytes(4));
|
|
||||||
thread_memory->data = Win32GetMemory(new_size);
|
|
||||||
thread_memory->size = new_size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
full_job->job.callback(&win32vars.system, thread, thread_memory,
|
|
||||||
&exchange_vars.thread, full_job->job.data);
|
|
||||||
PostMessage(win32vars.window_handle, WM_4coder_ANIMATE, 0, 0);
|
|
||||||
full_job->running_thread = 0;
|
|
||||||
thread->running = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
WaitForSingleObject(Win32Handle(queue->semaphore), INFINITE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Post_Job_Sig(system_post_job){
|
|
||||||
Work_Queue *queue = exchange_vars.thread.queues + group_id;
|
|
||||||
|
|
||||||
Assert((queue->write_position + 1) % QUEUE_WRAP != queue->read_position % QUEUE_WRAP);
|
|
||||||
|
|
||||||
b32 success = 0;
|
|
||||||
u32 result = 0;
|
|
||||||
while (!success){
|
|
||||||
u32 write_index = queue->write_position;
|
|
||||||
u32 next_write_index = (write_index + 1) % JOB_ID_WRAP;
|
|
||||||
u32 safe_write_index =
|
|
||||||
InterlockedCompareExchange(&queue->write_position,
|
|
||||||
next_write_index, write_index);
|
|
||||||
if (safe_write_index == write_index){
|
|
||||||
result = write_index;
|
|
||||||
write_index = write_index % QUEUE_WRAP;
|
|
||||||
queue->jobs[write_index].job = job;
|
|
||||||
queue->jobs[write_index].running_thread = THREAD_NOT_ASSIGNED;
|
|
||||||
queue->jobs[write_index].id = result;
|
|
||||||
success = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ReleaseSemaphore(Win32Handle(queue->semaphore), 1, 0);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(allen): I would like to get rid of job canceling
|
|
||||||
// but I still don't know what exactly I would do without it.
|
|
||||||
internal
|
|
||||||
Sys_Cancel_Job_Sig(system_cancel_job){
|
|
||||||
Work_Queue *queue = exchange_vars.thread.queues + group_id;
|
|
||||||
Thread_Group *group = win32vars.groups + group_id;
|
|
||||||
|
|
||||||
u32 job_index;
|
|
||||||
u32 thread_id;
|
|
||||||
Full_Job_Data *full_job;
|
|
||||||
Thread_Context *thread;
|
|
||||||
|
|
||||||
job_index = job_id % QUEUE_WRAP;
|
|
||||||
full_job = queue->jobs + job_index;
|
|
||||||
|
|
||||||
Assert(full_job->id == job_id);
|
|
||||||
thread_id =
|
|
||||||
InterlockedCompareExchange(&full_job->running_thread,
|
|
||||||
0, THREAD_NOT_ASSIGNED);
|
|
||||||
|
|
||||||
if (thread_id != THREAD_NOT_ASSIGNED){
|
|
||||||
system_acquire_lock(CANCEL_LOCK0 + thread_id - 1);
|
|
||||||
thread = group->threads + thread_id - 1;
|
|
||||||
TerminateThread(thread->handle, 0);
|
|
||||||
u32 creation_flag = 0;
|
|
||||||
thread->handle = CreateThread(0, 0, JobThreadProc, thread, creation_flag, (LPDWORD)&thread->windows_id);
|
|
||||||
system_release_lock(CANCEL_LOCK0 + thread_id - 1);
|
|
||||||
thread->running = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
system_grow_thread_memory(Thread_Memory *memory){
|
|
||||||
void *old_data;
|
|
||||||
i32 old_size, new_size;
|
|
||||||
|
|
||||||
system_acquire_lock(CANCEL_LOCK0 + memory->id - 1);
|
|
||||||
old_data = memory->data;
|
|
||||||
old_size = memory->size;
|
|
||||||
new_size = LargeRoundUp(memory->size*2, Kbytes(4));
|
|
||||||
memory->data = system_get_memory(new_size);
|
|
||||||
memory->size = new_size;
|
|
||||||
if (old_data){
|
|
||||||
memcpy(memory->data, old_data, old_size);
|
|
||||||
system_free_memory(old_data);
|
|
||||||
}
|
|
||||||
system_release_lock(CANCEL_LOCK0 + memory->id - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if FRED_INTERNAL
|
|
||||||
internal void
|
|
||||||
INTERNAL_get_thread_states(Thread_Group_ID id, bool8 *running, i32 *pending){
|
|
||||||
Work_Queue *queue = exchange_vars.thread.queues + id;
|
|
||||||
u32 write = queue->write_position;
|
|
||||||
u32 read = queue->read_position;
|
|
||||||
if (write < read) write += JOB_ID_WRAP;
|
|
||||||
*pending = (i32)(write - read);
|
|
||||||
|
|
||||||
Thread_Group *group = win32vars.groups + id;
|
|
||||||
for (i32 i = 0; i < group->count; ++i){
|
|
||||||
running[i] = (group->threads[i].running != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// Coroutine
|
|
||||||
//
|
|
||||||
|
|
||||||
internal Win32_Coroutine*
|
|
||||||
Win32AllocCoroutine(){
|
|
||||||
Win32_Coroutine *result = win32vars.coroutine_free;
|
|
||||||
Assert(result != 0);
|
|
||||||
win32vars.coroutine_free = result->next;
|
|
||||||
return(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
Win32FreeCoroutine(Win32_Coroutine *data){
|
|
||||||
data->next = win32vars.coroutine_free;
|
|
||||||
win32vars.coroutine_free = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void
|
|
||||||
Win32CoroutineMain(void *arg_){
|
|
||||||
Win32_Coroutine *c = (Win32_Coroutine*)arg_;
|
|
||||||
c->coroutine.func(&c->coroutine);
|
|
||||||
c->done = 1;
|
|
||||||
Win32FreeCoroutine(c);
|
|
||||||
SwitchToFiber(c->coroutine.yield_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Create_Coroutine_Sig(system_create_coroutine){
|
|
||||||
Win32_Coroutine *c;
|
|
||||||
Coroutine *coroutine;
|
|
||||||
void *fiber;
|
|
||||||
|
|
||||||
c = Win32AllocCoroutine();
|
|
||||||
c->done = 0;
|
|
||||||
|
|
||||||
coroutine = &c->coroutine;
|
|
||||||
|
|
||||||
fiber = CreateFiber(0, Win32CoroutineMain, coroutine);
|
|
||||||
|
|
||||||
coroutine->plat_handle = Win32Handle(fiber);
|
|
||||||
coroutine->func = func;
|
|
||||||
|
|
||||||
return(coroutine);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal
|
|
||||||
Sys_Launch_Coroutine_Sig(system_launch_coroutine){
|
|
||||||
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
|
|
||||||
void *fiber;
|
|
||||||
|
|
||||||
fiber = Win32Handle(coroutine->plat_handle);
|
|
||||||
coroutine->yield_handle = GetCurrentFiber();
|
|
||||||
coroutine->in = in;
|
|
||||||
coroutine->out = out;
|
|
||||||
|
|
||||||
SwitchToFiber(fiber);
|
|
||||||
|
|
||||||
if (c->done){
|
|
||||||
DeleteFiber(fiber);
|
|
||||||
Win32FreeCoroutine(c);
|
|
||||||
coroutine = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(coroutine);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sys_Resume_Coroutine_Sig(system_resume_coroutine){
|
|
||||||
Win32_Coroutine *c = (Win32_Coroutine*)coroutine;
|
|
||||||
void *fiber;
|
|
||||||
|
|
||||||
Assert(c->done == 0);
|
|
||||||
|
|
||||||
coroutine->yield_handle = GetCurrentFiber();
|
|
||||||
coroutine->in = in;
|
|
||||||
coroutine->out = out;
|
|
||||||
|
|
||||||
fiber = Win32Ptr(coroutine->plat_handle);
|
|
||||||
|
|
||||||
SwitchToFiber(fiber);
|
|
||||||
|
|
||||||
if (c->done){
|
|
||||||
DeleteFiber(fiber);
|
|
||||||
Win32FreeCoroutine(c);
|
|
||||||
coroutine = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return(coroutine);
|
|
||||||
}
|
|
||||||
|
|
||||||
Sys_Yield_Coroutine_Sig(system_yield_coroutine){
|
|
||||||
SwitchToFiber(coroutine->yield_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Command Line Exectuion
|
// Command Line Exectuion
|
||||||
|
@ -1780,6 +1788,7 @@ WinMain(HINSTANCE hInstance,
|
||||||
}
|
}
|
||||||
|
|
||||||
win32vars.custom_api.view_routine = (View_Routine_Function*)0;
|
win32vars.custom_api.view_routine = (View_Routine_Function*)0;
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
if (win32vars.custom_api.view_routine == 0){
|
if (win32vars.custom_api.view_routine == 0){
|
||||||
win32vars.custom_api.view_routine = (View_Routine_Function*)view_routine;
|
win32vars.custom_api.view_routine = (View_Routine_Function*)view_routine;
|
||||||
|
@ -1953,7 +1962,7 @@ WinMain(HINSTANCE hInstance,
|
||||||
|
|
||||||
system_free_memory(current_directory.str);
|
system_free_memory(current_directory.str);
|
||||||
|
|
||||||
win32vars.input_chunk.pers.keep_playing = 1;
|
b32 keep_playing = 1;
|
||||||
win32vars.first = 1;
|
win32vars.first = 1;
|
||||||
timeBeginPeriod(1);
|
timeBeginPeriod(1);
|
||||||
|
|
||||||
|
@ -1964,7 +1973,7 @@ WinMain(HINSTANCE hInstance,
|
||||||
u64 timer_start = Win32HighResolutionTime();
|
u64 timer_start = Win32HighResolutionTime();
|
||||||
system_acquire_lock(FRAME_LOCK);
|
system_acquire_lock(FRAME_LOCK);
|
||||||
MSG msg;
|
MSG msg;
|
||||||
for (;win32vars.input_chunk.pers.keep_playing;){
|
for (;keep_playing;){
|
||||||
// TODO(allen): Find a good way to wait on a pipe
|
// TODO(allen): Find a good way to wait on a pipe
|
||||||
// without interfering with the reading process
|
// without interfering with the reading process
|
||||||
// Looks like we can ReadFile with a size of zero
|
// Looks like we can ReadFile with a size of zero
|
||||||
|
@ -1977,7 +1986,7 @@ WinMain(HINSTANCE hInstance,
|
||||||
for (;win32vars.got_useful_event == 0;){
|
for (;win32vars.got_useful_event == 0;){
|
||||||
if (GetMessage(&msg, 0, 0, 0)){
|
if (GetMessage(&msg, 0, 0, 0)){
|
||||||
if (msg.message == WM_QUIT){
|
if (msg.message == WM_QUIT){
|
||||||
win32vars.input_chunk.pers.keep_playing = 0;
|
keep_playing = 0;
|
||||||
}else{
|
}else{
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
|
@ -1988,7 +1997,7 @@ WinMain(HINSTANCE hInstance,
|
||||||
|
|
||||||
while (PeekMessage(&msg, 0, 0, 0, 1)){
|
while (PeekMessage(&msg, 0, 0, 0, 1)){
|
||||||
if (msg.message == WM_QUIT){
|
if (msg.message == WM_QUIT){
|
||||||
win32vars.input_chunk.pers.keep_playing = 0;
|
keep_playing = 0;
|
||||||
}else{
|
}else{
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
|
@ -2034,46 +2043,47 @@ WinMain(HINSTANCE hInstance,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Key_Input_Data input_data;
|
Application_Step_Input input = {0};
|
||||||
Mouse_State mouse;
|
|
||||||
Application_Step_Result result;
|
|
||||||
|
|
||||||
input_data = input_chunk.trans.key_data;
|
input.first_step = win32vars.first;
|
||||||
mouse.out_of_window = input_chunk.trans.out_of_window;
|
|
||||||
|
|
||||||
mouse.l = input_chunk.pers.mouse_l;
|
// NOTE(allen): The expected dt given the frame limit in seconds.
|
||||||
mouse.press_l = input_chunk.trans.mouse_l_press;
|
input.dt = frame_useconds / 1000000.f;
|
||||||
mouse.release_l = input_chunk.trans.mouse_l_release;
|
|
||||||
|
|
||||||
mouse.r = input_chunk.pers.mouse_r;
|
input.keys = input_chunk.trans.key_data;
|
||||||
mouse.press_r = input_chunk.trans.mouse_r_press;
|
|
||||||
mouse.release_r = input_chunk.trans.mouse_r_release;
|
|
||||||
|
|
||||||
mouse.wheel = input_chunk.trans.mouse_wheel;
|
input.mouse.out_of_window = input_chunk.trans.out_of_window;
|
||||||
|
|
||||||
mouse.x = input_chunk.pers.mouse_x;
|
input.mouse.l = input_chunk.pers.mouse_l;
|
||||||
mouse.y = input_chunk.pers.mouse_y;
|
input.mouse.press_l = input_chunk.trans.mouse_l_press;
|
||||||
|
input.mouse.release_l = input_chunk.trans.mouse_l_release;
|
||||||
|
|
||||||
|
input.mouse.r = input_chunk.pers.mouse_r;
|
||||||
|
input.mouse.press_r = input_chunk.trans.mouse_r_press;
|
||||||
|
input.mouse.release_r = input_chunk.trans.mouse_r_release;
|
||||||
|
|
||||||
|
input.mouse.wheel = input_chunk.trans.mouse_wheel;
|
||||||
|
input.mouse.x = input_chunk.pers.mouse_x;
|
||||||
|
input.mouse.y = input_chunk.pers.mouse_y;
|
||||||
|
|
||||||
|
input.clipboard = win32vars.clipboard_contents;
|
||||||
|
|
||||||
|
|
||||||
|
Application_Step_Result result = {(Application_Mouse_Cursor)0};
|
||||||
result.mouse_cursor_type = APP_MOUSE_CURSOR_DEFAULT;
|
result.mouse_cursor_type = APP_MOUSE_CURSOR_DEFAULT;
|
||||||
result.lctrl_lalt_is_altgr = win32vars.lctrl_lalt_is_altgr;
|
result.lctrl_lalt_is_altgr = win32vars.lctrl_lalt_is_altgr;
|
||||||
result.trying_to_kill = input_chunk.trans.trying_to_kill;
|
result.trying_to_kill = input_chunk.trans.trying_to_kill;
|
||||||
result.perform_kill = 0;
|
result.perform_kill = 0;
|
||||||
|
|
||||||
// NOTE(allen): The expected dt given the frame limit in seconds.
|
|
||||||
f32 dt = frame_useconds / 1000000.f;
|
|
||||||
|
|
||||||
win32vars.app.step(&win32vars.system,
|
win32vars.app.step(&win32vars.system,
|
||||||
&input_data,
|
|
||||||
&mouse,
|
|
||||||
&win32vars.target,
|
&win32vars.target,
|
||||||
&memory_vars,
|
&memory_vars,
|
||||||
&exchange_vars,
|
&exchange_vars,
|
||||||
win32vars.clipboard_contents,
|
&input,
|
||||||
dt, win32vars.first,
|
|
||||||
&result);
|
&result);
|
||||||
|
|
||||||
if (result.perform_kill){
|
if (result.perform_kill){
|
||||||
win32vars.input_chunk.pers.keep_playing = 0;
|
keep_playing = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Win32SetCursorFromUpdate(result.mouse_cursor_type);
|
Win32SetCursorFromUpdate(result.mouse_cursor_type);
|
||||||
|
|
Loading…
Reference in New Issue