Merge pull request #10203 from jdgleaver/line-ticker-fix

Fix smooth (vertical) line ticker scroll speed
This commit is contained in:
Twinaphex 2020-03-03 17:01:36 +01:00 committed by GitHub
commit f61621f753
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 186 additions and 105 deletions

View File

@ -74,15 +74,16 @@ static const float ticker_pixel_period = (1.0f / 60.0f) * 1000.0f;
static const char ticker_spacer_default[] = TICKER_SPACER_DEFAULT;
static gfx_animation_t anim = {{0}};
static retro_time_t cur_time = 0;
static retro_time_t old_time = 0;
static uint64_t ticker_idx = 0; /* updated every TICKER_SPEED us */
static uint64_t ticker_slow_idx = 0; /* updated every TICKER_SLOW_SPEED us */
static uint64_t ticker_pixel_idx = 0; /* updated every frame */
static float delta_time = 0.0f;
static bool animation_is_active = false;
static bool ticker_is_active = false;
static gfx_animation_t anim = {{0}};
static retro_time_t cur_time = 0;
static retro_time_t old_time = 0;
static uint64_t ticker_idx = 0; /* updated every TICKER_SPEED us */
static uint64_t ticker_slow_idx = 0; /* updated every TICKER_SLOW_SPEED us */
static uint64_t ticker_pixel_idx = 0; /* updated every frame */
static uint64_t ticker_pixel_line_idx = 0; /* updated every frame */
static float delta_time = 0.0f;
static bool animation_is_active = false;
static bool ticker_is_active = false;
/* Forward declarations */
static void gfx_animation_update_time_default(
@ -1197,11 +1198,10 @@ bool gfx_animation_push(gfx_animation_ctx_entry_t *entry)
}
static void gfx_animation_update_time_default(
float *dst,
float *ticker_pixel_increment,
unsigned video_width, unsigned video_height)
{
if (video_width > 0)
*(dst) *= ((float)video_width / 1920.0f);
/* By default, this should be a NOOP */
}
void gfx_animation_set_update_time_cb(update_time_cb cb)
@ -1213,27 +1213,33 @@ void gfx_animation_unset_update_time_cb(void)
{
update_time_callback = gfx_animation_update_time_default;
}
static void gfx_animation_update_time(
retro_time_t current_time,
bool timedate_enable,
unsigned video_width, unsigned video_height,
float _ticker_speed)
{
static retro_time_t last_clock_update = 0;
static retro_time_t last_ticker_update = 0;
static retro_time_t
last_ticker_slow_update = 0;
static retro_time_t last_clock_update = 0;
static retro_time_t last_ticker_update = 0;
static retro_time_t last_ticker_slow_update = 0;
/* Horizontal smooth ticker parameters */
static float ticker_pixel_accumulator = 0.0f;
unsigned ticker_pixel_accumulator_uint = 0;
float ticker_pixel_increment = 0.0f;
/* Vertical (line) smooth ticker parameters */
static float ticker_pixel_line_accumulator = 0.0f;
unsigned ticker_pixel_line_accumulator_uint = 0;
float ticker_pixel_line_increment = 0.0f;
static float ticker_pixel_accumulator = 0.0f;
unsigned ticker_pixel_accumulator_uint = 0;
float ticker_pixel_increment = 0.0f;
/* Adjust ticker speed */
float speed_factor = (_ticker_speed > 0.0001f)
? _ticker_speed : 1.0f;
unsigned ticker_speed =
float speed_factor =
(_ticker_speed > 0.0001f) ? _ticker_speed : 1.0f;
unsigned ticker_speed =
(unsigned)(((float)TICKER_SPEED / speed_factor) + 0.5);
unsigned ticker_slow_speed =
unsigned ticker_slow_speed =
(unsigned)(((float)TICKER_SLOW_SPEED / speed_factor) + 0.5);
/* Note: cur_time & old_time are in us (microseconds),
@ -1251,6 +1257,7 @@ static void gfx_animation_update_time(
if (ticker_is_active)
{
/* Update non-smooth ticker indices */
if (cur_time - last_ticker_update >= ticker_speed)
{
ticker_idx++;
@ -1263,8 +1270,9 @@ static void gfx_animation_update_time(
last_ticker_slow_update = cur_time;
}
/* Pixel ticker updates every frame (regardless of time delta),
* so requires special handling */
/* Pixel tickers (horizontal + vertical/line) update
* every frame (regardless of time delta), so require
* special handling */
/* > Get base increment size (+1 every ticker_pixel_period ms) */
ticker_pixel_increment = delta_time / ticker_pixel_period;
@ -1272,39 +1280,43 @@ static void gfx_animation_update_time(
/* > Apply ticker speed adjustment */
ticker_pixel_increment *= speed_factor;
/* > Apply display resolution adjustment
* (baseline resolution: 1920x1080)
* Note 1: RGUI framebuffer size is independent of
* display resolution, so have to use a fixed multiplier.
* We choose a value such that text is scrolled
* 1 pixel every 4 frames when ticker speed is 1x,
* which matches almost exactly the scroll speed
* of non-smooth ticker text (scrolling 1 pixel
* every 2 frames is optimal, but may be too fast
* for some users - so play it safe. Users can always
* set ticker speed to 2x if they prefer)
* Note 2: GLUI uses the new DPI scaling system,
* so scaling multiplier is gfx_display_get_dpi_scale()
* multiplied by a small correction factor (since the
* default 1.0x speed is just a little faster than the
* non-smooth ticker)
* Note 3: Ozone now also uses the new DPI scaling
* system. We therefore take the same approach as GLUI,
* but with a different correction factor (expected
* scroll speed is somewhat lower for Ozone) */
/* At this point we diverge:
* > Vertical (line) ticker is based upon text
* characteristics (number of characters per
* line) - it is therefore independent of display
* size/scaling, so speed-adjusted pixel increment
* is used directly */
ticker_pixel_line_increment = ticker_pixel_increment;
/* > Horizontal ticker is based upon physical line
* width - it is therefore very much dependent upon
* display size/scaling. Each menu driver is free
* to handle video scaling as it pleases - a callback
* function set by the menu driver is thus used to
* perform menu-specific scaling adjustments */
update_time_callback(&ticker_pixel_increment,
video_width, video_height);
/* > Update accumulator */
/* > Update accumulators */
ticker_pixel_accumulator += ticker_pixel_increment;
ticker_pixel_accumulator_uint = (unsigned)ticker_pixel_accumulator;
/* > Check whether we've accumulated enough for an idx update */
ticker_pixel_line_accumulator += ticker_pixel_line_increment;
ticker_pixel_line_accumulator_uint = (unsigned)ticker_pixel_line_accumulator;
/* > Check whether we've accumulated enough
* for an idx update */
if (ticker_pixel_accumulator_uint > 0)
{
ticker_pixel_idx += ticker_pixel_accumulator_uint;
ticker_pixel_accumulator -= (float)ticker_pixel_accumulator_uint;
}
if (ticker_pixel_accumulator_uint > 0)
{
ticker_pixel_line_idx += ticker_pixel_line_accumulator_uint;
ticker_pixel_line_accumulator -= (float)ticker_pixel_line_accumulator_uint;
}
}
}
@ -2347,3 +2359,8 @@ uint64_t gfx_animation_get_ticker_pixel_idx(void)
{
return ticker_pixel_idx;
}
uint64_t gfx_animation_get_ticker_pixel_line_idx(void)
{
return ticker_pixel_line_idx;
}

View File

@ -31,7 +31,7 @@ RETRO_BEGIN_DECLS
typedef void (*tween_cb) (void*);
typedef void (*update_time_cb) (float *dst,
typedef void (*update_time_cb) (float *ticker_pixel_increment,
unsigned width, unsigned height);
enum gfx_animation_ctl_state
@ -235,6 +235,8 @@ uint64_t gfx_animation_get_ticker_slow_idx(void);
uint64_t gfx_animation_get_ticker_pixel_idx(void);
uint64_t gfx_animation_get_ticker_pixel_line_idx(void);
void gfx_animation_set_update_time_cb(update_time_cb cb);
void gfx_animation_unset_update_time_cb(void);

View File

@ -5646,10 +5646,16 @@ static void materialui_init_nav_bar(materialui_handle_t *mui)
}
static void materialui_menu_animation_update_time(
float *dst,
float *ticker_pixel_increment,
unsigned video_width, unsigned video_height)
{
*(dst) *= gfx_display_get_dpi_scale(video_width, video_height) * 0.8f;
/* MaterialUI uses DPI scaling
* > Smooth ticker scaling multiplier is
* gfx_display_get_dpi_scale() multiplied by
* a small correction factor to achieve a
* default scroll speed equal to that of the
* non-smooth ticker */
*(ticker_pixel_increment) *= gfx_display_get_dpi_scale(video_width, video_height) * 0.8f;
}
static void *materialui_init(void **userdata, bool video_is_threaded)

View File

@ -123,13 +123,18 @@ void ozone_free_list_nodes(file_list_t *list, bool actiondata)
}
static void ozone_menu_animation_update_time(
float *dst,
float *ticker_pixel_increment,
unsigned video_width, unsigned video_height)
{
*(dst) *= gfx_display_get_dpi_scale(video_width, video_height) * 0.5f;
/* Ozone uses DPI scaling
* > Smooth ticker scaling multiplier is
* gfx_display_get_dpi_scale() multiplied by
* a small correction factor to achieve a
* default scroll speed equal to that of the
* non-smooth ticker */
*(ticker_pixel_increment) *= gfx_display_get_dpi_scale(video_width, video_height) * 0.5f;
}
static void *ozone_init(void **userdata, bool video_is_threaded)
{
bool fallback_color_theme = false;

View File

@ -4296,10 +4296,20 @@ static bool rgui_set_aspect_ratio(rgui_t *rgui, bool delay_update)
}
static void rgui_menu_animation_update_time(
float *dst,
unsigned video_width, unsigned height)
float *ticker_pixel_increment,
unsigned video_width, unsigned video_height)
{
*(dst) *= 0.25f;
/* RGUI framebuffer size is independent of
* display resolution, so have to use a fixed
* multiplier for smooth scrolling ticker text.
* We choose a value such that text is scrolled
* 1 pixel every 4 frames when ticker speed is 1x,
* which matches almost exactly the scroll speed
* of non-smooth ticker text (scrolling 1 pixel
* every 2 frames is optimal, but may be too fast
* for some users - so play it safe. Users can always
* set ticker speed to 2x if they prefer) */
*(ticker_pixel_increment) *= 0.25f;
}
static void *rgui_init(void **userdata, bool video_is_threaded)

