diff --git a/driver.c b/driver.c index 03127a6d9f..e40338c300 100644 --- a/driver.c +++ b/driver.c @@ -696,6 +696,25 @@ retro_proc_address_t driver_get_proc_address(const char *sym) return NULL; } +bool driver_update_system_av_info(const struct retro_system_av_info *info) +{ + g_extern.system.av_info = *info; + rarch_set_fullscreen(g_settings.video.fullscreen); + // Cannot continue recording with different parameters. + // Take the easiest route out and just restart the recording. +#ifdef HAVE_FFMPEG + if (g_extern.recording) + { + static const char *msg = "Restarting FFmpeg recording due to driver reinit."; + msg_queue_push(g_extern.msg_queue, msg, 2, 180); + RARCH_WARN("%s\n", msg); + rarch_deinit_recording(); + rarch_init_recording(); + } +#endif + return true; +} + // Only called once on init and deinit. // Video and input drivers need to be active (owned) // before retroarch core starts. diff --git a/driver.h b/driver.h index fe791d60fc..3a6d6d5bdd 100644 --- a/driver.h +++ b/driver.h @@ -633,6 +633,9 @@ bool driver_location_get_position(double *lat, double *lon, double *horiz_accura void driver_location_set_interval(unsigned interval_msecs, unsigned interval_distance); #endif +// Used by RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO +bool driver_update_system_av_info(const struct retro_system_av_info *info); + extern driver_t driver; //////////////////////////////////////////////// Backends diff --git a/dynamic.c b/dynamic.c index 0920549e95..2d0b0acc2e 100644 --- a/dynamic.c +++ b/dynamic.c @@ -897,6 +897,19 @@ bool rarch_environment_cb(unsigned cmd, void *data) return false; break; + case RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY: + { + const char **dir = (const char**)data; + *dir = *g_settings.content_directory ? g_settings.content_directory : NULL; + RARCH_LOG("Environ CONTENT_DIRECTORY: \"%s\".\n", g_settings.content_directory); + break; + } + + case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO: + { + return driver_update_system_av_info((const struct retro_system_av_info*)data); + } + case RETRO_ENVIRONMENT_EXEC: case RETRO_ENVIRONMENT_EXEC_ESCAPE: @@ -923,14 +936,6 @@ bool rarch_environment_cb(unsigned cmd, void *data) break; - case RETRO_ENVIRONMENT_GET_CONTENT_DIRECTORY: - { - const char **dir = (const char**)data; - *dir = *g_settings.content_directory ? g_settings.content_directory : NULL; - RARCH_LOG("Environ CONTENT_DIRECTORY: \"%s\".\n", g_settings.content_directory); - break; - } - default: RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd); return false; diff --git a/general.h b/general.h index a395f194dc..9b40d3b425 100644 --- a/general.h +++ b/general.h @@ -725,11 +725,15 @@ bool rarch_set_rumble_state(unsigned port, enum retro_rumble_effect effect, bool void rarch_init_autosave(void); void rarch_deinit_autosave(void); void rarch_take_screenshot(void); - void rarch_load_state(void); void rarch_save_state(void); void rarch_state_slot_increase(void); void rarch_state_slot_decrease(void); + +#ifdef HAVE_FFMPEG +void rarch_init_recording(void); +void rarch_deinit_recording(void); +#endif ///////// // Public data structures diff --git a/libretro.h b/libretro.h index 6b350003f5..3c2f4acd6c 100755 --- a/libretro.h +++ b/libretro.h @@ -589,6 +589,24 @@ enum retro_mod // NOTE: libretro cores used to check GET_SYSTEM_DIRECTORY for similar things before. // They should still check GET_SYSTEM_DIRECTORY if they want to be backwards compatible. // The path here can be NULL. It should only be non-NULL if the frontend user has set a specific save path. + // +#define RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO 32 + // const struct retro_system_av_info * -- + // Sets a new av_info structure. This can only be called from within retro_run(). + // This should *only* be used if the core is completely altering the internal resolutions, aspect ratios, timings, etc. + // Calling this can require a full reinitialization of video/audio drivers in the frontend, + // so it is important to call it very sparingly, and usually only with the users explicit consent. + // An eventual driver reinit will happen so that video and audio callbacks + // happening after this call within the same retro_run() call will target the newly initialized driver. + // + // This callback makes it possible to support configurable resolutions in games, which can be useful to + // avoid setting the "worst case" in max_width/max_height. + // + // ***HIGHLY RECOMMENDED*** Do not call this callback every time resolution changes in an emulator core if it's + // expected to be a temporary change, for the reasons of possible driver reinit. + // This call is not a free pass for not trying to provide correct values in retro_get_system_av_info(). + // + // If this returns false, the frontend does not acknowledge a changed av_info struct. enum retro_log_level { diff --git a/retroarch.c b/retroarch.c index 2a4aa829d9..9bb97653c5 100644 --- a/retroarch.c +++ b/retroarch.c @@ -210,8 +210,6 @@ static void readjust_audio_input_rate(void) } #ifdef HAVE_FFMPEG -static void deinit_recording(void); - static void recording_dump_frame(const void *data, unsigned width, unsigned height, size_t pitch) { struct ffemu_video_data ffemu_data = {0}; @@ -238,7 +236,7 @@ static void recording_dump_frame(const void *data, unsigned width, unsigned heig msg_queue_clear(g_extern.msg_queue); msg_queue_push(g_extern.msg_queue, msg, 1, 180); - deinit_recording(); + rarch_deinit_recording(); g_extern.recording = false; return; } @@ -1369,9 +1367,8 @@ static inline void save_files(void) } } - #ifdef HAVE_FFMPEG -static void init_recording(void) +void rarch_init_recording(void) { if (!g_extern.recording) return; @@ -1413,10 +1410,10 @@ static void init_recording(void) return; } - params.out_width = vp.width; - params.out_height = vp.height; - params.fb_width = next_pow2(vp.width); - params.fb_height = next_pow2(vp.height); + params.out_width = vp.width; + params.out_height = vp.height; + params.fb_width = next_pow2(vp.width); + params.fb_height = next_pow2(vp.height); if (g_settings.video.force_aspect && (g_extern.system.aspect_ratio > 0.0f)) params.aspect_ratio = g_extern.system.aspect_ratio; @@ -1481,7 +1478,7 @@ static void init_recording(void) } } -static void deinit_recording(void) +void rarch_deinit_recording(void) { if (!g_extern.recording) return; @@ -3059,7 +3056,7 @@ int rarch_main_init(int argc, char *argv[]) init_controllers(); #ifdef HAVE_FFMPEG - init_recording(); + rarch_init_recording(); #endif #ifdef HAVE_NETPLAY @@ -3265,7 +3262,7 @@ void rarch_main_deinit(void) #endif #ifdef HAVE_FFMPEG - deinit_recording(); + rarch_deinit_recording(); #endif if (g_extern.use_sram)