/** * video_frame: * @data : pointer to data of the video frame. * @width : width of the video frame. * @height : height of the video frame. * @pitch : pitch of the video frame. * * Video frame render callback function. **/ static void video_frame(const void *data, unsigned width, unsigned height, size_t pitch) { unsigned output_width = 0; unsigned output_height = 0; unsigned output_pitch = 0; const char *msg = NULL; driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); const video_driver_t *video = driver ? (const video_driver_t*)driver->video : NULL; if (!driver->video_active) return; if (video_pixel_frame_scale(data, width, height, pitch)) { video_pixel_scaler_t *scaler = scaler_get_ptr(); data = scaler->scaler_out; pitch = scaler->scaler->out_stride; } video_driver_cached_frame_set(data, width, height, pitch); /* Slightly messy code, * but we really need to do processing before blocking on VSync * for best possible scheduling. */ if ((!video_driver_frame_filter_alive() || !settings->video.post_filter_record || !data || global->record.gpu_buffer) ) recording_dump_frame(data, width, height, pitch); msg = rarch_main_msg_queue_pull(); *driver->current_msg = 0; if (msg) strlcpy(driver->current_msg, msg, sizeof(driver->current_msg)); if (video_driver_frame_filter(data, width, height, pitch, &output_width, &output_height, &output_pitch)) { data = video_driver_frame_filter_get_buf_ptr(); width = output_width; height = output_height; pitch = output_pitch; } if (!video->frame(driver->video_data, data, width, height, pitch, driver->current_msg)) driver->video_active = false; }
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; }
static bool take_screenshot_choice(const char *global_name_base) { settings_t *settings = config_get_ptr(); /* No way to infer screenshot directory. */ if (string_is_empty(settings->directory.screenshot) && (!*global_name_base)) return false; if (video_driver_supports_viewport_read()) { /* Avoid taking screenshot of GUI overlays. */ video_driver_set_texture_enable(false, false); video_driver_cached_frame_render(); return take_screenshot_viewport(global_name_base); } if (!video_driver_cached_frame_has_valid_framebuffer()) return take_screenshot_raw(global_name_base); if (video_driver_supports_read_frame_raw()) { unsigned old_width, old_height; size_t old_pitch; bool ret = false; void *frame_data = NULL; const void* old_data = NULL; 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(global_name_base)) ret = true; free(frame_data); } return ret; } return false; }
void init_video(void) { unsigned max_dim, scale, width, height; video_viewport_t *custom_vp = NULL; const input_driver_t *tmp = NULL; const struct retro_game_geometry *geom = NULL; video_info_t video = {0}; static uint16_t dummy_pixels[32] = {0}; driver_t *driver = driver_get_ptr(); global_t *global = global_get_ptr(); settings_t *settings = config_get_ptr(); struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); init_video_filter(video_state.pix_fmt); event_command(EVENT_CMD_SHADER_DIR_INIT); if (av_info) geom = (const struct retro_game_geometry*)&av_info->geometry; max_dim = max(geom->max_width, geom->max_height); scale = next_pow2(max_dim) / RARCH_SCALE_BASE; scale = max(scale, 1); if (video_state.filter.filter) scale = video_state.filter.scale; /* Update core-dependent aspect ratio values. */ video_viewport_set_square_pixel(geom->base_width, geom->base_height); video_viewport_set_core(); video_viewport_set_config(); /* Update CUSTOM viewport. */ custom_vp = video_viewport_get_custom(); if (settings->video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM) { float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value; aspectratio_lut[ASPECT_RATIO_CUSTOM].value = (custom_vp->width && custom_vp->height) ? (float)custom_vp->width / custom_vp->height : default_aspect; } video_driver_set_aspect_ratio_value( aspectratio_lut[settings->video.aspect_ratio_idx].value); if (settings->video.fullscreen) { width = settings->video.fullscreen_x; height = settings->video.fullscreen_y; } else { if (settings->video.force_aspect) { /* Do rounding here to simplify integer scale correctness. */ unsigned base_width = roundf(geom->base_height * video_driver_get_aspect_ratio()); width = roundf(base_width * settings->video.scale); } else width = roundf(geom->base_width * settings->video.scale); height = roundf(geom->base_height * settings->video.scale); } if (width && height) RARCH_LOG("Video @ %ux%u\n", width, height); else RARCH_LOG("Video @ fullscreen\n"); driver->display_type = RARCH_DISPLAY_NONE; driver->video_display = 0; driver->video_window = 0; if (!init_video_pixel_converter(RARCH_SCALE_BASE * scale)) { RARCH_ERR("Failed to initialize pixel converter.\n"); rarch_fail(1, "init_video()"); } video.width = width; video.height = height; video.fullscreen = settings->video.fullscreen; video.vsync = settings->video.vsync && !global->system.force_nonblock; video.force_aspect = settings->video.force_aspect; #ifdef GEKKO video.viwidth = settings->video.viwidth; video.vfilter = settings->video.vfilter; #endif video.smooth = settings->video.smooth; video.input_scale = scale; video.rgb32 = video_state.filter.filter ? video_state.filter.out_rgb32 : (video_state.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888); tmp = (const input_driver_t*)driver->input; /* Need to grab the "real" video driver interface on a reinit. */ find_video_driver(); #ifdef HAVE_THREADS if (settings->video.threaded && !video_state.hw_render_callback.context_type) { /* Can't do hardware rendering with threaded driver currently. */ RARCH_LOG("Starting threaded video driver ...\n"); if (!rarch_threaded_video_init(&driver->video, &driver->video_data, &driver->input, &driver->input_data, driver->video, &video)) { RARCH_ERR("Cannot open threaded video driver ... Exiting ...\n"); rarch_fail(1, "init_video()"); } } else #endif driver->video_data = driver->video->init(&video, &driver->input, &driver->input_data); if (!driver->video_data) { RARCH_ERR("Cannot open video driver ... Exiting ...\n"); rarch_fail(1, "init_video()"); } driver->video_poke = NULL; if (driver->video->poke_interface) driver->video->poke_interface(driver->video_data, &driver->video_poke); if (driver->video->viewport_info && (!custom_vp->width || !custom_vp->height)) { /* Force custom viewport to have sane parameters. */ custom_vp->width = width; custom_vp->height = height; video_driver_viewport_info(custom_vp); } video_driver_set_rotation( (settings->video.rotation + global->system.rotation) % 4); video_driver_suppress_screensaver(settings->ui.suspend_screensaver_enable); if (!driver->input) init_video_input(tmp); event_command(EVENT_CMD_OVERLAY_DEINIT); event_command(EVENT_CMD_OVERLAY_INIT); video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8); #if defined(PSP) video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f); #endif }