Move menu DPI scaling code to menu_widgets

This commit is contained in:
twinaphex 2020-02-17 00:17:36 +01:00
parent 633277ddd0
commit 550e8fff6b
4 changed files with 427 additions and 426 deletions

View File

@ -39,6 +39,9 @@
#include "menu_input.h"
#include "menu_entries.h"
#include "widgets/menu_dialog.h"
#ifdef HAVE_MENU_WIDGETS
#include "widgets/menu_widgets.h"
#endif
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
#include "menu_shader.h"
#endif
@ -61,20 +64,6 @@
#define SCROLL_INDEX_SIZE (2 * (26 + 2) + 1)
/* Number of pixels corner-to-corner on a 1080p
* display:
* > sqrt((1920 * 1920) + (1080 * 1080))
* Note: This is a double, so no suffix */
#define DIAGONAL_PIXELS_1080P 2202.90717008229831581901
/* Standard reference DPI value, used when determining
* DPI-aware menu scaling factors */
#define REFERENCE_DPI 96.0f
/* 'OZONE_SIDEBAR_WIDTH' must be kept in sync
* with ozone menu driver metrics */
#define OZONE_SIDEBAR_WIDTH 408
#define POWERSTATE_CHECK_INTERVAL (30 * 1000000)
#define DATETIME_CHECK_INTERVAL 1000000
@ -187,8 +176,6 @@ static menu_handle_t *menu_driver_data = NULL;
static const menu_ctx_driver_t *menu_driver_ctx = NULL;
static void *menu_userdata = NULL;
static enum menu_driver_id_type menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
/* Quick jumping indices with L/R.
* Rebuilt when parsing directory. */
static size_t scroll_index_list[SCROLL_INDEX_SIZE];
@ -1677,11 +1664,6 @@ const char *menu_driver_ident(void)
return menu_driver_ctx->ident;
}
enum menu_driver_id_type menu_driver_ident_id(void)
{
return menu_driver_id;
}
void menu_driver_frame(video_frame_info_t *video_info)
{
if (video_info->menu_is_alive && menu_driver_ctx->frame)
@ -1931,7 +1913,9 @@ static void menu_driver_set_id(void)
{
const char *driver_name = NULL;
menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
#ifdef HAVE_MENU_WIDGETS
menu_widgets_set_driver_id(MENU_DRIVER_ID_UNKNOWN);
#endif
if (!menu_driver_ctx || !menu_driver_ctx->ident)
return;
@ -1941,23 +1925,27 @@ static void menu_driver_set_id(void)
if (string_is_empty(driver_name))
return;
#ifdef HAVE_MENU_WIDGETS
if (string_is_equal(driver_name, "rgui"))
menu_driver_id = MENU_DRIVER_ID_RGUI;
menu_widgets_set_driver_id(MENU_DRIVER_ID_RGUI);
else if (string_is_equal(driver_name, "ozone"))
menu_driver_id = MENU_DRIVER_ID_OZONE;
menu_widgets_set_driver_id(MENU_DRIVER_ID_OZONE);
else if (string_is_equal(driver_name, "glui"))
menu_driver_id = MENU_DRIVER_ID_GLUI;
menu_widgets_set_driver_id(MENU_DRIVER_ID_GLUI);
else if (string_is_equal(driver_name, "xmb"))
menu_driver_id = MENU_DRIVER_ID_XMB;
menu_widgets_set_driver_id(MENU_DRIVER_ID_XMB);
else if (string_is_equal(driver_name, "xui"))
menu_driver_id = MENU_DRIVER_ID_XUI;
menu_widgets_set_driver_id(MENU_DRIVER_ID_XUI);
else if (string_is_equal(driver_name, "stripes"))
menu_driver_id = MENU_DRIVER_ID_STRIPES;
menu_widgets_set_driver_id(MENU_DRIVER_ID_STRIPES);
#endif
}
static bool menu_driver_init_internal(bool video_is_threaded)
{
menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
#ifdef HAVE_MENU_WIDGETS
menu_widgets_set_driver_id(MENU_DRIVER_ID_UNKNOWN);
#endif
if (menu_driver_ctx->init)
{
@ -2089,380 +2077,6 @@ bool menu_driver_list_get_size(menu_ctx_list_t *list)
return true;
}
static float menu_display_get_adjusted_scale_internal(
float base_scale, float scale_factor, unsigned width)
{
/* Apply user-set scaling factor */
float adjusted_scale = base_scale * scale_factor;
/* Ozone has a capped scale factor */
adjusted_scale = (menu_driver_id == MENU_DRIVER_ID_OZONE) ?
(((float)OZONE_SIDEBAR_WIDTH * adjusted_scale) > ((float)width * 0.3333333f) ?
((float)width * 0.3333333f / (float)OZONE_SIDEBAR_WIDTH) : adjusted_scale) :
adjusted_scale;
/* Ensure final scale is 'sane' */
return (adjusted_scale > 0.0001f) ? adjusted_scale : 1.0f;
}
float menu_display_get_dpi_scale_internal(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
float diagonal_pixels;
float pixel_scale;
float dpi;
gfx_ctx_metrics_t metrics;
if (scale_cached &&
(width == last_width) &&
(height == last_height))
return scale;
/* Determine the diagonal 'size' of the display
* (or window) in terms of pixels */
diagonal_pixels = (float)sqrt(
(double)((width * width) + (height * height)));
/* TODO/FIXME: On Mac, calling video_context_driver_get_metrics()
* here causes RetroArch to crash (EXC_BAD_ACCESS). This is
* unfortunate, and needs to be fixed at the gfx context driver
* level. Until this is done, all we can do is fallback to using
* the old legacy 'magic number' scaling on Mac platforms. */
#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL)
if (true)
{
scale = (diagonal_pixels / 6.5f) / 212.0f;
scale_cached = true;
last_width = width;
last_height = height;
return scale;
}
#endif
/* Get pixel scale relative to baseline 1080p display */
pixel_scale = diagonal_pixels / DIAGONAL_PIXELS_1080P;
/* Attempt to get display DPI */
metrics.type = DISPLAY_METRIC_DPI;
metrics.value = &dpi;
if (video_context_driver_get_metrics(&metrics) && (dpi > 0.0f))
{
float display_size;
float dpi_scale;
#if defined(ANDROID) || defined(HAVE_COCOATOUCH)
/* Android/iOS devices tell complete lies when
* reporting DPI values. From the Android devices
* I've had access to, the DPI is generally
* overestimated by 17%. All we can do is apply
* a blind correction factor... */
dpi = dpi * 0.83f;
#endif
/* Note: If we are running in windowed mode, this
* 'display size' is actually the window size - which
* kinda makes a mess of everything. Since we cannot
* get fullscreen resolution when running in windowed
* mode, there is nothing we can do about this. So just
* treat the window as a display, and hope for the best... */
display_size = diagonal_pixels / dpi;
dpi_scale = dpi / REFERENCE_DPI;
/* Note: We have tried leveraging every possible metric
* (and numerous studies on TV/monitor/mobile device
* usage habits) to determine an appropriate auto scaling
* factor. *None of these 'smart'/technical methods work
* consistently in the real world* - there is simply too
* much variance.
* So instead we have implemented a very fuzzy/loose
* method which is crude as can be, but actually has
* some semblance of usability... */
if (display_size > 24.0f)
{
/* DPI scaling fails miserably when using large
* displays. Having a UI element that's 1 inch high
* on all screens might seem like a good idea - until
* you realise that a HTPC user is probably sitting
* several metres from their TV, which makes something
* 1 inch high virtually invisible.
* So we make some assumptions:
* - Normal size displays <= 24 inches are probably
* PC monitors, with an eye-to-screen distance of
* 1 arm length. Under these conditions, fixed size
* (DPI scaled) UI elements should be visible for most
* users
* - Large displays > 24 inches start to encroach on
* TV territory. Once we start working with TVs, we
* have to consider users sitting on a couch - and
* in this situation, we fall back to the age-old
* standard of UI elements occupying a fixed fraction
* of the display size (i.e. just look at the menu of
* any console system for the past decade)
* - 24 -> 32 inches is a grey area, where the display
* might be a monitor or a TV. Above 32 inches, a TV
* is almost a certainty. So we simply lerp between
* dpi scaling and pixel scaling as the display size
* increases from 24 to 32 */
float fraction = (display_size > 32.0f) ? 32.0f : display_size;
fraction = fraction - 24.0f;
fraction = fraction / (32.0f - 24.0f);
scale = ((1.0f - fraction) * dpi_scale) + (fraction * pixel_scale);
}
else if (display_size < 12.0f)
{
/* DPI scaling also fails when using very small
* displays - i.e. mobile devices (tablets/phones).
* That 1 inch UI element is going to look pretty
* dumb on a 5 inch screen in landscape orientation...
* We're essentially in the opposite situation to the
* TV case above, and it turns out that a similar
* solution provides relief: as screen size reduces
* from 12 inches to zero, we lerp from dpi scaling
* to pixel scaling */
float fraction = display_size / 12.0f;
scale = ((1.0f - fraction) * pixel_scale) + (fraction * dpi_scale);
}
else
scale = dpi_scale;
}
/* If DPI retrieval is unsupported, all we can do
* is use the raw pixel scale */
else
scale = pixel_scale;
scale_cached = true;
last_width = width;
last_height = height;
return scale;
}
float menu_display_get_dpi_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
float menu_scale_factor = 1.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
if (settings)
menu_scale_factor = settings->floats.menu_scale_factor;
/* Scale is based on display metrics - these are a fixed
* hardware property. To minimise performance overheads
* we therefore only call video_context_driver_get_metrics()
* on first run, or when the current video resolution changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
scale = menu_display_get_dpi_scale_internal(width, height);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
#ifdef HAVE_MENU_WIDGETS
float menu_display_get_widget_dpi_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
float menu_scale_factor = 1.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
/* When using RGUI, settings->floats.menu_scale_factor
* is ignored
* > If we are not using a widget scale factor override,
* just set menu_scale_factor to 1.0 */
if (settings)
menu_scale_factor = settings->bools.menu_widget_scale_auto ?
((menu_driver_id == MENU_DRIVER_ID_RGUI) ?
1.0f : settings->floats.menu_scale_factor) :
settings->floats.menu_widget_scale_factor;
/* Scale is based on display metrics - these are a fixed
* hardware property. To minimise performance overheads
* we therefore only call video_context_driver_get_metrics()
* on first run, or when the current video resolution changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
scale = menu_display_get_dpi_scale_internal(width, height);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
#endif
#ifdef HAVE_MENU_WIDGETS
float menu_display_get_widget_pixel_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
float menu_scale_factor = 1.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
/* When using RGUI, settings->floats.menu_scale_factor
* is ignored
* > If we are not using a widget scale factor override,
* just set menu_scale_factor to 1.0 */
if (settings)
menu_scale_factor = settings->bools.menu_widget_scale_auto ?
((menu_driver_id == MENU_DRIVER_ID_RGUI) ?
1.0f : settings->floats.menu_scale_factor) :
settings->floats.menu_widget_scale_factor;
/* We need to perform a square root here, which
* can be slow on some platforms (not *slow*, but
* it involves enough work that it's worth trying
* to optimise). We therefore cache the pixel scale,
* and only update on first run or when the video
* size changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
/* Baseline reference is a 1080p display */
scale = (float)(
sqrt((double)((width * width) + (height * height))) /
DIAGONAL_PIXELS_1080P);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
#endif
/* Ugh... Since we must now have independent scale
* factors for menus and widgets, and most of the internal
* scaling variables are cached/static, a huge amount of
* code duplication is required for the pixel_scale and
* dpi_scale functions. A necessary evil, I suppose... */
float menu_display_get_pixel_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
float menu_scale_factor = 1.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
if (settings)
menu_scale_factor = settings->floats.menu_scale_factor;
/* We need to perform a square root here, which
* can be slow on some platforms (not *slow*, but
* it involves enough work that it's worth trying
* to optimise). We therefore cache the pixel scale,
* and only update on first run or when the video
* size changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
/* Baseline reference is a 1080p display */
scale = (float)(
sqrt((double)((width * width) + (height * height))) /
DIAGONAL_PIXELS_1080P);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(
scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
{
@ -2563,7 +2177,9 @@ bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
free(menu_userdata);
menu_userdata = NULL;
menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
#ifdef HAVE_MENU_WIDGETS
menu_widgets_set_driver_id(MENU_DRIVER_ID_UNKNOWN);
#endif
#ifndef HAVE_DYNAMIC
if (frontend_driver_has_fork())

View File

@ -206,16 +206,6 @@ enum menu_settings_type
MENU_SETTINGS_LAST
};
enum menu_driver_id_type
{
MENU_DRIVER_ID_UNKNOWN = 0,
MENU_DRIVER_ID_RGUI,
MENU_DRIVER_ID_OZONE,
MENU_DRIVER_ID_GLUI,
MENU_DRIVER_ID_XMB,
MENU_DRIVER_ID_XUI,
MENU_DRIVER_ID_STRIPES
};
typedef struct menu_ctx_driver
{
@ -425,8 +415,6 @@ const char* config_get_menu_driver_options(void);
const char *menu_driver_ident(void);
enum menu_driver_id_type menu_driver_ident_id(void);
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data);
void menu_driver_frame(video_frame_info_t *video_info);
@ -467,13 +455,6 @@ size_t menu_navigation_get_selection(void);
void menu_navigation_set_selection(size_t val);
float menu_display_get_dpi_scale(unsigned width, unsigned height);
float menu_display_get_pixel_scale(unsigned width, unsigned height);
#ifdef HAVE_MENU_WIDGETS
float menu_display_get_widget_pixel_scale(unsigned width, unsigned height);
float menu_display_get_widget_dpi_scale(unsigned width, unsigned height);
#endif
void menu_display_handle_thumbnail_upload(retro_task_t *task,
void *task_data,
void *user_data, const char *err);

View File

@ -30,6 +30,7 @@
#include "../../accessibility.h"
#endif
#include "../../configuration.h"
#include "../../msg_hash.h"
#include "../../tasks/task_content.h"
@ -40,6 +41,21 @@
#include "../menu_driver.h"
/* Number of pixels corner-to-corner on a 1080p
* display:
* > sqrt((1920 * 1920) + (1080 * 1080))
* Note: This is a double, so no suffix */
#define DIAGONAL_PIXELS_1080P 2202.90717008229831581901
/* Standard reference DPI value, used when determining
* DPI-aware menu scaling factors */
#define REFERENCE_DPI 96.0f
/* 'OZONE_SIDEBAR_WIDTH' must be kept in sync
* with ozone menu driver metrics */
#define OZONE_SIDEBAR_WIDTH 408
/* TODO: Fix context reset freezing everything in place (probably kills animations when it shouldn't anymore) */
static float msg_queue_background[16] = COLOR_HEX_TO_FLOAT(0x3A3A3A, 1.0f);
@ -326,6 +342,377 @@ static unsigned last_video_width;
static unsigned last_video_height;
static float last_scale_factor;
static enum menu_driver_id_type menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
void menu_widgets_set_driver_id(enum menu_driver_id_type type)
{
menu_driver_id = type;
}
static float menu_display_get_adjusted_scale_internal(
float base_scale, float scale_factor, unsigned width)
{
/* Apply user-set scaling factor */
float adjusted_scale = base_scale * scale_factor;
/* Ozone has a capped scale factor */
adjusted_scale = (menu_driver_id == MENU_DRIVER_ID_OZONE) ?
(((float)OZONE_SIDEBAR_WIDTH * adjusted_scale) > ((float)width * 0.3333333f) ?
((float)width * 0.3333333f / (float)OZONE_SIDEBAR_WIDTH) : adjusted_scale) :
adjusted_scale;
/* Ensure final scale is 'sane' */
return (adjusted_scale > 0.0001f) ? adjusted_scale : 1.0f;
}
float menu_display_get_dpi_scale_internal(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
float diagonal_pixels;
float pixel_scale;
float dpi;
gfx_ctx_metrics_t metrics;
if (scale_cached &&
(width == last_width) &&
(height == last_height))
return scale;
/* Determine the diagonal 'size' of the display
* (or window) in terms of pixels */
diagonal_pixels = (float)sqrt(
(double)((width * width) + (height * height)));
/* TODO/FIXME: On Mac, calling video_context_driver_get_metrics()
* here causes RetroArch to crash (EXC_BAD_ACCESS). This is
* unfortunate, and needs to be fixed at the gfx context driver
* level. Until this is done, all we can do is fallback to using
* the old legacy 'magic number' scaling on Mac platforms. */
#if defined(HAVE_COCOA) || defined(HAVE_COCOA_METAL)
if (true)
{
scale = (diagonal_pixels / 6.5f) / 212.0f;
scale_cached = true;
last_width = width;
last_height = height;
return scale;
}
#endif
/* Get pixel scale relative to baseline 1080p display */
pixel_scale = diagonal_pixels / DIAGONAL_PIXELS_1080P;
/* Attempt to get display DPI */
metrics.type = DISPLAY_METRIC_DPI;
metrics.value = &dpi;
if (video_context_driver_get_metrics(&metrics) && (dpi > 0.0f))
{
float display_size;
float dpi_scale;
#if defined(ANDROID) || defined(HAVE_COCOATOUCH)
/* Android/iOS devices tell complete lies when
* reporting DPI values. From the Android devices
* I've had access to, the DPI is generally
* overestimated by 17%. All we can do is apply
* a blind correction factor... */
dpi = dpi * 0.83f;
#endif
/* Note: If we are running in windowed mode, this
* 'display size' is actually the window size - which
* kinda makes a mess of everything. Since we cannot
* get fullscreen resolution when running in windowed
* mode, there is nothing we can do about this. So just
* treat the window as a display, and hope for the best... */
display_size = diagonal_pixels / dpi;
dpi_scale = dpi / REFERENCE_DPI;
/* Note: We have tried leveraging every possible metric
* (and numerous studies on TV/monitor/mobile device
* usage habits) to determine an appropriate auto scaling
* factor. *None of these 'smart'/technical methods work
* consistently in the real world* - there is simply too
* much variance.
* So instead we have implemented a very fuzzy/loose
* method which is crude as can be, but actually has
* some semblance of usability... */
if (display_size > 24.0f)
{
/* DPI scaling fails miserably when using large
* displays. Having a UI element that's 1 inch high
* on all screens might seem like a good idea - until
* you realise that a HTPC user is probably sitting
* several metres from their TV, which makes something
* 1 inch high virtually invisible.
* So we make some assumptions:
* - Normal size displays <= 24 inches are probably
* PC monitors, with an eye-to-screen distance of
* 1 arm length. Under these conditions, fixed size
* (DPI scaled) UI elements should be visible for most
* users
* - Large displays > 24 inches start to encroach on
* TV territory. Once we start working with TVs, we
* have to consider users sitting on a couch - and
* in this situation, we fall back to the age-old
* standard of UI elements occupying a fixed fraction
* of the display size (i.e. just look at the menu of
* any console system for the past decade)
* - 24 -> 32 inches is a grey area, where the display
* might be a monitor or a TV. Above 32 inches, a TV
* is almost a certainty. So we simply lerp between
* dpi scaling and pixel scaling as the display size
* increases from 24 to 32 */
float fraction = (display_size > 32.0f) ? 32.0f : display_size;
fraction = fraction - 24.0f;
fraction = fraction / (32.0f - 24.0f);
scale = ((1.0f - fraction) * dpi_scale) + (fraction * pixel_scale);
}
else if (display_size < 12.0f)
{
/* DPI scaling also fails when using very small
* displays - i.e. mobile devices (tablets/phones).
* That 1 inch UI element is going to look pretty
* dumb on a 5 inch screen in landscape orientation...
* We're essentially in the opposite situation to the
* TV case above, and it turns out that a similar
* solution provides relief: as screen size reduces
* from 12 inches to zero, we lerp from dpi scaling
* to pixel scaling */
float fraction = display_size / 12.0f;
scale = ((1.0f - fraction) * pixel_scale) + (fraction * dpi_scale);
}
else
scale = dpi_scale;
}
/* If DPI retrieval is unsupported, all we can do
* is use the raw pixel scale */
else
scale = pixel_scale;
scale_cached = true;
last_width = width;
last_height = height;
return scale;
}
float menu_display_get_dpi_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
float menu_scale_factor = settings->floats.menu_scale_factor;
/* Scale is based on display metrics - these are a fixed
* hardware property. To minimise performance overheads
* we therefore only call video_context_driver_get_metrics()
* on first run, or when the current video resolution changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
scale = menu_display_get_dpi_scale_internal(width, height);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
#ifdef HAVE_MENU_WIDGETS
static float menu_display_get_widget_dpi_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
/* When using RGUI, settings->floats.menu_scale_factor
* is ignored
* > If we are not using a widget scale factor override,
* just set menu_scale_factor to 1.0 */
float menu_scale_factor =
settings->bools.menu_widget_scale_auto ?
((menu_driver_id == MENU_DRIVER_ID_RGUI) ?
1.0f : settings->floats.menu_scale_factor) :
settings->floats.menu_widget_scale_factor;
/* Scale is based on display metrics - these are a fixed
* hardware property. To minimise performance overheads
* we therefore only call video_context_driver_get_metrics()
* on first run, or when the current video resolution changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
scale = menu_display_get_dpi_scale_internal(width, height);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
static float menu_display_get_widget_pixel_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
/* When using RGUI, settings->floats.menu_scale_factor
* is ignored
* > If we are not using a widget scale factor override,
* just set menu_scale_factor to 1.0 */
float menu_scale_factor =
settings->bools.menu_widget_scale_auto ?
((menu_driver_id == MENU_DRIVER_ID_RGUI) ?
1.0f : settings->floats.menu_scale_factor) :
settings->floats.menu_widget_scale_factor;
/* We need to perform a square root here, which
* can be slow on some platforms (not *slow*, but
* it involves enough work that it's worth trying
* to optimise). We therefore cache the pixel scale,
* and only update on first run or when the video
* size changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
/* Baseline reference is a 1080p display */
scale = (float)(
sqrt((double)((width * width) + (height * height))) /
DIAGONAL_PIXELS_1080P);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
#endif
/* Ugh... Since we must now have independent scale
* factors for menus and widgets, and most of the internal
* scaling variables are cached/static, a huge amount of
* code duplication is required for the pixel_scale and
* dpi_scale functions. A necessary evil, I suppose... */
#if 0
static float menu_display_get_pixel_scale(unsigned width, unsigned height)
{
static unsigned last_width = 0;
static unsigned last_height = 0;
static float scale = 0.0f;
static bool scale_cached = false;
bool scale_updated = false;
static float last_menu_scale_factor = 0.0f;
static enum menu_driver_id_type last_menu_driver_id = MENU_DRIVER_ID_UNKNOWN;
static float adjusted_scale = 1.0f;
settings_t *settings = config_get_ptr();
float menu_scale_factor = settings->floats.menu_scale_factor;
/* We need to perform a square root here, which
* can be slow on some platforms (not *slow*, but
* it involves enough work that it's worth trying
* to optimise). We therefore cache the pixel scale,
* and only update on first run or when the video
* size changes */
if (!scale_cached ||
(width != last_width) ||
(height != last_height))
{
/* Baseline reference is a 1080p display */
scale = (float)(
sqrt((double)((width * width) + (height * height))) /
DIAGONAL_PIXELS_1080P);
scale_cached = true;
scale_updated = true;
last_width = width;
last_height = height;
}
/* Adjusted scale calculation may also be slow, so
* only update if something changes */
if (scale_updated ||
(menu_scale_factor != last_menu_scale_factor) ||
(menu_driver_id != last_menu_driver_id))
{
adjusted_scale = menu_display_get_adjusted_scale_internal(
scale, menu_scale_factor, width);
last_menu_scale_factor = menu_scale_factor;
last_menu_driver_id = menu_driver_id;
}
return adjusted_scale;
}
#endif
static void msg_widget_msg_transition_animation_done(void *userdata)
{
menu_widget_msg_t *msg = (menu_widget_msg_t*) userdata;
@ -890,7 +1277,7 @@ void menu_widgets_iterate(
/* Check whether screen dimensions or menu scale
* factor have changed */
float scale_factor = (menu_driver_ident_id() == MENU_DRIVER_ID_XMB) ?
float scale_factor = (menu_driver_id == MENU_DRIVER_ID_XMB) ?
menu_display_get_widget_pixel_scale(width, height) :
menu_display_get_widget_dpi_scale(width, height);
@ -1906,7 +2293,7 @@ bool menu_widgets_init(bool video_is_threaded)
* > XMB uses pixel based scaling - all other drivers
* use DPI based scaling */
video_driver_get_size(&last_video_width, &last_video_height);
last_scale_factor = (menu_driver_ident_id() == MENU_DRIVER_ID_XMB) ?
last_scale_factor = (menu_driver_id == MENU_DRIVER_ID_XMB) ?
menu_display_get_widget_pixel_scale(last_video_width, last_video_height) :
menu_display_get_widget_dpi_scale(last_video_width, last_video_height);
@ -2089,7 +2476,7 @@ void menu_widgets_context_reset(bool is_threaded,
/* Update scaling/dimensions */
last_video_width = width;
last_video_height = height;
last_scale_factor = (menu_driver_ident_id() == MENU_DRIVER_ID_XMB) ?
last_scale_factor = (menu_driver_id == MENU_DRIVER_ID_XMB) ?
menu_display_get_widget_pixel_scale(last_video_width, last_video_height) :
menu_display_get_widget_dpi_scale(last_video_width, last_video_height);
menu_widgets_layout(is_threaded, dir_assets, font_path);

View File

@ -36,6 +36,17 @@
#define HOURGLASS_DURATION 1000
#define GENERIC_MESSAGE_DURATION 3000
enum menu_driver_id_type
{
MENU_DRIVER_ID_UNKNOWN = 0,
MENU_DRIVER_ID_RGUI,
MENU_DRIVER_ID_OZONE,
MENU_DRIVER_ID_GLUI,
MENU_DRIVER_ID_XMB,
MENU_DRIVER_ID_XUI,
MENU_DRIVER_ID_STRIPES
};
bool menu_widgets_init(bool video_is_threaded);
void menu_widgets_free(void);
@ -94,4 +105,10 @@ void menu_widgets_frame(void *data);
bool menu_widgets_set_fps_text(const char *new_fps_text);
void menu_widgets_set_driver_id(enum menu_driver_id_type type);
float menu_display_get_dpi_scale(unsigned width, unsigned height);
enum menu_driver_id_type menu_driver_ident_id(void);
#endif