mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-14 22:47:44 +00:00
Move menu DPI scaling code to menu_widgets
This commit is contained in:
parent
633277ddd0
commit
550e8fff6b
@ -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())
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user