static bool sdl2_gfx_read_viewport(void *data, uint8_t *buffer) { SDL_Surface *surf = NULL, *bgr24 = NULL; sdl2_video_t *vid = (sdl2_video_t*)data; RARCH_PERFORMANCE_INIT(sdl2_gfx_read_viewport); RARCH_PERFORMANCE_START(sdl2_gfx_read_viewport); video_driver_cached_frame(); surf = SDL_GetWindowSurface(vid->window); bgr24 = SDL_ConvertSurfaceFormat(surf, SDL_PIXELFORMAT_BGR24, 0); if (!bgr24) { RARCH_WARN("Failed to convert viewport data to BGR24: %s", SDL_GetError()); return false; } memcpy(buffer, bgr24->pixels, bgr24->h * bgr24->pitch); RARCH_PERFORMANCE_STOP(sdl2_gfx_read_viewport); return true; }
static bool take_screenshot_choice(const char *name_base, bool savestate, bool is_paused, bool is_idle, bool has_valid_framebuffer) { size_t old_pitch; unsigned old_width, old_height; bool ret = false; void *frame_data = NULL; const void* old_data = NULL; settings_t *settings = config_get_ptr(); const char *screenshot_dir = settings->paths.directory_screenshot; /* No way to infer screenshot directory. */ if ( string_is_empty(screenshot_dir) && string_is_empty(name_base)) return false; if (video_driver_supports_viewport_read()) { /* Avoid taking screenshot of GUI overlays. */ video_driver_set_texture_enable(false, false); if (!is_idle) video_driver_cached_frame(); #if defined(VITA) return take_screenshot_raw(name_base, NULL, savestate, is_idle, is_paused); #else return take_screenshot_viewport(name_base, savestate, is_idle, is_paused); #endif } if (!has_valid_framebuffer) return take_screenshot_raw(name_base, NULL, savestate, is_idle, is_paused); if (!video_driver_supports_read_frame_raw()) return false; video_driver_cached_frame_get(&old_data, &old_width, &old_height, &old_pitch); frame_data = video_driver_read_frame_raw( &old_width, &old_height, &old_pitch); video_driver_cached_frame_set(old_data, old_width, old_height, old_pitch); if (frame_data) { video_driver_set_cached_frame_ptr(frame_data); if (take_screenshot_raw(name_base, frame_data, savestate, is_idle, is_paused)) ret = true; } return ret; }
/** * check_slowmotion: * @slowmotion_pressed : was slow motion key pressed or held? * * Checks if slowmotion toggle/hold was being pressed and/or held. **/ static void check_slowmotion(settings_t *settings, global_t *global, runloop_t *runloop, bool slowmotion_pressed) { runloop->is_slowmotion = slowmotion_pressed; if (!runloop->is_slowmotion) return; if (settings->video.black_frame_insertion) video_driver_cached_frame(); if (global->rewind.frame_is_reverse) rarch_main_msg_queue_push_new(MSG_SLOW_MOTION_REWIND, 0, 30, true); else rarch_main_msg_queue_push_new(MSG_SLOW_MOTION, 0, 30, true); }
bool take_screenshot(const char *name_base, bool silence, bool has_valid_framebuffer) { bool is_paused = false; bool is_idle = false; bool is_slowmotion = false; bool is_perfcnt_enable = false; bool ret = false; runloop_get_status(&is_paused, &is_idle, &is_slowmotion, &is_perfcnt_enable); ret = take_screenshot_choice(name_base, silence, is_paused, is_idle, has_valid_framebuffer); if (is_paused && !is_idle) video_driver_cached_frame(); return ret; }
static int do_pause_state_checks( bool frameadvance_pressed, bool fullscreen_toggle_pressed, bool rewind_pressed) { bool check_is_oneshot = frameadvance_pressed || rewind_pressed; if (!main_is_paused) return 0; if (fullscreen_toggle_pressed) { event_command(EVENT_CMD_FULLSCREEN_TOGGLE); video_driver_cached_frame(); } if (!check_is_oneshot) return 1; return 0; }
static bool gl1_renderchain_read_viewport( void *data, void *chain_data, uint8_t *buffer, bool is_idle) { unsigned num_pixels = 0; gl_t *gl = (gl_t*)data; if (!gl) return false; num_pixels = gl->vp.width * gl->vp.height; /* Use slow synchronous readbacks. Use this with plain screenshots as we don't really care about performance in this case. */ /* GL1 only guarantees GL_RGBA/GL_UNSIGNED_BYTE * readbacks so do just that. * GL1 also doesn't support reading back data * from front buffer, so render a cached frame * and have gl_frame() do the readback while it's * in the back buffer. */ gl->readback_buffer_screenshot = malloc(num_pixels * sizeof(uint32_t)); if (!gl->readback_buffer_screenshot) return false; if (!is_idle) video_driver_cached_frame(); video_frame_convert_rgba_to_bgr( (const void*)gl->readback_buffer_screenshot, buffer, num_pixels); free(gl->readback_buffer_screenshot); gl->readback_buffer_screenshot = NULL; return true; }
/** ** menu_display_fb: * * Draws menu graphics onscreen. **/ void menu_display_fb(void) { driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); video_driver_set_texture_enable(true, false); if (!settings->menu.pause_libretro) { if (global->main_is_init && !global->libretro_dummy) { bool block_libretro_input = driver->block_libretro_input; driver->block_libretro_input = true; pretro_run(); driver->block_libretro_input = block_libretro_input; return; } } video_driver_cached_frame(); }
bool core_run(void) { #ifdef HAVE_NETWORKING if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_PRE_FRAME, NULL)) { /* Paused due to netplay. We must poll and display something so that a * netplay peer pausing doesn't just hang. */ input_poll(); video_driver_cached_frame(); return true; } #endif switch (current_core.poll_type) { case POLL_TYPE_EARLY: input_poll(); break; case POLL_TYPE_LATE: current_core.input_polled = false; break; default: break; } current_core.retro_run(); if (current_core.poll_type == POLL_TYPE_LATE && !current_core.input_polled) input_poll(); #ifdef HAVE_NETWORKING netplay_driver_ctl(RARCH_NETPLAY_CTL_POST_FRAME, NULL); #endif return true; }
static bool gl1_gfx_read_viewport(void *data, uint8_t *buffer, bool is_idle) { unsigned num_pixels = 0; gl1_t *gl1 = (gl1_t*)data; if (!gl1) return false; gl1_context_bind_hw_render(gl1, false); num_pixels = gl1->vp.width * gl1->vp.height; gl1->readback_buffer_screenshot = malloc(num_pixels * sizeof(uint32_t)); if (!gl1->readback_buffer_screenshot) goto error; if (!is_idle) video_driver_cached_frame(); video_frame_convert_rgba_to_bgr( (const void*)gl1->readback_buffer_screenshot, buffer, num_pixels); free(gl1->readback_buffer_screenshot); gl1->readback_buffer_screenshot = NULL; gl1_context_bind_hw_render(gl1, true); return true; error: gl1_context_bind_hw_render(gl1, true); return false; }
/** * event_command: * @cmd : Event command index. * * Performs RetroArch event command with index @cmd. * * Returns: true (1) on success, otherwise false (0). **/ bool event_command(enum event_command cmd) { unsigned i = 0; bool boolean = false; runloop_t *runloop = rarch_main_get_ptr(); driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); rarch_system_info_t *system = rarch_system_info_get_ptr(); (void)i; switch (cmd) { case EVENT_CMD_LOAD_CONTENT_PERSIST: #ifdef HAVE_DYNAMIC event_command(EVENT_CMD_LOAD_CORE); #endif rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT); break; #ifdef HAVE_FFMPEG case EVENT_CMD_LOAD_CONTENT_FFMPEG: rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG); break; #endif case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER: rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER); break; case EVENT_CMD_LOAD_CONTENT: #ifdef HAVE_DYNAMIC event_command(EVENT_CMD_LOAD_CONTENT_PERSIST); #else rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)settings->libretro); rarch_environment_cb(RETRO_ENVIRONMENT_EXEC, (void*)global->fullpath); event_command(EVENT_CMD_QUIT); #endif break; case EVENT_CMD_LOAD_CORE_DEINIT: #ifdef HAVE_DYNAMIC libretro_free_system_info(&global->menu.info); #endif break; case EVENT_CMD_LOAD_CORE_PERSIST: event_command(EVENT_CMD_LOAD_CORE_DEINIT); { #ifdef HAVE_MENU menu_handle_t *menu = menu_driver_get_ptr(); if (menu) event_update_system_info(&global->menu.info, &menu->load_no_content); #endif } break; case EVENT_CMD_LOAD_CORE: event_command(EVENT_CMD_LOAD_CORE_PERSIST); #ifndef HAVE_DYNAMIC event_command(EVENT_CMD_QUIT); #endif break; case EVENT_CMD_LOAD_STATE: /* Immutable - disallow savestate load when * we absolutely cannot change game state. */ if (global->bsv.movie) return false; #ifdef HAVE_NETPLAY if (driver->netplay_data) return false; #endif event_main_state(cmd); break; case EVENT_CMD_RESIZE_WINDOWED_SCALE: if (global->pending.windowed_scale == 0) return false; settings->video.scale = global->pending.windowed_scale; if (!settings->video.fullscreen) event_command(EVENT_CMD_REINIT); global->pending.windowed_scale = 0; break; case EVENT_CMD_MENU_TOGGLE: if (menu_driver_alive()) rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED); else rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING); break; case EVENT_CMD_CONTROLLERS_INIT: event_init_controllers(); break; case EVENT_CMD_RESET: RARCH_LOG(RETRO_LOG_RESETTING_CONTENT); rarch_main_msg_queue_push("Reset.", 1, 120, true); pretro_reset(); /* bSNES since v073r01 resets controllers to JOYPAD * after a reset, so just enforce it here. */ event_command(EVENT_CMD_CONTROLLERS_INIT); break; case EVENT_CMD_SAVE_STATE: if (settings->savestate_auto_index) settings->state_slot++; event_main_state(cmd); break; case EVENT_CMD_TAKE_SCREENSHOT: if (!take_screenshot()) return false; break; case EVENT_CMD_PREPARE_DUMMY: { #ifdef HAVE_MENU menu_handle_t *menu = menu_driver_get_ptr(); if (menu) menu->load_no_content = false; #endif rarch_main_data_deinit(); *global->fullpath = '\0'; rarch_main_set_state(RARCH_ACTION_STATE_LOAD_CONTENT); } break; case EVENT_CMD_UNLOAD_CORE: event_command(EVENT_CMD_PREPARE_DUMMY); event_command(EVENT_CMD_LOAD_CORE_DEINIT); break; case EVENT_CMD_QUIT: rarch_main_set_state(RARCH_ACTION_STATE_QUIT); break; case EVENT_CMD_REINIT: { const struct retro_hw_render_callback *hw_render = (const struct retro_hw_render_callback*)video_driver_callback(); driver->video_cache_context = hw_render->cache_context; driver->video_cache_context_ack = false; event_command(EVENT_CMD_RESET_CONTEXT); driver->video_cache_context = false; /* Poll input to avoid possibly stale data to corrupt things. */ input_driver_poll(); #ifdef HAVE_MENU menu_display_fb_set_dirty(); if (menu_driver_alive()) event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE); #endif } break; case EVENT_CMD_CHEATS_DEINIT: if (!global) break; if (global->cheat) cheat_manager_free(global->cheat); global->cheat = NULL; break; case EVENT_CMD_CHEATS_INIT: event_command(EVENT_CMD_CHEATS_DEINIT); event_init_cheats(); break; case EVENT_CMD_REMAPPING_DEINIT: break; case EVENT_CMD_REMAPPING_INIT: event_command(EVENT_CMD_REMAPPING_DEINIT); event_init_remapping(); break; case EVENT_CMD_REWIND_DEINIT: if (!global) break; #ifdef HAVE_NETPLAY if (driver->netplay_data) return false; #endif if (global->rewind.state) state_manager_free(global->rewind.state); global->rewind.state = NULL; break; case EVENT_CMD_REWIND_INIT: init_rewind(); break; case EVENT_CMD_REWIND_TOGGLE: if (settings->rewind_enable) event_command(EVENT_CMD_REWIND_INIT); else event_command(EVENT_CMD_REWIND_DEINIT); break; case EVENT_CMD_AUTOSAVE_DEINIT: #ifdef HAVE_THREADS event_deinit_autosave(); #endif break; case EVENT_CMD_AUTOSAVE_INIT: event_command(EVENT_CMD_AUTOSAVE_DEINIT); #ifdef HAVE_THREADS event_init_autosave(); #endif break; case EVENT_CMD_AUTOSAVE_STATE: event_save_auto_state(); break; case EVENT_CMD_AUDIO_STOP: if (!driver->audio_data) return false; if (!audio_driver_alive()) return false; if (!audio_driver_stop()) return false; break; case EVENT_CMD_AUDIO_START: if (!driver->audio_data || audio_driver_alive()) return false; if (!settings->audio.mute_enable && !audio_driver_start()) { RARCH_ERR("Failed to start audio driver. Will continue without audio.\n"); driver->audio_active = false; } break; case EVENT_CMD_AUDIO_MUTE_TOGGLE: { const char *msg = !settings->audio.mute_enable ? "Audio muted." : "Audio unmuted."; if (!audio_driver_mute_toggle()) { RARCH_ERR("Failed to unmute audio.\n"); return false; } rarch_main_msg_queue_push(msg, 1, 180, true); RARCH_LOG("%s\n", msg); } break; case EVENT_CMD_OVERLAY_DEINIT: #ifdef HAVE_OVERLAY if (driver->overlay) input_overlay_free(driver->overlay); driver->overlay = NULL; memset(&driver->overlay_state, 0, sizeof(driver->overlay_state)); #endif break; case EVENT_CMD_OVERLAY_INIT: event_command(EVENT_CMD_OVERLAY_DEINIT); #ifdef HAVE_OVERLAY if (driver->osk_enable) { if (!*settings->osk.overlay) break; } else { if (!*settings->input.overlay) break; } driver->overlay = input_overlay_new(driver->osk_enable ? settings->osk.overlay : settings->input.overlay, driver->osk_enable ? settings->osk.enable : settings->input.overlay_enable, settings->input.overlay_opacity, settings->input.overlay_scale); if (!driver->overlay) RARCH_ERR("Failed to load overlay.\n"); #endif break; case EVENT_CMD_OVERLAY_NEXT: #ifdef HAVE_OVERLAY input_overlay_next(driver->overlay, settings->input.overlay_opacity); #endif break; case EVENT_CMD_DSP_FILTER_DEINIT: if (!global) break; audio_driver_dsp_filter_free(); break; case EVENT_CMD_DSP_FILTER_INIT: event_command(EVENT_CMD_DSP_FILTER_DEINIT); if (!*settings->audio.dsp_plugin) break; audio_driver_dsp_filter_init(settings->audio.dsp_plugin); break; case EVENT_CMD_GPU_RECORD_DEINIT: if (!global) break; if (global->record.gpu_buffer) free(global->record.gpu_buffer); global->record.gpu_buffer = NULL; break; case EVENT_CMD_RECORD_DEINIT: if (!recording_deinit()) return false; break; case EVENT_CMD_RECORD_INIT: event_command(EVENT_CMD_HISTORY_DEINIT); if (!recording_init()) return false; break; case EVENT_CMD_HISTORY_DEINIT: if (g_defaults.history) { content_playlist_write_file(g_defaults.history); content_playlist_free(g_defaults.history); } g_defaults.history = NULL; break; case EVENT_CMD_HISTORY_INIT: event_command(EVENT_CMD_HISTORY_DEINIT); if (!settings->history_list_enable) return false; RARCH_LOG("Loading history file: [%s].\n", settings->content_history_path); g_defaults.history = content_playlist_init( settings->content_history_path, settings->content_history_size); break; case EVENT_CMD_CORE_INFO_DEINIT: if (!global) break; if (global->core_info) core_info_list_free(global->core_info); global->core_info = NULL; break; case EVENT_CMD_DATA_RUNLOOP_FREE: rarch_main_data_free(); break; case EVENT_CMD_CORE_INFO_INIT: event_command(EVENT_CMD_CORE_INFO_DEINIT); if (*settings->libretro_directory) global->core_info = core_info_list_new(); break; case EVENT_CMD_CORE_DEINIT: { struct retro_hw_render_callback *cb = video_driver_callback(); event_deinit_core(true); if (cb) memset(cb, 0, sizeof(*cb)); break; } case EVENT_CMD_CORE_INIT: if (!event_init_core()) return false; break; case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES: video_driver_apply_state_changes(); break; case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE: boolean = true; /* fall-through */ case EVENT_CMD_VIDEO_SET_BLOCKING_STATE: video_driver_set_nonblock_state(boolean); break; case EVENT_CMD_VIDEO_SET_ASPECT_RATIO: video_driver_set_aspect_ratio(settings->video.aspect_ratio_idx); break; case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE: boolean = true; /* fall-through */ case EVENT_CMD_AUDIO_SET_BLOCKING_STATE: audio_driver_set_nonblock_state(boolean); break; case EVENT_CMD_OVERLAY_SET_SCALE_FACTOR: #ifdef HAVE_OVERLAY input_overlay_set_scale_factor(driver->overlay, settings->input.overlay_scale); #endif break; case EVENT_CMD_OVERLAY_SET_ALPHA_MOD: #ifdef HAVE_OVERLAY input_overlay_set_alpha_mod(driver->overlay, settings->input.overlay_opacity); #endif break; case EVENT_CMD_DRIVERS_DEINIT: uninit_drivers(DRIVERS_CMD_ALL); break; case EVENT_CMD_DRIVERS_INIT: init_drivers(DRIVERS_CMD_ALL); break; case EVENT_CMD_AUDIO_REINIT: uninit_drivers(DRIVER_AUDIO); init_drivers(DRIVER_AUDIO); break; case EVENT_CMD_RESET_CONTEXT: event_command(EVENT_CMD_DRIVERS_DEINIT); event_command(EVENT_CMD_DRIVERS_INIT); break; case EVENT_CMD_QUIT_RETROARCH: rarch_main_set_state(RARCH_ACTION_STATE_FORCE_QUIT); break; case EVENT_CMD_RESUME: rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED); break; case EVENT_CMD_RESTART_RETROARCH: #if defined(GEKKO) && defined(HW_RVL) fill_pathname_join(global->fullpath, g_defaults.core_dir, SALAMANDER_FILE, sizeof(global->fullpath)); #endif if (driver->frontend_ctx && driver->frontend_ctx->set_fork) driver->frontend_ctx->set_fork(true, false); break; case EVENT_CMD_MENU_SAVE_CONFIG: if (!event_save_core_config()) return false; break; case EVENT_CMD_SHADERS_APPLY_CHANGES: #ifdef HAVE_MENU menu_shader_manager_apply_changes(); #endif break; case EVENT_CMD_PAUSE_CHECKS: if (runloop->is_paused) { RARCH_LOG("Paused.\n"); event_command(EVENT_CMD_AUDIO_STOP); if (settings->video.black_frame_insertion) video_driver_cached_frame(); } else { RARCH_LOG("Unpaused.\n"); event_command(EVENT_CMD_AUDIO_START); } break; case EVENT_CMD_PAUSE_TOGGLE: runloop->is_paused = !runloop->is_paused; event_command(EVENT_CMD_PAUSE_CHECKS); break; case EVENT_CMD_UNPAUSE: runloop->is_paused = false; event_command(EVENT_CMD_PAUSE_CHECKS); break; case EVENT_CMD_PAUSE: runloop->is_paused = true; event_command(EVENT_CMD_PAUSE_CHECKS); break; case EVENT_CMD_MENU_PAUSE_LIBRETRO: if (menu_driver_alive()) { if (settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_STOP); else event_command(EVENT_CMD_AUDIO_START); } else { if (settings->menu.pause_libretro) event_command(EVENT_CMD_AUDIO_START); } break; case EVENT_CMD_SHADER_DIR_DEINIT: if (!global) break; dir_list_free(global->shader_dir.list); global->shader_dir.list = NULL; global->shader_dir.ptr = 0; break; case EVENT_CMD_SHADER_DIR_INIT: event_command(EVENT_CMD_SHADER_DIR_DEINIT); if (!*settings->video.shader_dir) return false; global->shader_dir.list = dir_list_new_special(NULL, DIR_LIST_SHADERS); if (!global->shader_dir.list || global->shader_dir.list->size == 0) { event_command(EVENT_CMD_SHADER_DIR_DEINIT); return false; } global->shader_dir.ptr = 0; dir_list_sort(global->shader_dir.list, false); for (i = 0; i < global->shader_dir.list->size; i++) RARCH_LOG("Found shader \"%s\"\n", global->shader_dir.list->elems[i].data); break; case EVENT_CMD_SAVEFILES: event_save_files(); break; case EVENT_CMD_SAVEFILES_DEINIT: if (!global) break; if (global->savefiles) string_list_free(global->savefiles); global->savefiles = NULL; break; case EVENT_CMD_SAVEFILES_INIT: global->use_sram = global->use_sram && !global->sram_save_disable #ifdef HAVE_NETPLAY && (!driver->netplay_data || !global->netplay_is_client) #endif ; if (!global->use_sram) RARCH_LOG("SRAM will not be saved.\n"); if (global->use_sram) event_command(EVENT_CMD_AUTOSAVE_INIT); break; case EVENT_CMD_MSG_QUEUE_DEINIT: rarch_main_msg_queue_free(); break; case EVENT_CMD_MSG_QUEUE_INIT: event_command(EVENT_CMD_MSG_QUEUE_DEINIT); rarch_main_msg_queue_init(); rarch_main_data_init_queues(); break; case EVENT_CMD_BSV_MOVIE_DEINIT: if (!global) break; if (global->bsv.movie) bsv_movie_free(global->bsv.movie); global->bsv.movie = NULL; break; case EVENT_CMD_BSV_MOVIE_INIT: event_command(EVENT_CMD_BSV_MOVIE_DEINIT); event_init_movie(); break; case EVENT_CMD_NETPLAY_DEINIT: #ifdef HAVE_NETPLAY deinit_netplay(); #endif break; case EVENT_CMD_NETWORK_DEINIT: #ifdef HAVE_NETWORKING network_deinit(); #endif break; case EVENT_CMD_NETWORK_INIT: #ifdef HAVE_NETWORKING network_init(); #endif break; case EVENT_CMD_NETPLAY_INIT: event_command(EVENT_CMD_NETPLAY_DEINIT); #ifdef HAVE_NETPLAY if (!init_netplay()) return false; #endif break; case EVENT_CMD_NETPLAY_FLIP_PLAYERS: #ifdef HAVE_NETPLAY { netplay_t *netplay = (netplay_t*)driver->netplay_data; if (!netplay) return false; netplay_flip_users(netplay); } #endif break; case EVENT_CMD_FULLSCREEN_TOGGLE: if (!video_driver_has_windowed()) return false; /* If we go fullscreen we drop all drivers and * reinitialize to be safe. */ settings->video.fullscreen = !settings->video.fullscreen; event_command(EVENT_CMD_REINIT); break; case EVENT_CMD_COMMAND_DEINIT: #ifdef HAVE_COMMAND if (driver->command) rarch_cmd_free(driver->command); driver->command = NULL; #endif break; case EVENT_CMD_COMMAND_INIT: event_command(EVENT_CMD_COMMAND_DEINIT); #ifdef HAVE_COMMAND event_init_command(); #endif break; case EVENT_CMD_TEMPORARY_CONTENT_DEINIT: if (!global) break; if (global->temporary_content) event_free_temporary_content(); global->temporary_content = NULL; break; case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT: if (!global) break; if (global->subsystem_fullpaths) string_list_free(global->subsystem_fullpaths); global->subsystem_fullpaths = NULL; break; case EVENT_CMD_LOG_FILE_DEINIT: if (!global) break; if (global->log_file && global->log_file != stderr) fclose(global->log_file); global->log_file = NULL; break; case EVENT_CMD_DISK_EJECT_TOGGLE: if (system && system->disk_control.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &system->disk_control; if (control) event_check_disk_eject(control); } else rarch_main_msg_queue_push("Core does not support Disk Options.", 1, 120, true); break; case EVENT_CMD_DISK_NEXT: if (system && system->disk_control.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &system->disk_control; if (!control) return false; if (!control->get_eject_state()) return false; event_check_disk_next(control); } else rarch_main_msg_queue_push("Core does not support Disk Options.", 1, 120, true); break; case EVENT_CMD_DISK_PREV: if (system && system->disk_control.get_num_images) { const struct retro_disk_control_callback *control = (const struct retro_disk_control_callback*) &system->disk_control; if (!control) return false; if (!control->get_eject_state()) return false; event_check_disk_prev(control); } else rarch_main_msg_queue_push("Core does not support Disk Options.", 1, 120, true); break; case EVENT_CMD_RUMBLE_STOP: for (i = 0; i < MAX_USERS; i++) { input_driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0); input_driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0); } break; case EVENT_CMD_GRAB_MOUSE_TOGGLE: { static bool grab_mouse_state = false; grab_mouse_state = !grab_mouse_state; if (!driver->input || !input_driver_grab_mouse(grab_mouse_state)) return false; RARCH_LOG("Grab mouse state: %s.\n", grab_mouse_state ? "yes" : "no"); video_driver_show_mouse(!grab_mouse_state); } break; case EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG: rarch_perf_log(); break; case EVENT_CMD_VOLUME_UP: event_set_volume(0.5f); break; case EVENT_CMD_VOLUME_DOWN: event_set_volume(-0.5f); break; case EVENT_CMD_NONE: default: goto error; } return true; error: return false; }
bool rarch_main_ctl(enum rarch_main_ctl_state state, void *data) { driver_t *driver = driver_get_ptr(); settings_t *settings = config_get_ptr(); global_t *global = global_get_ptr(); switch (state) { case RARCH_MAIN_CTL_CHECK_STATE: { event_cmd_state_t *cmd = (event_cmd_state_t*)data; if (!cmd || main_is_idle) return false; if (cmd->screenshot_pressed) event_command(EVENT_CMD_TAKE_SCREENSHOT); if (cmd->mute_pressed) event_command(EVENT_CMD_AUDIO_MUTE_TOGGLE); if (cmd->osk_pressed) driver->keyboard_linefeed_enable = !driver->keyboard_linefeed_enable; if (cmd->volume_up_pressed) event_command(EVENT_CMD_VOLUME_UP); else if (cmd->volume_down_pressed) event_command(EVENT_CMD_VOLUME_DOWN); #ifdef HAVE_NETPLAY if (driver->netplay_data) { if (cmd->netplay_flip_pressed) event_command(EVENT_CMD_NETPLAY_FLIP_PLAYERS); if (cmd->fullscreen_toggle) event_command(EVENT_CMD_FULLSCREEN_TOGGLE); break; } #endif check_pause(driver, settings, cmd->pause_pressed, cmd->frameadvance_pressed); if (!rarch_main_ctl(RARCH_MAIN_CTL_CHECK_PAUSE_STATE, cmd)) return false; check_fast_forward_button(driver, cmd->fastforward_pressed, cmd->hold_pressed, cmd->old_hold_pressed); check_stateslots(settings, cmd->state_slot_increase, cmd->state_slot_decrease); if (cmd->save_state_pressed) event_command(EVENT_CMD_SAVE_STATE); else if (cmd->load_state_pressed) event_command(EVENT_CMD_LOAD_STATE); check_rewind(settings, global, cmd->rewind_pressed); rarch_main_ctl(RARCH_MAIN_CTL_CHECK_SLOWMOTION, &cmd->slowmotion_pressed); if (cmd->movie_record) rarch_main_ctl(RARCH_MAIN_CTL_CHECK_MOVIE, NULL); check_shader_dir(global, cmd->shader_next_pressed, cmd->shader_prev_pressed); if (cmd->disk_eject_pressed) event_command(EVENT_CMD_DISK_EJECT_TOGGLE); else if (cmd->disk_next_pressed) event_command(EVENT_CMD_DISK_NEXT); else if (cmd->disk_prev_pressed) event_command(EVENT_CMD_DISK_PREV); if (cmd->reset_pressed) event_command(EVENT_CMD_RESET); if (global->cheat) { if (cmd->cheat_index_plus_pressed) cheat_manager_index_next(global->cheat); else if (cmd->cheat_index_minus_pressed) cheat_manager_index_prev(global->cheat); else if (cmd->cheat_toggle_pressed) cheat_manager_toggle(global->cheat); } } break; case RARCH_MAIN_CTL_CHECK_PAUSE_STATE: { bool check_is_oneshot; event_cmd_state_t *cmd = (event_cmd_state_t*)data; if (!cmd) return false; check_is_oneshot = cmd->frameadvance_pressed || cmd->rewind_pressed; if (!main_is_paused) return true; if (cmd->fullscreen_toggle) { event_command(EVENT_CMD_FULLSCREEN_TOGGLE); video_driver_cached_frame(); } if (!check_is_oneshot) return false; } break; case RARCH_MAIN_CTL_CHECK_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; main_is_slowmotion = *ptr; if (!main_is_slowmotion) return false; if (settings->video.black_frame_insertion) video_driver_cached_frame(); if (state_manager_frame_is_reversed()) rarch_main_msg_queue_push_new(MSG_SLOW_MOTION_REWIND, 0, 30, true); else rarch_main_msg_queue_push_new(MSG_SLOW_MOTION, 0, 30, true); } break; case RARCH_MAIN_CTL_CHECK_MOVIE: if (global->bsv.movie_playback) return rarch_main_ctl(RARCH_MAIN_CTL_CHECK_MOVIE_PLAYBACK, NULL); if (!global->bsv.movie) return rarch_main_ctl(RARCH_MAIN_CTL_CHECK_MOVIE_INIT, NULL); return rarch_main_ctl(RARCH_MAIN_CTL_CHECK_MOVIE_RECORD, NULL); case RARCH_MAIN_CTL_CHECK_MOVIE_RECORD: if (!global->bsv.movie) return false; rarch_main_msg_queue_push_new( MSG_MOVIE_RECORD_STOPPED, 2, 180, true); RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED)); event_command(EVENT_CMD_BSV_MOVIE_DEINIT); break; case RARCH_MAIN_CTL_CHECK_MOVIE_INIT: if (global->bsv.movie) return false; { char path[PATH_MAX_LENGTH], msg[PATH_MAX_LENGTH]; settings->rewind_granularity = 1; if (settings->state_slot > 0) snprintf(path, sizeof(path), "%s%d", global->bsv.movie_path, settings->state_slot); else strlcpy(path, global->bsv.movie_path, sizeof(path)); strlcat(path, ".bsv", sizeof(path)); snprintf(msg, sizeof(msg), "%s \"%s\".", msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO), path); global->bsv.movie = bsv_movie_init(path, RARCH_MOVIE_RECORD); if (!global->bsv.movie) return false; else if (global->bsv.movie) { rarch_main_msg_queue_push(msg, 1, 180, true); RARCH_LOG("%s \"%s\".\n", msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO), path); } else { rarch_main_msg_queue_push_new( MSG_FAILED_TO_START_MOVIE_RECORD, 1, 180, true); RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD)); } } break; case RARCH_MAIN_CTL_CHECK_MOVIE_PLAYBACK: if (!global->bsv.movie_end) return false; rarch_main_msg_queue_push_new( MSG_MOVIE_PLAYBACK_ENDED, 1, 180, false); RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED)); event_command(EVENT_CMD_BSV_MOVIE_DEINIT); global->bsv.movie_end = false; global->bsv.movie_playback = false; break; case RARCH_MAIN_CTL_STATE_FREE: main_is_idle = false; main_is_paused = false; main_is_slowmotion = false; frame_limit_last_time = 0.0; main_max_frames = 0; break; case RARCH_MAIN_CTL_GLOBAL_FREE: event_command(EVENT_CMD_TEMPORARY_CONTENT_DEINIT); event_command(EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT); event_command(EVENT_CMD_RECORD_DEINIT); event_command(EVENT_CMD_LOG_FILE_DEINIT); memset(&g_extern, 0, sizeof(g_extern)); break; case RARCH_MAIN_CTL_CLEAR_STATE: driver_clear_state(); rarch_main_ctl(RARCH_MAIN_CTL_STATE_FREE, NULL); rarch_main_ctl(RARCH_MAIN_CTL_GLOBAL_FREE, NULL); break; case RARCH_MAIN_CTL_SET_MAX_FRAMES: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; main_max_frames = *ptr; } break; case RARCH_MAIN_CTL_SET_FRAME_LIMIT_LAST_TIME: { struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); float fastforward_ratio = settings->fastforward_ratio; if (fastforward_ratio == 0.0f) fastforward_ratio = 1.0f; frame_limit_last_time = retro_get_time_usec(); frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f / (av_info->timing.fps * fastforward_ratio)); } break; case RARCH_MAIN_CTL_IS_IDLE: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = main_is_idle; } break; case RARCH_MAIN_CTL_SET_IDLE: { bool *ptr = (bool*)data; if (!ptr) return false; main_is_idle = *ptr; } break; case RARCH_MAIN_CTL_IS_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = main_is_slowmotion; } break; case RARCH_MAIN_CTL_SET_SLOWMOTION: { bool *ptr = (bool*)data; if (!ptr) return false; main_is_slowmotion = *ptr; } break; case RARCH_MAIN_CTL_SET_PAUSED: { bool *ptr = (bool*)data; if (!ptr) return false; main_is_paused = *ptr; } break; case RARCH_MAIN_CTL_IS_PAUSED: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = main_is_paused; } break; default: return false; } return true; }
static bool gl2_renderchain_read_viewport( void *data, void *chain_data, uint8_t *buffer, bool is_idle) { unsigned num_pixels = 0; gl_t *gl = (gl_t*)data; if (!gl) return false; context_bind_hw_render(false); num_pixels = gl->vp.width * gl->vp.height; #ifdef HAVE_GL_ASYNC_READBACK if (gl->pbo_readback_enable) { const uint8_t *ptr = NULL; /* Don't readback if we're in menu mode. * We haven't buffered up enough frames yet, come back later. */ if (!gl->pbo_readback_valid[gl->pbo_readback_index]) goto error; gl->pbo_readback_valid[gl->pbo_readback_index] = false; glBindBuffer(GL_PIXEL_PACK_BUFFER, gl->pbo_readback[gl->pbo_readback_index]); #ifdef HAVE_OPENGLES3 /* Slower path, but should work on all implementations at least. */ ptr = (const uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, num_pixels * sizeof(uint32_t), GL_MAP_READ_BIT); if (ptr) { unsigned y; for (y = 0; y < gl->vp.height; y++) { video_frame_convert_rgba_to_bgr( (const void*)ptr, buffer, gl->vp.width); } } #else ptr = (const uint8_t*)glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY); if (ptr) { struct scaler_ctx *ctx = &gl->pbo_readback_scaler; scaler_ctx_scale_direct(ctx, buffer, ptr); } #endif if (!ptr) { RARCH_ERR("[GL]: Failed to map pixel unpack buffer.\n"); goto error; } glUnmapBuffer(GL_PIXEL_PACK_BUFFER); glBindBuffer(GL_PIXEL_PACK_BUFFER, 0); } else #endif { /* Use slow synchronous readbacks. Use this with plain screenshots as we don't really care about performance in this case. */ /* GLES2 only guarantees GL_RGBA/GL_UNSIGNED_BYTE * readbacks so do just that. * GLES2 also doesn't support reading back data * from front buffer, so render a cached frame * and have gl_frame() do the readback while it's * in the back buffer. * * Keep codepath similar for GLES and desktop GL. */ gl->readback_buffer_screenshot = malloc(num_pixels * sizeof(uint32_t)); if (!gl->readback_buffer_screenshot) goto error; if (!is_idle) video_driver_cached_frame(); video_frame_convert_rgba_to_bgr( (const void*)gl->readback_buffer_screenshot, buffer, num_pixels); free(gl->readback_buffer_screenshot); gl->readback_buffer_screenshot = NULL; } context_bind_hw_render(true); return true; error: context_bind_hw_render(true); return false; }
static enum runloop_state runloop_check_state( settings_t *settings, uint64_t current_input, uint64_t old_input, unsigned *sleep_ms) { static bool old_focus = true; #ifdef HAVE_OVERLAY static char prev_overlay_restore = false; bool osk_enable = input_driver_is_onscreen_keyboard_enabled(); #endif #ifdef HAVE_NETWORKING bool tmp = false; #endif bool focused = true; uint64_t trigger_input = current_input & ~old_input; bool pause_pressed = runloop_cmd_triggered(trigger_input, RARCH_PAUSE_TOGGLE); if (input_driver_is_flushing_input()) { input_driver_unset_flushing_input(); if (current_input) { current_input = 0; /* If core was paused before entering menu, evoke * pause toggle to wake it up. */ if (runloop_paused) BIT64_SET(current_input, RARCH_PAUSE_TOGGLE); input_driver_set_flushing_input(); } } if (runloop_cmd_triggered(trigger_input, RARCH_OVERLAY_NEXT)) command_event(CMD_EVENT_OVERLAY_NEXT, NULL); if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY)) { bool fullscreen_toggled = !runloop_paused; #ifdef HAVE_MENU fullscreen_toggled = fullscreen_toggled || menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL); #endif if (fullscreen_toggled) command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); } if (runloop_cmd_triggered(trigger_input, RARCH_GRAB_MOUSE_TOGGLE)) command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL); #ifdef HAVE_OVERLAY if (osk_enable && !input_keyboard_ctl( RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) { input_driver_unset_onscreen_keyboard_enabled(); prev_overlay_restore = true; command_event(CMD_EVENT_OVERLAY_DEINIT, NULL); } else if (!osk_enable && input_keyboard_ctl( RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) { input_driver_set_onscreen_keyboard_enabled(); prev_overlay_restore = false; command_event(CMD_EVENT_OVERLAY_INIT, NULL); } else if (prev_overlay_restore) { if (!settings->input.overlay_hide_in_menu) command_event(CMD_EVENT_OVERLAY_INIT, NULL); prev_overlay_restore = false; } #endif if (runloop_iterate_time_to_exit( runloop_cmd_press(current_input, RARCH_QUIT_KEY)) != 1) return RUNLOOP_STATE_QUIT; #ifdef HAVE_MENU if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { menu_ctx_iterate_t iter; bool skip = false; #ifdef HAVE_OVERLAY skip = osk_enable && input_keyboard_return_pressed(); #endif if (!skip) { enum menu_action action = (enum menu_action)menu_event(current_input, trigger_input); bool focused = settings->pause_nonactive ? video_driver_is_focused() : true; focused = focused && !ui_companion_is_on_foreground(); iter.action = action; if (!menu_driver_ctl(RARCH_MENU_CTL_ITERATE, &iter)) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); if (focused || !runloop_idle) menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL); if (!focused) return RUNLOOP_STATE_SLEEP; if (action == MENU_ACTION_QUIT) return RUNLOOP_STATE_QUIT; } } #endif if (runloop_idle) return RUNLOOP_STATE_SLEEP; #ifdef HAVE_MENU if (menu_event_keyboard_is_set(RETROK_F1) == 1) { if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) { rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); menu_event_keyboard_set(false, RETROK_F1); } } } else if ((!menu_event_keyboard_is_set(RETROK_F1) && runloop_cmd_menu_press(current_input, old_input, trigger_input)) || rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) { if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL)) rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL); } else { menu_display_toggle_set_reason(MENU_TOGGLE_REASON_USER); rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL); } } else menu_event_keyboard_set(false, RETROK_F1); if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL)) { if (!settings->menu.throttle_framerate && !settings->fastforward_ratio) return RUNLOOP_STATE_MENU_ITERATE; return RUNLOOP_STATE_END; } #endif if (settings->pause_nonactive) focused = video_driver_is_focused(); if (runloop_cmd_triggered(trigger_input, RARCH_SCREENSHOT)) command_event(CMD_EVENT_TAKE_SCREENSHOT, NULL); if (runloop_cmd_triggered(trigger_input, RARCH_MUTE)) command_event(CMD_EVENT_AUDIO_MUTE_TOGGLE, NULL); if (runloop_cmd_triggered(trigger_input, RARCH_OSK)) { if (input_keyboard_ctl( RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL)) input_keyboard_ctl( RARCH_INPUT_KEYBOARD_CTL_UNSET_LINEFEED_ENABLED, NULL); else input_keyboard_ctl( RARCH_INPUT_KEYBOARD_CTL_SET_LINEFEED_ENABLED, NULL); } if (runloop_cmd_press(current_input, RARCH_VOLUME_UP)) command_event(CMD_EVENT_VOLUME_UP, NULL); else if (runloop_cmd_press(current_input, RARCH_VOLUME_DOWN)) command_event(CMD_EVENT_VOLUME_DOWN, NULL); #ifdef HAVE_NETWORKING tmp = runloop_cmd_triggered(trigger_input, RARCH_NETPLAY_FLIP); netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp); tmp = runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY); netplay_driver_ctl(RARCH_NETPLAY_CTL_FULLSCREEN_TOGGLE, &tmp); #endif /* Check if libretro pause key was pressed. If so, pause or * unpause the libretro core. */ /* FRAMEADVANCE will set us into pause mode. */ pause_pressed |= !runloop_paused && runloop_cmd_triggered(trigger_input, RARCH_FRAMEADVANCE); if (focused && pause_pressed) command_event(CMD_EVENT_PAUSE_TOGGLE, NULL); else if (focused && !old_focus) command_event(CMD_EVENT_UNPAUSE, NULL); else if (!focused && old_focus) command_event(CMD_EVENT_PAUSE, NULL); old_focus = focused; if (!focused) return RUNLOOP_STATE_SLEEP; if (runloop_paused) { /* check pause state */ bool check_is_oneshot = runloop_cmd_triggered(trigger_input, RARCH_FRAMEADVANCE) || runloop_cmd_press(current_input, RARCH_REWIND); if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY)) { command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL); if (!runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL)) video_driver_cached_frame(); } if (!check_is_oneshot) return RUNLOOP_STATE_SLEEP; } /* To avoid continous switching if we hold the button down, we require * that the button must go from pressed to unpressed back to pressed * to be able to toggle between then. */ if (runloop_cmd_triggered(trigger_input, RARCH_FAST_FORWARD_KEY)) { if (input_driver_is_nonblock_state()) input_driver_unset_nonblock_state(); else input_driver_set_nonblock_state(); driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL); } else if ((runloop_cmd_pressed(old_input, RARCH_FAST_FORWARD_HOLD_KEY) != runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY))) { if (runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY)) input_driver_set_nonblock_state(); else input_driver_unset_nonblock_state(); driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL); } /* Checks if the state increase/decrease keys have been pressed * for this frame. */ if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_PLUS)) { char msg[128]; msg[0] = '\0'; settings->state_slot++; snprintf(msg, sizeof(msg), "%s: %d", msg_hash_to_str(MSG_STATE_SLOT), settings->state_slot); runloop_msg_queue_push(msg, 2, 180, true); RARCH_LOG("%s\n", msg); } else if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_MINUS)) { char msg[128]; msg[0] = '\0'; if (settings->state_slot > 0) settings->state_slot--; snprintf(msg, sizeof(msg), "%s: %d", msg_hash_to_str(MSG_STATE_SLOT), settings->state_slot); runloop_msg_queue_push(msg, 2, 180, true); RARCH_LOG("%s\n", msg); } if (runloop_cmd_triggered(trigger_input, RARCH_SAVE_STATE_KEY)) command_event(CMD_EVENT_SAVE_STATE, NULL); else if (runloop_cmd_triggered(trigger_input, RARCH_LOAD_STATE_KEY)) command_event(CMD_EVENT_LOAD_STATE, NULL); #ifdef HAVE_CHEEVOS if (!settings->cheevos.hardcore_mode_enable) #endif state_manager_check_rewind(runloop_cmd_press(current_input, RARCH_REWIND)); runloop_slowmotion = runloop_cmd_press(current_input, RARCH_SLOWMOTION); if (runloop_slowmotion) { /* Checks if slowmotion toggle/hold was being pressed and/or held. */ if (settings->video.black_frame_insertion) { if (!runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL)) video_driver_cached_frame(); } if (state_manager_frame_is_reversed()) runloop_msg_queue_push(msg_hash_to_str(MSG_SLOW_MOTION_REWIND), 2, 30, true); else runloop_msg_queue_push(msg_hash_to_str(MSG_SLOW_MOTION), 2, 30, true); } if (runloop_cmd_triggered(trigger_input, RARCH_MOVIE_RECORD_TOGGLE)) bsv_movie_check(); if (runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT) || runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV)) dir_check_shader( runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT), runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV)); if (runloop_cmd_triggered(trigger_input, RARCH_DISK_EJECT_TOGGLE)) command_event(CMD_EVENT_DISK_EJECT_TOGGLE, NULL); else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_NEXT)) command_event(CMD_EVENT_DISK_NEXT, NULL); else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_PREV)) command_event(CMD_EVENT_DISK_PREV, NULL); if (runloop_cmd_triggered(trigger_input, RARCH_RESET)) command_event(CMD_EVENT_RESET, NULL); cheat_manager_state_checks( runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_PLUS), runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_MINUS), runloop_cmd_triggered(trigger_input, RARCH_CHEAT_TOGGLE)); return RUNLOOP_STATE_ITERATE; }
bool menu_display_ctl(enum menu_display_ctl_state state, void *data) { unsigned width, height; menu_framebuf_t *frame_buf = menu_display_fb_get_ptr(); menu_display_t *disp = menu_display_get_ptr(); settings_t *settings = config_get_ptr(); switch (state) { case MENU_DISPLAY_CTL_FONT_BUF: { void **ptr = (void**)data; if (!ptr) return false; *ptr = disp->font.buf; } return true; case MENU_DISPLAY_CTL_SET_FONT_BUF: { void **ptr = (void**)data; if (!ptr) return false; disp->font.buf = *ptr; } return true; case MENU_DISPLAY_CTL_FONT_FB: { uint8_t **ptr = (uint8_t**)data; if (!ptr) return false; *ptr = (uint8_t*)disp->font.framebuf; } return true; case MENU_DISPLAY_CTL_SET_FONT_FB: { uint8_t **ptr = (uint8_t**)data; if (!ptr) return false; disp->font.framebuf = *ptr; } return true; case MENU_DISPLAY_CTL_LIBRETRO_RUNNING: { global_t *global = global_get_ptr(); if (!settings->menu.pause_libretro) if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY)) return true; } break; case MENU_DISPLAY_CTL_LIBRETRO: video_driver_set_texture_enable(true, false); if (menu_display_ctl(MENU_DISPLAY_CTL_LIBRETRO_RUNNING, NULL)) { driver_t *driver = driver_get_ptr(); bool block_libretro_input = driver->block_libretro_input; driver->block_libretro_input = true; core.retro_run(); driver->block_libretro_input = block_libretro_input; return true; } video_driver_cached_frame(); return true; case MENU_DISPLAY_CTL_SET_WIDTH: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; frame_buf->width = *ptr; } return true; case MENU_DISPLAY_CTL_WIDTH: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = frame_buf->width; } return true; case MENU_DISPLAY_CTL_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = frame_buf->height; } return true; case MENU_DISPLAY_CTL_HEADER_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = disp->header_height; } return true; case MENU_DISPLAY_CTL_SET_HEADER_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; disp->header_height = *ptr; } return true; case MENU_DISPLAY_CTL_FONT_SIZE: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; *ptr = disp->font.size; } return true; case MENU_DISPLAY_CTL_SET_FONT_SIZE: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; disp->font.size = *ptr; } return true; case MENU_DISPLAY_CTL_SET_HEIGHT: { unsigned *ptr = (unsigned*)data; if (!ptr) return false; frame_buf->height = *ptr; } return true; case MENU_DISPLAY_CTL_FB_DATA: { uint16_t **ptr = (uint16_t**)data; if (!ptr) return false; *ptr = frame_buf->data; } return true; case MENU_DISPLAY_CTL_SET_FB_DATA: { uint16_t *ptr = (uint16_t*)data; if (!ptr) return false; frame_buf->data = ptr; } return true; case MENU_DISPLAY_CTL_FB_PITCH: { size_t *ptr = (size_t*)data; if (!ptr) return false; *ptr = frame_buf->pitch; } return true; case MENU_DISPLAY_CTL_SET_FB_PITCH: { size_t *ptr = (size_t*)data; if (!ptr) return false; frame_buf->pitch = *ptr; } return true; case MENU_DISPLAY_CTL_MSG_FORCE: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = disp->msg_force; } return true; case MENU_DISPLAY_CTL_SET_MSG_FORCE: { bool *ptr = (bool*)data; if (!ptr) return false; disp->msg_force = *ptr; } return true; case MENU_DISPLAY_CTL_FONT_DATA_INIT: { bool *ptr = (bool*)data; if (!ptr) return false; *ptr = disp->font.alloc_framebuf; } return true; case MENU_DISPLAY_CTL_SET_FONT_DATA_INIT: { bool *ptr = (bool*)data; if (!ptr) return false; disp->font.alloc_framebuf = *ptr; } return true; case MENU_DISPLAY_CTL_UPDATE_PENDING: { bool ptr; menu_display_ctl(MENU_DISPLAY_CTL_GET_FRAMEBUFFER_DIRTY_FLAG, &ptr); if (menu_animation_ctl(MENU_ANIMATION_CTL_IS_ACTIVE, NULL) || ptr) return true; } return false; case MENU_DISPLAY_CTL_SET_VIEWPORT: video_driver_get_size(&width, &height); video_driver_set_viewport(width, height, true, false); return true; case MENU_DISPLAY_CTL_UNSET_VIEWPORT: video_driver_get_size(&width, &height); video_driver_set_viewport(width, height, false, true); return true; case MENU_DISPLAY_CTL_GET_FRAMEBUFFER_DIRTY_FLAG: { bool *ptr = (bool*)data; if (!ptr || !frame_buf) return false; *ptr = frame_buf->dirty; } return true; case MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG: if (frame_buf && frame_buf->data) frame_buf->dirty = true; return true; case MENU_DISPLAY_CTL_UNSET_FRAMEBUFFER_DIRTY_FLAG: if (frame_buf && frame_buf->data) frame_buf->dirty = false; return true; case MENU_DISPLAY_CTL_GET_DPI: { float *dpi = (float*)data; *dpi = menu_dpi_override_value; if (!settings) return true; if (settings->menu.dpi.override_enable) *dpi = settings->menu.dpi.override_value; else if (!gfx_ctx_get_metrics(DISPLAY_METRIC_DPI, dpi)) *dpi = menu_dpi_override_value; } return true; } return false; }