int fs_emu_is_quitting() { // FIXME: move to header file for possible inlining... return fs_ml_is_quitting(); }
void fs_ml_render_iteration() { static int first = 1; if (first) { first = 0; initialize_opengl_sync(); } if (g_fs_ml_vblank_sync) { render_iteration_vsync(); } else if (g_fs_ml_benchmarking) { update_frame(); render_frame(); swap_opengl_buffers(); } else { // when vsync is off, we wait until a new frame is ready and // then we display it immediately if (fs_ml_is_quitting()) { // but when the emulation is quitting, we can't expect any new // frames so there's no point waiting for them. Instead, we just // sleep a bit to throttle the frame rate for the quit animation fs_ml_usleep(10000); } else { // wait max 33 ms to allow the user interface to work even if // the emu hangs // int64_t dest_time = fs_get_real_time() + 33 * 1000; int64_t end_time = fs_condition_get_wait_end_time(33 * 1000); int64_t check_time = 0; fs_mutex_lock(g_frame_available_mutex); // fs_log("cond wait until %lld\n", end_time); while (g_rendered_frame == g_available_frame) { fs_condition_wait_until( g_frame_available_cond, g_frame_available_mutex, end_time); check_time = fs_condition_get_wait_end_time(0); if (check_time >= end_time) { // fs_log("timed out at %lld\n", check_time); break; } else { // fs_log("wake-up at %lld (end_time = %lld)\n", check_time, end_time); } } fs_mutex_unlock(g_frame_available_mutex); } update_frame(); render_frame(); swap_opengl_buffers(); //gl_finish(); } if (g_fs_ml_video_screenshot_path) { fs_mutex_lock(g_fs_ml_video_screenshot_mutex); if (g_fs_ml_video_screenshot_path) { save_screenshot_of_opengl_framebuffer( g_fs_ml_video_screenshot_path); g_free(g_fs_ml_video_screenshot_path); g_fs_ml_video_screenshot_path = NULL; } fs_mutex_unlock(g_fs_ml_video_screenshot_mutex); } if (g_fs_ml_video_post_render_function) { g_fs_ml_video_post_render_function(); } }
static void *manymouse_thread(void* data) { fs_log("[MANYMOUSE] Thread running\n"); int k = g_fs_ml_input_device_count; g_first_manymouse_index = k; int mouse_count = ManyMouse_Init(); if (mouse_count < 0) { fs_log("[MANYMOUSE] Initialization failed (%d)\n", mouse_count); } else if (mouse_count == 0) { fs_log("MANYMOUSE: no mice found\n"); // no mice found, so we just quit using the library } for (int i = 0; i < mouse_count; i++) { const char *device = ManyMouse_DeviceName(i); const char *driver = ManyMouse_DriverName(); char *name; if (device[0] == 0 || g_ascii_strcasecmp(device, "mouse") == 0) { name = g_strdup("Mouse: Unnamed Mouse"); } else { name = g_strdup_printf("Mouse: %s", device); } // fs_ml_input_unique_device_name either returns name, or frees it // and return another name, so name must be malloced and owned by // caller name = fs_ml_input_unique_device_name(name); fs_log("MANYMOUSE: Adding %s (%s)\n", name, driver); g_fs_ml_input_devices[k].type = FS_ML_MOUSE; g_fs_ml_input_devices[k].index = k; g_fs_ml_input_devices[k].name = name; g_fs_ml_input_devices[k].alias = g_strdup_printf("MOUSE #%d", i + 2); k += 1; } // when done like this, I believe no memory barrier is needed when the // other thread polls g_manymouse_last_index g_manymouse_last_index = k; if (mouse_count < 0) { // ManyMouse library was not initialized return NULL; } ManyMouseEvent event; fs_ml_event *new_event; while (!fs_ml_is_quitting()) { // printf("..\n"); while (ManyMouse_PollEvent(&event)) { // printf(" -- event type %d -- \n", event.type); if (event.type == MANYMOUSE_EVENT_RELMOTION) { // printf("MANYMOUSE_EVENT_RELMOTION\n"); new_event = fs_ml_alloc_event(); new_event->type = FS_ML_MOUSEMOTION; new_event->motion.device = g_first_manymouse_index + \ event.device; if (event.item == 0) { new_event->motion.xrel = event.value; new_event->motion.yrel = 0; } else if (event.item == 1) { new_event->motion.xrel = 0; new_event->motion.yrel = event.value; } new_event->motion.x = FS_ML_NO_ABSOLUTE_MOUSE_POS; new_event->motion.y = FS_ML_NO_ABSOLUTE_MOUSE_POS; fs_ml_post_event(new_event); // ManyMouseEventType type; // unsigned int device; // unsigned int item; // int value; // int minval; // int maxval; } else if (event.type == MANYMOUSE_EVENT_BUTTON) { db_log(input, "MANYMOUSE: EVENT_BUTTON " "device %d item %d value %d\n", event.device, event.item, event.value); new_event = fs_ml_alloc_event(); new_event->type = event.value ? FS_ML_MOUSEBUTTONDOWN : FS_ML_MOUSEBUTTONUP; new_event->button.state = event.value != 0; new_event->button.device = g_first_manymouse_index + \ event.device; if (event.item == 0) { new_event->button.button = FS_ML_BUTTON_LEFT; } else if (event.item == 1) { new_event->button.button = FS_ML_BUTTON_RIGHT; } else if (event.item == 2) { new_event->button.button = FS_ML_BUTTON_MIDDLE; } else { new_event->button.button = 0; } fs_ml_post_event(new_event); } else if (event.type == MANYMOUSE_EVENT_ABSMOTION) { // printf("MANYMOUSE_EVENT_ABSMOTION\n"); } else if (event.type == MANYMOUSE_EVENT_SCROLL) { db_log(input, "MANYMOUSE: EVENT_SCROLL " "device %d item %d value %d\n", event.device, event.item, event.value); new_event = fs_ml_alloc_event(); new_event->type = FS_ML_MOUSEBUTTONDOWN; new_event->button.state = 1; new_event->button.device = g_first_manymouse_index + \ event.device; new_event->button.button = 0; if (event.item == 0) { if (event.value == 1) { new_event->button.button = FS_ML_BUTTON_WHEELUP; } else { new_event->button.button = FS_ML_BUTTON_WHEELDOWN; } } fs_ml_post_event(new_event); } } fs_ml_usleep(1000); } ManyMouse_Quit(); return NULL; }