diff --git a/gfx/drivers/ctr_gfx.c b/gfx/drivers/ctr_gfx.c index 18da5807e0..c665b0e734 100644 --- a/gfx/drivers/ctr_gfx.c +++ b/gfx/drivers/ctr_gfx.c @@ -76,11 +76,16 @@ typedef struct ctr_video DVLB_s* dvlb; shaderProgram_s shader; + video_viewport_t vp; + bool rgb32; bool vsync; bool smooth; bool menu_texture_enable; unsigned rotation; + bool keep_aspect; + bool should_resize; + } ctr_video_t; static INLINE void ctr_set_scale_vector(ctr_scale_vector_t* vec, @@ -93,6 +98,117 @@ static INLINE void ctr_set_scale_vector(ctr_scale_vector_t* vec, vec->v = -1.0 / texture_height; } +static INLINE void ctr_set_screen_coords(ctr_video_t * ctr) +{ + if (ctr->rotation == 0) + { + ctr->frame_coords->x0 = ctr->vp.x; + ctr->frame_coords->y0 = ctr->vp.y; + ctr->frame_coords->x1 = ctr->vp.x + ctr->vp.width; + ctr->frame_coords->y1 = ctr->vp.y + ctr->vp.height; + } + else if (ctr->rotation == 1) /* 90° */ + { + ctr->frame_coords->x1 = ctr->vp.x; + ctr->frame_coords->y0 = ctr->vp.y; + ctr->frame_coords->x0 = ctr->vp.x + ctr->vp.width; + ctr->frame_coords->y1 = ctr->vp.y + ctr->vp.height; + } + else if (ctr->rotation == 2) /* 180° */ + { + ctr->frame_coords->x1 = ctr->vp.x; + ctr->frame_coords->y1 = ctr->vp.y; + ctr->frame_coords->x0 = ctr->vp.x + ctr->vp.width; + ctr->frame_coords->y0 = ctr->vp.y + ctr->vp.height; + } + else /* 270° */ + { + ctr->frame_coords->x0 = ctr->vp.x; + ctr->frame_coords->y1 = ctr->vp.y; + ctr->frame_coords->x1 = ctr->vp.x + ctr->vp.width; + ctr->frame_coords->y0 = ctr->vp.y + ctr->vp.height; + } +} + + +static void ctr_update_viewport(ctr_video_t* ctr) +{ + int x = 0; + int y = 0; + float device_aspect = ((float)ctr->vp.full_width) / ctr->vp.full_height; + float width = ctr->vp.full_width; + float height = ctr->vp.full_height; + settings_t *settings = config_get_ptr(); + + if (settings->video.scale_integer) + { + video_viewport_get_scaled_integer(&ctr->vp, ctr->vp.full_width, + ctr->vp.full_height, video_driver_get_aspect_ratio(), ctr->keep_aspect); + width = ctr->vp.width; + height = ctr->vp.height; + } + else if (ctr->keep_aspect) + { + float delta; + float desired_aspect = video_driver_get_aspect_ratio(); + +#if defined(HAVE_MENU) + if (settings->video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM) + { + struct video_viewport *custom = video_viewport_get_custom(); + + if (custom) + { + x = custom->x; + y = custom->y; + width = custom->width; + height = custom->height; + } + } + else +#endif + { + if (fabsf(device_aspect - desired_aspect) < 0.0001f) + { + /* If the aspect ratios of screen and desired aspect + * ratio are sufficiently equal (floating point stuff), + * assume they are actually equal. + */ + } + else if (device_aspect > desired_aspect) + { + delta = (desired_aspect / device_aspect - 1.0f) + / 2.0f + 0.5f; + x = (int)roundf(width * (0.5f - delta)); + width = (unsigned)roundf(2.0f * width * delta); + } + else + { + delta = (device_aspect / desired_aspect - 1.0f) + / 2.0f + 0.5f; + y = (int)roundf(height * (0.5f - delta)); + height = (unsigned)roundf(2.0f * height * delta); + } + } + + ctr->vp.x = x; + ctr->vp.y = y; + ctr->vp.width = width; + ctr->vp.height = height; + } + else + { + ctr->vp.x = ctr->vp.y = 0; + ctr->vp.width = width; + ctr->vp.height = height; + } + + ctr_set_screen_coords(ctr); + + ctr->should_resize = false; + +} + static void* ctr_init(const video_info_t* video, const input_driver_t** input, void** input_data) { @@ -107,6 +223,15 @@ static void* ctr_init(const video_info_t* video, memset(ctr, 0, sizeof(ctr_video_t)); + + ctr->vp.x = 0; + ctr->vp.y = 0; + ctr->vp.width = CTR_TOP_FRAMEBUFFER_WIDTH; + ctr->vp.height = CTR_TOP_FRAMEBUFFER_HEIGHT; + ctr->vp.full_width = CTR_TOP_FRAMEBUFFER_WIDTH; + ctr->vp.full_height = CTR_TOP_FRAMEBUFFER_HEIGHT; + + ctr->display_list_size = 0x40000; ctr->display_list = linearAlloc(ctr->display_list_size * sizeof(uint32_t)); GPU_Reset(NULL, ctr->display_list, ctr->display_list_size); @@ -212,6 +337,9 @@ static void* ctr_init(const video_info_t* video, *input_data = ctrinput; } + ctr->keep_aspect = true; + ctr->should_resize = true; + return ctr; } @@ -275,6 +403,11 @@ static bool ctr_frame(void* data, const void* frame, RARCH_PERFORMANCE_INIT(ctrframe_f); RARCH_PERFORMANCE_START(ctrframe_f); + if (ctr->should_resize) + ctr_update_viewport(ctr); + + + ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000, (u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000, @@ -321,7 +454,8 @@ static bool ctr_frame(void* data, const void* frame, ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height, - GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | + (ctr->smooth? GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) + : GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST)) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGB565); @@ -472,6 +606,7 @@ static void ctr_set_rotation(void* data, unsigned rotation) return; ctr->rotation = rotation; + ctr->should_resize = true; } static void ctr_set_filtering(void* data, unsigned index, bool smooth) { @@ -483,21 +618,50 @@ static void ctr_set_filtering(void* data, unsigned index, bool smooth) static void ctr_set_aspect_ratio(void* data, unsigned aspectratio_index) { - (void)data; - (void)aspectratio_index; - return; + ctr_video_t *ctr = (ctr_video_t*)data; + struct retro_system_av_info *av_info = video_viewport_get_system_av_info(); + + switch (aspectratio_index) + { + case ASPECT_RATIO_SQUARE: + video_viewport_set_square_pixel( + av_info->geometry.base_width, + av_info->geometry.base_height); + break; + + case ASPECT_RATIO_CORE: + video_viewport_set_core(); + break; + + case ASPECT_RATIO_CONFIG: + video_viewport_set_config(); + break; + + default: + break; + } + + video_driver_set_aspect_ratio_value(aspectratio_lut[aspectratio_index].value); + + ctr->keep_aspect = true; + ctr->should_resize = true; } static void ctr_apply_state_changes(void* data) { - (void)data; - return; + ctr_video_t* ctr = (ctr_video_t*)data; + + if (ctr) + ctr->should_resize = true; + } static void ctr_viewport_info(void* data, struct video_viewport* vp) { - (void)data; - return; + ctr_video_t* ctr = (ctr_video_t*)data; + + if (ctr) + *vp = ctr->vp; } static const video_poke_interface_t ctr_poke_interface =