View File

@ -243,6 +243,7 @@ typedef struct xmb_handle
{
bool mouse_show;
bool use_ps3_layout;
bool last_use_ps3_layout;
bool assets_missing;
bool is_playlist;
bool is_db_manager_list;
@ -273,7 +274,7 @@ typedef struct xmb_handle
float shadow_offset;
float font_size;
float font2_size;
float previous_scale_factor;
float last_scale_factor;
float margins_screen_left;
float margins_screen_top;
@ -3141,7 +3142,7 @@ static int xmb_draw_item(
{
line_ticker_smooth.fade_enabled = true;
line_ticker_smooth.type_enum = menu_ticker_type;
line_ticker_smooth.idx = gfx_animation_get_ticker_pixel_idx();
line_ticker_smooth.idx = gfx_animation_get_ticker_pixel_line_idx();
line_ticker_smooth.font = xmb->font2;
line_ticker_smooth.font_scale = 1.0f;
@ -3401,6 +3402,48 @@ static void xmb_draw_items(
gfx_display_blend_end(video_info);
}
static INLINE bool xmb_use_ps3_layout(
settings_t *settings, unsigned width, unsigned height)
{
unsigned menu_xmb_layout = settings->uints.menu_xmb_layout;
switch (menu_xmb_layout)
{
case 1:
/* PS3 */
return true;
case 2:
/* PSP */
return false;
case 0:
default:
/* Automatic
* > Use PSP layout on tiny screens */
return (width > 320) && (height > 240);
}
}
static INLINE float xmb_get_scale_factor(
settings_t *settings, bool use_ps3_layout, unsigned width)
{
float menu_scale_factor = settings->floats.menu_scale_factor;
float scale_factor;
/* PS3 Layout */
if (use_ps3_layout)
scale_factor = (menu_scale_factor * (float)width) / 1920.0f;
/* PSP Layout */
else
#ifdef _3DS
scale_factor = menu_scale_factor / 4.0f;
#else
scale_factor = ((menu_scale_factor * (float)width) / 1920.0f) * 1.5f;
#endif
/* Apply safety limit */
return (scale_factor >= 0.1f) ? scale_factor : 0.1f;
}
static void xmb_context_reset_internal(xmb_handle_t *xmb,
bool is_threaded, bool reinit_textures);
@ -3410,21 +3453,25 @@ static void xmb_render(void *data,
size_t i;
float scale_factor;
menu_input_pointer_t pointer;
settings_t *settings = config_get_ptr();
xmb_handle_t *xmb = (xmb_handle_t*)data;
settings_t *settings = config_get_ptr();
unsigned end = (unsigned)menu_entries_get_size();
float menu_scale_factor = settings->floats.menu_scale_factor;
if (!xmb)
return;
scale_factor = (menu_scale_factor * (float)width) / 1920.0f;
xmb->use_ps3_layout = xmb_use_ps3_layout(settings, width, height);
scale_factor = xmb_get_scale_factor(settings, xmb->use_ps3_layout, width);
if ((xmb->use_ps3_layout != xmb->last_use_ps3_layout) ||
(scale_factor != xmb->last_scale_factor))
{
xmb->last_use_ps3_layout = xmb->use_ps3_layout;
xmb->last_scale_factor = scale_factor;
if (scale_factor >= 0.1f && scale_factor != xmb->previous_scale_factor)
xmb_context_reset_internal(xmb, video_driver_is_threaded(),
false);
xmb->previous_scale_factor = scale_factor;
}
menu_input_get_pointer_state(&pointer);
@ -4279,7 +4326,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
/* Drop shadow for thumbnails needs to be larger
* than for text/icons, and also needs to scale
* with screen dimensions */
float shadow_offset = xmb->shadow_offset * 1.5f * (menu_scale_factor * (float)width) / 1920.0f;
float shadow_offset = xmb->shadow_offset * 1.5f * xmb->last_scale_factor;
shadow_offset = (shadow_offset > xmb->shadow_offset)
? shadow_offset
: xmb->shadow_offset;
@ -4841,10 +4888,7 @@ static void xmb_frame(void *data, video_frame_info_t *video_info)
static void xmb_layout_ps3(xmb_handle_t *xmb, int width)
{
unsigned new_font_size, new_header_height;
settings_t *settings = config_get_ptr();
float menu_scale_factor = settings->floats.menu_scale_factor;
float scale_factor =
(menu_scale_factor * (float)width) / 1920.0f;
float scale_factor = xmb->last_scale_factor;
xmb->above_subitem_offset = 1.5;
xmb->above_item_offset = -1.0;
@ -4896,13 +4940,7 @@ static void xmb_layout_ps3(xmb_handle_t *xmb, int width)
static void xmb_layout_psp(xmb_handle_t *xmb, int width)
{
unsigned new_font_size, new_header_height;
settings_t *settings = config_get_ptr();
float menu_scale_factor = settings->floats.menu_scale_factor;
float scale_factor =
((menu_scale_factor * (float)width) / 1920.0f) * 1.5f;
#ifdef _3DS
scale_factor = menu_scale_factor / 4.0f;
#endif
float scale_factor = xmb->last_scale_factor;
xmb->above_subitem_offset = 1.5;
xmb->above_item_offset = -1.0;
@ -4951,37 +4989,13 @@ static void xmb_layout(xmb_handle_t *xmb)
unsigned width, height, i, current, end;
file_list_t *selection_buf = menu_entries_get_selection_buf_ptr(0);
size_t selection = menu_navigation_get_selection();
settings_t *settings = config_get_ptr();
unsigned menu_xmb_layout = settings->uints.menu_xmb_layout;
video_driver_get_size(&width, &height);
switch (menu_xmb_layout)
{
/* Automatic */
case 0:
{
xmb->use_ps3_layout = false;
xmb->use_ps3_layout = width > 320 && height > 240;
/* Mimic the layout of the PSP instead of the PS3 on tiny screens */
if (xmb->use_ps3_layout)
xmb_layout_ps3(xmb, width);
else
xmb_layout_psp(xmb, width);
}
break;
/* PS3 */
case 1:
xmb->use_ps3_layout = true;
xmb_layout_ps3(xmb, width);
break;
/* PSP */
case 2:
xmb->use_ps3_layout = false;
xmb_layout_psp(xmb, width);
break;
}
if (xmb->use_ps3_layout)
xmb_layout_ps3(xmb, width);
else
xmb_layout_psp(xmb, width);
#ifdef XMB_DEBUG
RARCH_LOG("[XMB] margin screen left: %.2f\n", xmb->margins_screen_left);
@ -5093,6 +5107,24 @@ static void xmb_init_ribbon(xmb_handle_t * xmb)
free(ribbon_verts);
}
static void xmb_menu_animation_update_time(
float *ticker_pixel_increment,
unsigned video_width, unsigned video_height)
{
menu_handle_t *menu = menu_driver_get_ptr();
xmb_handle_t *xmb = NULL;
if (!menu)
return;
xmb = (xmb_handle_t*)menu->userdata;
if (!xmb)
return;
*(ticker_pixel_increment) *= xmb->last_scale_factor;
}
static void *xmb_init(void **userdata, bool video_is_threaded)
{
unsigned width, height;
@ -5224,6 +5256,12 @@ static void *xmb_init(void **userdata, bool video_is_threaded)
xmb->fullscreen_thumbnail_selection = 0;
xmb->fullscreen_thumbnail_label[0] = '\0';
xmb->use_ps3_layout = xmb_use_ps3_layout(settings, width, height);
xmb->last_use_ps3_layout = xmb->use_ps3_layout;
xmb->last_scale_factor = xmb_get_scale_factor(settings, xmb->use_ps3_layout, width);
gfx_animation_set_update_time_cb(xmb_menu_animation_update_time);
return menu;
error:
@ -5238,6 +5276,7 @@ error:
file_list_free(xmb->horizontal_list);
}
xmb->horizontal_list = NULL;
gfx_animation_unset_update_time_cb();
return NULL;
}
@ -5275,6 +5314,8 @@ static void xmb_free(void *data)
}
font_driver_bind_block(NULL, NULL);
gfx_animation_unset_update_time_cb();
}
static void xmb_context_bg_destroy(xmb_handle_t *xmb)