Widgets: lay out at the monitor's aspect on non-square pixels

With CRT switching at a super resolution (e.g. 2560x240 on a 4:3
monitor) notifications were laid out in output pixels, so every box,
icon and glyph came out squeezed horizontally.

The widgets now lay out at the switchres monitor aspect at the output
height (320x240 for 2560x240), and gfx_display stretches their quads,
draws and scissors across the real width. Text gets a new
font_params.x_scale, which the font backends apply to glyph geometry;
it is 1 everywhere else, so other output is unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
Frank ZegarraandClaude Opus 5.5 authored and libretroadmin committed 2026-11-09 03:16:20 +01:00
1 parent 71cd6b5384
commit 927dda4c1e
26 files changed
+254 -80

No files matched your search

+4 -4
View File
@@ -1589,7 +1589,7 @@ static void d3d10_font_render_msg(
get_glyph = font->font_driver->get_glyph;
font_data = font->font_data;
inv_viewport_w = 1.0f / (float)d3d10->viewport.Width;
inv_viewport_w = rp.x_scale / (float)d3d10->viewport.Width;
inv_viewport_h = 1.0f / (float)d3d10->viewport.Height;
inv_tex_w = 1.0f / (float)font->texture.desc.Width;
inv_tex_h = 1.0f / (float)font->texture.desc.Height;
@@ -1599,7 +1599,7 @@ static void d3d10_font_render_msg(
drop_pos_x = 0.0f;
drop_pos_y = 0.0f;
drop_pre_x = 0;
pre_x = roundf(x * width);
pre_x = roundf(x * width / rp.x_scale);
if (has_drop)
{
@@ -1608,9 +1608,9 @@ static void d3d10_font_render_msg(
unsigned b_dark = b * drop_mod;
unsigned alpha_dark = alpha * drop_alpha;
color_dark = DXGI_COLOR_RGBA(r_dark, g_dark, b_dark, alpha_dark);
drop_pos_x = x + scale * drop_x / width;
drop_pos_x = x + scale * drop_x * rp.x_scale / width;
drop_pos_y = y + scale * drop_y / height;
drop_pre_x = roundf(drop_pos_x * width);
drop_pre_x = roundf(drop_pos_x * width / rp.x_scale);
}
/* Single VBO map for all geometry (drop shadow + main text) */
+6 -4
View File
@@ -2021,6 +2021,7 @@ static void d3d11_font_render_msg(
void *font_data = NULL;
float inv_vp_w, inv_vp_h, inv_tex_w, inv_tex_h;
float scale_inv_vp_w, scale_inv_vp_h;
float win_w;
int drop_x_px, drop_y_px;
int base_lx;
@@ -2075,7 +2076,8 @@ static void d3d11_font_render_msg(
}
/* Precompute reciprocals and scale*reciprocal products once. */
inv_vp_w = 1.0f / (float)d3d11->viewport.Width;
inv_vp_w = rp.x_scale / (float)d3d11->viewport.Width;
win_w = width / rp.x_scale;
inv_vp_h = 1.0f / (float)d3d11->viewport.Height;
inv_tex_w = 1.0f / (float)font->texture.desc.Width;
inv_tex_h = 1.0f / (float)font->texture.desc.Height;
@@ -2086,8 +2088,8 @@ static void d3d11_font_render_msg(
* sprite positions are the foreground positions shifted by this constant,
* so both can be emitted from a single glyph lookup. */
drop_x_px = have_drop
? (int)roundf((x + scale * drop_x / width) * width)
- (int)roundf(x * width)
? (int)roundf((x + scale * drop_x / win_w) * win_w)
- (int)roundf(x * win_w)
: 0;
drop_y_px = have_drop
? (int)roundf((1.0f - (y + scale * drop_y / height)) * height)
@@ -2095,7 +2097,7 @@ static void d3d11_font_render_msg(
: 0;
/* Base lx depends only on x and width — constant across lines. */
base_lx = (int)roundf(x * width);
base_lx = (int)roundf(x * win_w);
/* Capacity check without strlen: scan the message once to
* count bytes while also finding newlines. The byte count is a
+2 -2
View File
@@ -3205,7 +3205,7 @@ static void d3d12_font_render_msg(
get_glyph = font->font_driver->get_glyph;
font_data = font->font_data;
inv_vp_w = 1.0f / (float)d3d12->chain.viewport.Width;
inv_vp_w = rp.x_scale / (float)d3d12->chain.viewport.Width;
inv_vp_h = 1.0f / (float)d3d12->chain.viewport.Height;
inv_tex_w = 1.0f / (float)font->texture.desc.Width;
inv_tex_h = 1.0f / (float)font->texture.desc.Height;
@@ -3279,7 +3279,7 @@ static void d3d12_font_render_msg(
{
d3d12_sprite_t *line_v_first = v;
bool line_ok = false;
int xi = roundf(x * width);
int xi = roundf(x * width / rp.x_scale);
int lx = 0;
int ly = 0;
size_t line_cap = font->block
+2 -1
View File
@@ -1497,7 +1497,7 @@ static void d3d8_font_render_msg(
float line_height;
d3d8_font_t *font = (d3d8_font_t*)data;
d3d8_video_t *d3d = (d3d8_video_t*)userdata;
unsigned width = 0;
float width = 0.0f;
unsigned height = 0;
/* Top-down ortho mapping x[0..1]→[-1..1], y[0..1]→[1..-1] so
* (0,0) is the top-left corner. D3D uses row-vector convention
@@ -1532,6 +1532,7 @@ static void d3d8_font_render_msg(
return;
font_driver_resolve_params(params, &rp);
width = width / rp.x_scale;
x = rp.x;
y = rp.y;
scale = rp.scale;
+2 -1
View File
@@ -1597,7 +1597,7 @@ static void d3d9_cg_font_render_msg(
float line_height;
d3d9_cg_font_t *font = (d3d9_cg_font_t*)data;
d3d9_video_t *d3d = (d3d9_video_t*)userdata;
unsigned width = 0;
float width = 0.0f;
unsigned height = 0;
if (!d3d || !font || !msg || !*msg)
@@ -1609,6 +1609,7 @@ static void d3d9_cg_font_render_msg(
return;
font_driver_resolve_params(params, &rp);
width = width / rp.x_scale;
x = rp.x;
y = rp.y;
scale = rp.scale;
+2 -1
View File
@@ -1680,7 +1680,7 @@ static void d3d9_font_render_msg(
float line_height;
d3d9_font_t *font = (d3d9_font_t*)data;
d3d9_video_t *d3d = (d3d9_video_t*)userdata;
unsigned width = 0;
float width = 0.0f;
unsigned height = 0;
if (!font || !msg || !*msg)
@@ -1694,6 +1694,7 @@ static void d3d9_font_render_msg(
return;
font_driver_resolve_params(params, &rp);
width = width / rp.x_scale;
x = rp.x;
y = rp.y;
scale = rp.scale;
+8 -7
View File
@@ -950,7 +950,7 @@ static void gl1_raster_font_render_message(gl1_t *gl,
GLfloat scale, const GLfloat color[4], GLfloat pos_x, GLfloat pos_y,
float inv_tex_size_x,
float inv_tex_size_y,
float inv_win_width,
float win_width,
float inv_win_height,
unsigned text_align)
{
@@ -965,7 +965,8 @@ static void gl1_raster_font_render_message(gl1_t *gl,
GLfloat *font_tex_coords = font->font_tex_coords;
GLfloat *font_vertex = font->font_vertex;
GLfloat *font_color = font->font_color;
int pre_x = roundf(pos_x * VIDEO_SCALE_W(gl->vp.dims));
float inv_win_width = 1.0f / win_width;
int pre_x = roundf(pos_x * win_width);
const struct font_glyph* (*get_glyph)(void*, uint32_t)
= font->font_driver->get_glyph;
void *font_data = font->font_data;
@@ -1111,7 +1112,7 @@ static void gl1_raster_font_render_msg(
? gl->screen_dims : gl->frame_dims;
float inv_tex_size_x = 1.0f / VIDEO_SCALE_W(font->tex_dims);
float inv_tex_size_y = 1.0f / VIDEO_SCALE_H(font->tex_dims);
float inv_win_width;
float win_width;
float inv_win_height;
/* setup_viewport may change gl->vp, so capture inv_win_width/height
* AFTER it runs — otherwise the vertex math uses one viewport while
@@ -1120,7 +1121,7 @@ static void gl1_raster_font_render_msg(
* gl->vp as-is. */
if (!font->block)
gl1_raster_font_setup_viewport(gl, dims, font, full_screen);
inv_win_width = 1.0f / VIDEO_SCALE_W(gl->vp.dims);
win_width = VIDEO_SCALE_W(gl->vp.dims) / rp.x_scale;
inv_win_height = 1.0f / VIDEO_SCALE_H(gl->vp.dims);
if (msg && *msg
@@ -1137,11 +1138,11 @@ static void gl1_raster_font_render_msg(
gl1_raster_font_render_message(gl, font, msg, msg_len, scale,
color_dark,
x + scale * drop_x / VIDEO_SCALE_W(gl->vp.dims),
x + scale * drop_x / win_width,
y + scale * drop_y / VIDEO_SCALE_H(gl->vp.dims),
inv_tex_size_x,
inv_tex_size_y,
inv_win_width,
win_width,
inv_win_height,
text_align);
}
@@ -1151,7 +1152,7 @@ static void gl1_raster_font_render_msg(
x, y,
inv_tex_size_x,
inv_tex_size_y,
inv_win_width,
win_width,
inv_win_height,
text_align);
}
+8 -7
View File
@@ -1350,8 +1350,8 @@ static void gl2_raster_font_draw_vertices(gl2_t *gl,
static void gl2_raster_font_render_message(gl2_t *gl,
gl2_raster_t *font, const char *msg, size_t msg_len,
GLfloat scale, const GLfloat color[4], GLfloat pos_x,
GLfloat pos_y, unsigned text_align)
GLfloat scale, GLfloat x_scale, const GLfloat color[4],
GLfloat pos_x, GLfloat pos_y, unsigned text_align)
{
struct video_coords coords;
GLfloat color_block[4 * 6];
@@ -1367,7 +1367,8 @@ static void gl2_raster_font_render_message(gl2_t *gl,
GLfloat *font_color = font->font_color;
float inv_tex_size_x = 1.0f / VIDEO_SCALE_W(font->tex_dims);
float inv_tex_size_y = 1.0f / VIDEO_SCALE_H(font->tex_dims);
float inv_win_width = 1.0f / VIDEO_SCALE_W(gl->vp.dims);
float win_width = VIDEO_SCALE_W(gl->vp.dims) / x_scale;
float inv_win_width = 1.0f / win_width;
float inv_win_height = 1.0f / VIDEO_SCALE_H(gl->vp.dims);
const struct font_glyph* (*get_glyph)(void*, uint32_t)
= font->font_driver->get_glyph;
@@ -1392,7 +1393,7 @@ static void gl2_raster_font_render_message(gl2_t *gl,
do \
{ \
(void)(count); \
x = roundf(pos_x * VIDEO_SCALE_W(gl->vp.dims)); \
x = roundf(pos_x * win_width); \
y = roundf((pos_y - (float)(line) * line_height) \
* VIDEO_SCALE_H(gl->vp.dims)); \
if (text_align == TEXT_ALIGN_RIGHT) \
@@ -1541,14 +1542,14 @@ static void gl2_raster_font_render_msg(
color_dark[3] = color[3] * drop_alpha;
gl2_raster_font_render_message(gl, font, msg, msg_len, scale,
color_dark,
x + scale * drop_x / VIDEO_SCALE_W(gl->vp.dims),
rp.x_scale, color_dark,
x + scale * drop_x * rp.x_scale / VIDEO_SCALE_W(gl->vp.dims),
y + scale * drop_y / VIDEO_SCALE_H(gl->vp.dims),
text_align);
}
gl2_raster_font_render_message(gl, font, msg, msg_len, scale,
color, x, y, text_align);
rp.x_scale, color, x, y, text_align);
}
if (!font->block)
+8 -7
View File
@@ -1775,8 +1775,8 @@ static void gl3_raster_font_draw_vertices(gl3_t *gl,
static void gl3_raster_font_render_message(
gl3_t *gl,
gl3_raster_t *font, const char *msg, size_t msg_len,
GLfloat scale, const GLfloat color[4], GLfloat pos_x,
GLfloat pos_y, unsigned text_align)
GLfloat scale, GLfloat x_scale, const GLfloat color[4],
GLfloat pos_x, GLfloat pos_y, unsigned text_align)
{
struct video_coords coords;
GLfloat color_block[4 * 6];
@@ -1791,9 +1791,10 @@ static void gl3_raster_font_render_message(
GLfloat *font_color = font->font_color;
float inv_tex_size_x = 1.0f / font->atlas->width;
float inv_tex_size_y = 1.0f / font->atlas->height;
float inv_win_width = 1.0f / VIDEO_SCALE_W(gl->vp.dims);
float win_width = VIDEO_SCALE_W(gl->vp.dims) / x_scale;
float inv_win_width = 1.0f / win_width;
float inv_win_height = 1.0f / VIDEO_SCALE_H(gl->vp.dims);
int pre_x = roundf(pos_x * VIDEO_SCALE_W(gl->vp.dims));
int pre_x = roundf(pos_x * win_width);
const struct font_glyph* (*get_glyph)(void*, uint32_t)
= font->font_driver->get_glyph;
void *font_data = font->font_data;
@@ -1949,13 +1950,13 @@ static void gl3_raster_font_render_msg(
color_dark[3] = color[3] * drop_alpha;
gl3_raster_font_render_message(gl, font, msg, msg_len, scale,
color_dark,
x + scale * drop_x / VIDEO_SCALE_W(gl->vp.dims),
rp.x_scale, color_dark,
x + scale * drop_x * rp.x_scale / VIDEO_SCALE_W(gl->vp.dims),
y + scale * drop_y / VIDEO_SCALE_H(gl->vp.dims), text_align);
}
gl3_raster_font_render_message(gl, font, msg, msg_len, scale,
color,
rp.x_scale, color,
x, y, text_align);
}
+6 -3
View File
@@ -5346,6 +5346,7 @@ static INLINE void write_quad6(SpriteVertex *pv,
length:(NSUInteger)msg_len
height:(unsigned)height
scale:(float)scale
xScale:(float)x_scale
color:(vector_float4)color
posX:(float)posX
posY:(float)posY
@@ -5358,7 +5359,7 @@ static INLINE void write_quad6(SpriteVertex *pv,
float inv_win_height;
float rgba[4];
uint64_t packed;
unsigned full_w;
float full_w;
unsigned full_h;
SpriteVertex *v;
struct font_line_metrics *line_metrics = NULL;
@@ -5385,7 +5386,7 @@ static INLINE void write_quad6(SpriteVertex *pv,
rgba[2] = color.z;
rgba[3] = color.w;
packed = rgba16_pack(rgba);
full_w = VIDEO_SCALE_W(_driver.viewport->full_dims);
full_w = VIDEO_SCALE_W(_driver.viewport->full_dims) / x_scale;
full_h = VIDEO_SCALE_H(_driver.viewport->full_dims);
inv_tex_size_x = 1.0f / _texture.width;
inv_tex_size_y = 1.0f / _texture.height;
@@ -5493,8 +5494,9 @@ static INLINE void write_quad6(SpriteVertex *pv,
length:msg_len
height:height
scale:scale
xScale:rp.x_scale
color:color_dark
posX:x + scale * drop_x / width
posX:x + scale * drop_x * rp.x_scale / width
posY:y + scale * drop_y / height
aligned:text_align];
}
@@ -5503,6 +5505,7 @@ static INLINE void write_quad6(SpriteVertex *pv,
length:msg_len
height:height
scale:scale
xScale:rp.x_scale
color:color
posX:x
posY:y
+11 -9
View File
@@ -2509,8 +2509,10 @@ static int sdl2_raster_font_get_message_width(void *data, const char *msg,
static void sdl2_raster_font_render_message(
sdl2_raster_t *font, const char *msg, size_t msg_len, float scale,
const SDL_Color col, float pos_x, float pos_y,
enum text_alignment align, unsigned width, unsigned height)
enum text_alignment align, unsigned width, unsigned height,
float x_scale)
{
float scale_x = scale * x_scale;
struct font_line_metrics *line_metrics = NULL;
float line_height_norm = 0.0f;
SDL_Vertex *verts = font->verts;
@@ -2571,9 +2573,9 @@ static void sdl2_raster_font_render_message(
y = (1.0f - (pos_y - (float)(line) * line_height_norm)) \
* (float)height; \
if (align == TEXT_ALIGN_RIGHT) \
x -= (int)((float)(line_width) * scale); \
x -= (int)((float)(line_width) * scale_x); \
else if (align == TEXT_ALIGN_CENTER) \
x -= (int)((float)(line_width) * scale) * 0.5f; \
x -= (int)((float)(line_width) * scale_x) * 0.5f; \
inv_w = 1.0f / (float)VIDEO_SCALE_W(font->tex_dims); \
inv_h = 1.0f / (float)VIDEO_SCALE_H(font->tex_dims); \
n_glyphs = 0; \
@@ -2588,9 +2590,9 @@ static void sdl2_raster_font_render_message(
(void)(pen_y); \
if (!line_ok) \
break; \
gx = x + (glyph)->draw_offset_x * scale; \
gx = x + (glyph)->draw_offset_x * scale_x; \
gy = y + (glyph)->draw_offset_y * scale; \
gw = VIDEO_SCALE_W((glyph)->dims) * scale; \
gw = VIDEO_SCALE_W((glyph)->dims) * scale_x; \
gh = VIDEO_SCALE_H((glyph)->dims) * scale; \
u0 = (float)VIDEO_SCALE_W((glyph)->atlas_pos) * inv_w; \
v0 = (float)VIDEO_SCALE_H((glyph)->atlas_pos) * inv_h; \
@@ -2623,7 +2625,7 @@ static void sdl2_raster_font_render_message(
idx[n_glyphs * 6 + 3] = base + 2; \
idx[n_glyphs * 6 + 4] = base + 1; \
idx[n_glyphs * 6 + 5] = base + 3; \
x += (glyph)->advance_x * scale; \
x += (glyph)->advance_x * scale_x; \
if (++n_glyphs >= SDL2_FONT_MAX_GLYPHS) \
{ \
SDL_RenderGeometry(font->vid->renderer, font->tex, \
@@ -2705,14 +2707,14 @@ static void sdl2_raster_font_render_msg(
sdl2_raster_font_render_message(font, msg, msg_len, scale,
col_drop,
x + scale * drop_x / (float)width,
x + scale * drop_x * rp.x_scale / (float)width,
y + scale * drop_y / (float)height,
align, width, height);
align, width, height, rp.x_scale);
}
sdl2_raster_font_render_message(font, msg, msg_len, scale,
col,
x, y, align, width, height);
x, y, align, width, height, rp.x_scale);
}
static const struct font_glyph *sdl2_raster_font_get_glyph(
+11 -9
View File
@@ -2303,8 +2303,10 @@ static int sdl3_raster_font_get_message_width(void *data, const char *msg,
static void sdl3_raster_font_render_message(
sdl3_raster_t *font, const char *msg, size_t msg_len, float scale,
const SDL_FColor col, float pos_x, float pos_y,
enum text_alignment align, unsigned width, unsigned height)
enum text_alignment align, unsigned width, unsigned height,
float x_scale)
{
float scale_x = scale * x_scale;
struct font_line_metrics *line_metrics = NULL;
float line_height_norm = 0.0f;
SDL_Vertex *verts = font->verts;
@@ -2365,9 +2367,9 @@ static void sdl3_raster_font_render_message(
y = (1.0f - (pos_y - (float)(line) * line_height_norm)) \
* (float)height; \
if (align == TEXT_ALIGN_RIGHT) \
x -= (int)((float)(line_width) * scale); \
x -= (int)((float)(line_width) * scale_x); \
else if (align == TEXT_ALIGN_CENTER) \
x -= (int)((float)(line_width) * scale) * 0.5f; \
x -= (int)((float)(line_width) * scale_x) * 0.5f; \
inv_w = 1.0f / (float)VIDEO_SCALE_W(font->tex_dims); \
inv_h = 1.0f / (float)VIDEO_SCALE_H(font->tex_dims); \
n_glyphs = 0; \
@@ -2382,9 +2384,9 @@ static void sdl3_raster_font_render_message(
(void)(pen_y); \
if (!line_ok) \
break; \
gx = x + (glyph)->draw_offset_x * scale; \
gx = x + (glyph)->draw_offset_x * scale_x; \
gy = y + (glyph)->draw_offset_y * scale; \
gw = VIDEO_SCALE_W((glyph)->dims) * scale; \
gw = VIDEO_SCALE_W((glyph)->dims) * scale_x; \
gh = VIDEO_SCALE_H((glyph)->dims) * scale; \
u0 = (float)VIDEO_SCALE_W((glyph)->atlas_pos) * inv_w; \
v0 = (float)VIDEO_SCALE_H((glyph)->atlas_pos) * inv_h; \
@@ -2417,7 +2419,7 @@ static void sdl3_raster_font_render_message(
idx[n_glyphs * 6 + 3] = base + 2; \
idx[n_glyphs * 6 + 4] = base + 1; \
idx[n_glyphs * 6 + 5] = base + 3; \
x += (glyph)->advance_x * scale; \
x += (glyph)->advance_x * scale_x; \
if (++n_glyphs >= SDL3_FONT_MAX_GLYPHS) \
{ \
SDL_RenderGeometry(font->vid->renderer, font->tex, \
@@ -2497,13 +2499,13 @@ static void sdl3_raster_font_render_msg(
col_drop.a = col.a * drop_alpha;
sdl3_raster_font_render_message(font, msg, msg_len, scale, col_drop,
x + scale * drop_x / (float)width,
x + scale * drop_x * rp.x_scale / (float)width,
y + scale * drop_y / (float)height,
align, width, height);
align, width, height, rp.x_scale);
}
sdl3_raster_font_render_message(font, msg, msg_len, scale, col,
x, y, align, width, height);
x, y, align, width, height, rp.x_scale);
}
static const struct font_glyph *sdl3_raster_font_get_glyph(
+7 -6
View File
@@ -382,7 +382,7 @@ static void vg_render_msg(vg_t *vg, const char *msg, size_t msg_len,
float off_y = 0.0f;
float line_x = 0.0f;
float line_y = 0.0f;
float x0, y0, scale;
float x0, y0, scale, scale_x;
bool atlas_ok = true;
int pass;
@@ -391,6 +391,7 @@ static void vg_render_msg(vg_t *vg, const char *msg, size_t msg_len,
font_driver_resolve_params(params, &rp);
scale = rp.scale;
scale_x = scale * rp.x_scale;
x0 = rp.x * (float)width;
y0 = rp.y * (float)height;
glyph_q = get_glyph(font_data, '?');
@@ -415,7 +416,7 @@ static void vg_render_msg(vg_t *vg, const char *msg, size_t msg_len,
color[1] = rp.color[1] * rp.drop_mod;
color[2] = rp.color[2] * rp.drop_mod;
color[3] = rp.color[3] * rp.drop_alpha;
off_x = (float)rp.drop_x * scale;
off_x = (float)rp.drop_x * scale_x;
off_y = (float)rp.drop_y * scale;
}
else
@@ -435,9 +436,9 @@ static void vg_render_msg(vg_t *vg, const char *msg, size_t msg_len,
#define FONT_LAYOUT_LINE(line, line_width, count, bytes) \
line_x = x0 + off_x; \
if (rp.text_align == TEXT_ALIGN_RIGHT) \
line_x -= (float)(line_width) * scale; \
line_x -= (float)(line_width) * scale_x; \
else if (rp.text_align == TEXT_ALIGN_CENTER) \
line_x -= (float)(line_width) * scale / 2.0f; \
line_x -= (float)(line_width) * scale_x / 2.0f; \
line_y = y0 + off_y - (float)(line) * line_height * scale; \
if ( atlas->dirty \
|| vg->font_atlas_dims != VIDEO_SCALE_PACK(atlas->width, \
@@ -451,9 +452,9 @@ static void vg_render_msg(vg_t *vg, const char *msg, size_t msg_len,
{ \
vgLoadIdentity(); \
vgTranslate( \
line_x + (float)((pen_x) + (glyph)->draw_offset_x) * scale, \
line_x + (float)((pen_x) + (glyph)->draw_offset_x) * scale_x, \
line_y - (float)((pen_y) + (glyph)->draw_offset_y) * scale); \
vgScale(scale, -scale); \
vgScale(scale_x, -scale); \
vgDrawImage(vg_glyph_img); \
} \
}
+5 -3
View File
@@ -4551,6 +4551,7 @@ static void vulkan_font_render_msg(
const struct font_glyph *glyph_q;
float x, y, scale, drop_mod, drop_alpha;
float inv_tex_size_x, inv_tex_size_y, inv_win_width, inv_win_height;
float win_width;
float scale_iww, scale_iwh; /* pre-multiplied scale * inv_win */
const struct font_glyph *(*get_glyph)(void*, uint32_t);
void *font_data;
@@ -4652,7 +4653,8 @@ static void vulkan_font_render_msg(
/* Hoist reciprocals, function pointer, and pre-multiplied factors. */
inv_tex_size_x = 1.0f / VIDEO_SCALE_W(font->texture.dims);
inv_tex_size_y = 1.0f / VIDEO_SCALE_H(font->texture.dims);
inv_win_width = 1.0f / VIDEO_SCALE_W(vk->vp.dims);
win_width = VIDEO_SCALE_W(vk->vp.dims) / rp.x_scale;
inv_win_width = 1.0f / win_width;
inv_win_height = 1.0f / VIDEO_SCALE_H(vk->vp.dims);
scale_iww = scale * inv_win_width;
scale_iwh = scale * inv_win_height;
@@ -4671,7 +4673,7 @@ static void vulkan_font_render_msg(
vk_color = rgba16_pack(color);
fg_base_x = roundf(x * VIDEO_SCALE_W(vk->vp.dims)) * inv_win_width;
fg_base_x = roundf(x * win_width) * inv_win_width;
sh_base_x = 0.0f;
sh_y_origin = 0.0f;
@@ -4684,7 +4686,7 @@ static void vulkan_font_render_msg(
dark[3] = color[3] * drop_alpha;
vk_color_dark = rgba16_pack(dark);
sh_base_x = roundf((x + scale * drop_x
* inv_win_width) * VIDEO_SCALE_W(vk->vp.dims))
* inv_win_width) * win_width)
* inv_win_width;
sh_y_origin = y + scale * drop_y * inv_win_height;
}
+2
View File
@@ -2181,6 +2181,7 @@ void font_driver_resolve_params(const struct font_params *params,
out->x = params->x;
out->y = params->y;
out->scale = params->scale;
out->x_scale = params->x_scale > 0.0f ? params->x_scale : 1.0f;
out->drop_mod = params->drop_mod;
out->drop_alpha = params->drop_alpha;
out->drop_x = params->drop_x;
@@ -2203,6 +2204,7 @@ void font_driver_resolve_params(const struct font_params *params,
out->x = settings->floats.video_msg_pos_x;
out->y = settings->floats.video_msg_pos_y;
out->scale = 1.0f;
out->x_scale = 1.0f;
out->drop_mod = 0.3f;
out->drop_alpha = 1.0f;
out->drop_x = -2;
+1
View File
@@ -289,6 +289,7 @@ typedef struct font_params_resolved
float x;
float y;
float scale;
float x_scale; /* Never 0 */
float drop_mod;
float drop_alpha;
float color[4]; /* RGBA, 0..1, from the packed colour */
+73 -5
View File
@@ -14,6 +14,8 @@
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <math.h>
#include <string/stdstring.h>
#include "gfx_display.h"
@@ -344,6 +346,34 @@ static void gfx_display_flush_as(gfx_display_t *p_disp,
gfx_display_flush_impl(p_disp);
}
void gfx_display_set_output_dims(gfx_display_t *p_disp,
unsigned output_dims)
{
p_disp->output_dims = output_dims;
}
static bool gfx_display_stretched(const gfx_display_t *p_disp,
unsigned video_dims)
{
return p_disp->output_dims
&& VIDEO_SCALE_W(video_dims)
&& VIDEO_SCALE_W(video_dims) != VIDEO_SCALE_W(p_disp->output_dims);
}
unsigned gfx_display_output_dims(const gfx_display_t *p_disp,
unsigned video_dims)
{
return gfx_display_stretched(p_disp, video_dims)
? p_disp->output_dims : video_dims;
}
static int gfx_display_stretch_x(const gfx_display_t *p_disp,
unsigned video_dims, int x)
{
return (int)floor((double)x * VIDEO_SCALE_W(p_disp->output_dims)
/ VIDEO_SCALE_W(video_dims) + 0.5);
}
/* Begin scissoring operation */
void gfx_display_scissor_begin(
gfx_display_t *p_disp,
@@ -351,11 +381,23 @@ void gfx_display_scissor_begin(
unsigned video_dims,
int x, int y, unsigned dims)
{
unsigned video_width = VIDEO_SCALE_W(video_dims);
unsigned video_height = VIDEO_SCALE_H(video_dims);
unsigned width = VIDEO_SCALE_W(dims);
unsigned height = VIDEO_SCALE_H(dims);
unsigned video_width;
unsigned video_height;
unsigned width;
unsigned height;
gfx_display_ctx_driver_t *dispctx = p_disp->dispctx;
if (gfx_display_stretched(p_disp, video_dims))
{
int x1 = gfx_display_stretch_x(p_disp, video_dims,
x + (int)VIDEO_SCALE_W(dims));
x = gfx_display_stretch_x(p_disp, video_dims, x);
dims = VIDEO_SCALE_PACK(x1 - x, VIDEO_SCALE_H(dims));
video_dims = p_disp->output_dims;
}
video_width = VIDEO_SCALE_W(video_dims);
video_height = VIDEO_SCALE_H(video_dims);
width = VIDEO_SCALE_W(dims);
height = VIDEO_SCALE_H(dims);
/* What is gathered goes out before this draws */
gfx_display_flush_as(disp_get_ptr(), GFX_DISPLAY_FLUSH_SCISSOR);
if (dispctx && dispctx->scissor_begin)
@@ -459,6 +501,9 @@ static void gfx_display_draw_text_internal(
params.x = x / width;
params.y = 1.0f - y / height;
params.scale = scale;
params.x_scale = gfx_display_stretched(p_disp, dims)
? (float)VIDEO_SCALE_W(p_disp->output_dims) / width
: 1.0f;
params.drop_mod = 0.0f;
params.drop_x = 0.0f;
params.drop_y = 0.0f;
@@ -1114,7 +1159,21 @@ void gfx_display_draw(gfx_display_ctx_driver_t *dispctx,
gfx_display_ctx_draw_t *draw, void *userdata,
unsigned video_dims)
{
gfx_display_flush_as(disp_get_ptr(), GFX_DISPLAY_FLUSH_DRAW);
gfx_display_ctx_draw_t stretched;
gfx_display_t *p_disp = disp_get_ptr();
gfx_display_flush_as(p_disp, GFX_DISPLAY_FLUSH_DRAW);
if (draw && gfx_display_stretched(p_disp, video_dims))
{
int x = VIDEO_POS_X(draw->pos);
int x1 = gfx_display_stretch_x(p_disp, video_dims,
x + (int)VIDEO_SCALE_W(draw->dims));
x = gfx_display_stretch_x(p_disp, video_dims, x);
stretched = *draw;
stretched.pos = VIDEO_POS_PACK(x, VIDEO_POS_Y(draw->pos));
stretched.dims = VIDEO_SCALE_PACK(x1 - x, VIDEO_SCALE_H(draw->dims));
draw = &stretched;
video_dims = p_disp->output_dims;
}
if (dispctx && dispctx->draw && draw)
dispctx->draw(draw, userdata, video_dims);
}
@@ -1137,6 +1196,15 @@ void gfx_display_draw_quad(
gfx_display_ctx_driver_t
*dispctx = p_disp->dispctx;
if (gfx_display_stretched(p_disp, video_dims))
{
int x1 = gfx_display_stretch_x(p_disp, video_dims, x + (int)w);
x = gfx_display_stretch_x(p_disp, video_dims, x);
w = (unsigned)(x1 - x);
width = gfx_display_stretch_x(p_disp, video_dims, (int)width);
dims = VIDEO_SCALE_PACK(w, h);
video_dims = p_disp->output_dims;
}
if (w == 0 || h == 0)
return;
if (!dispctx || !color)
+13
View File
@@ -272,6 +272,9 @@ struct gfx_display
unsigned batch_first_dims;
void *batch_userdata;
unsigned batch_video_dims;
/* The size drawn to while callers lay out at a narrower or wider
* one of the same height (gfx_display_set_output_dims); 0 if none */
unsigned output_dims;
/* Whether a caller has blending on right now. A quad drawn on its
* own turns blending on and off around itself; one gathered while
* a caller has it on must leave it on, or the caller's group ends
@@ -332,6 +335,16 @@ void gfx_display_draw_text_hp(
float scale_factor, bool shadows_enable, float shadow_offset,
bool draw_outside);
/* Until cleared with 0, what is drawn at a video_dims of another
* width is stretched across the width of output_dims: for a display
* whose pixels are not square. Drawing thread only. */
void gfx_display_set_output_dims(gfx_display_t *p_disp,
unsigned output_dims);
/* What a driver is to be handed for video_dims */
unsigned gfx_display_output_dims(const gfx_display_t *p_disp,
unsigned video_dims);
void gfx_display_scissor_begin(
gfx_display_t *p_disp,
void *userdata,
+37 -9
View File
@@ -1111,7 +1111,8 @@ void gfx_widgets_flush_text(
return;
if (font_data->font && font_data->font->renderer && font_data->font->renderer->flush)
font_data->font->renderer->flush(video_dims,
font_data->font->renderer->flush(
gfx_display_output_dims(disp_get_ptr(), video_dims),
font_data->font->renderer_data);
font_data->raster_block.carr.coords.vertices = 0;
font_data->usage_count = 0;
@@ -1377,6 +1378,15 @@ static void gfx_widgets_layout(
}
}
unsigned gfx_widgets_layout_dims(unsigned dims, float display_aspect)
{
unsigned height = VIDEO_SCALE_H(dims);
if (display_aspect <= 0.0f || !height)
return dims;
return VIDEO_SCALE_PACK((unsigned)(height * display_aspect + 0.5f),
height);
}
/* The scale the widgets lay out at, from the settings: worked out on
* the main thread, and carried to the threaded video worker in the
* frame (video_frame_info_t.widget_scale_factor) */
@@ -1553,6 +1563,7 @@ void gfx_widgets_iterate(
const char *dir_assets, char *font_path,
bool is_threaded)
{
dims = gfx_widgets_layout_dims(dims, video_driver_ui_display_aspect());
/* A relayout resets the frame time counter */
if (gfx_widgets_update_layout((gfx_display_t*)data_disp,
gfx_widgets_scale_factor(data_disp, settings_data, dims,
@@ -1873,7 +1884,7 @@ static void gfx_widgets_draw_task_msg(
&p_dispwidget->gfx_widget_fonts.msg_queue);
if (dispctx && dispctx->scissor_end)
dispctx->scissor_end(userdata,
video_dims);
gfx_display_output_dims(p_disp, video_dims));
}
/* Progress text */
@@ -2098,7 +2109,10 @@ static void gfx_widgets_frame_state(void *data)
bool time_show = video_info->time_show;
bool onscreen_panels = fps_show || framecount_show || memory_show || core_status_msg_show || time_show;
void *userdata = video_info->userdata;
unsigned video_width = VIDEO_SCALE_W(video_info->dims);
unsigned output_dims = video_info->dims;
unsigned layout_dims = gfx_widgets_layout_dims(output_dims,
video_info->widget_display_aspect);
unsigned video_width = VIDEO_SCALE_W(layout_dims);
uint32_t video_flags = video_info->video_st_flags;
bool widgets_is_paused = (video_flags & VIDEO_FLAG_WIDGETS_PAUSED) != 0;
bool widgets_is_fastmotion = (video_flags & VIDEO_FLAG_WIDGETS_FASTMOTION) != 0;
@@ -2145,7 +2159,14 @@ static void gfx_widgets_frame_state(void *data)
if (video_st->current_video && video_st->current_video->set_viewport)
video_st->current_video->set_viewport(
video_st->data, video_info->dims, true, false);
video_st->data, output_dims, true, false);
/* Laid out at layout_dims, stretched across the output */
if (layout_dims != output_dims)
{
video_info->dims = layout_dims;
gfx_display_set_output_dims(p_disp, output_dims);
}
/* Font setup */
font_driver_bind_block(p_dispwidget->gfx_widget_fonts.regular.font,
@@ -2180,9 +2201,11 @@ static void gfx_widgets_frame_state(void *data)
if (video_driver_get_viewport_info(&content_vp) && VIDEO_SCALE_W(content_vp.dims) && VIDEO_SCALE_H(content_vp.dims))
{
overlay_x = VIDEO_POS_X(content_vp.pos);
overlay_x = VIDEO_POS_X(content_vp.pos) * (int)video_width
/ (int)VIDEO_SCALE_W(output_dims);
overlay_y = VIDEO_POS_Y(content_vp.pos);
overlay_width = VIDEO_SCALE_W(content_vp.dims);
overlay_width = VIDEO_SCALE_W(content_vp.dims) * video_width
/ VIDEO_SCALE_W(output_dims);
overlay_height = VIDEO_SCALE_H(content_vp.dims);
}
gfx_display_set_alpha(p_dispwidget->pure_white, 1.0f);
@@ -2428,9 +2451,12 @@ static void gfx_widgets_frame_state(void *data)
font_driver_bind_block(p_dispwidget->gfx_widget_fonts.bold.font, NULL);
font_driver_bind_block(p_dispwidget->gfx_widget_fonts.msg_queue.font, NULL);
video_info->dims = output_dims;
gfx_display_set_output_dims(p_disp, 0);
if (video_st->current_video && video_st->current_video->set_viewport)
video_st->current_video->set_viewport(
video_st->data, video_info->dims, false, true);
video_st->data, output_dims, false, true);
}
void gfx_widgets_frame(void *data)
@@ -3084,8 +3110,10 @@ void gfx_widgets_worker_step(void *data,
return;
/* At the notifications' window's size: one eye's for per-eye UI */
widget_dims = video_frame_ui_layer_dims(video_info,
VIDEO_WINDOW_UI_NOTIFICATIONS);
widget_dims = gfx_widgets_layout_dims(
video_frame_ui_layer_dims(video_info,
VIDEO_WINDOW_UI_NOTIFICATIONS),
video_info->widget_display_aspect);
if (gfx_widgets_update_layout(disp_get_ptr(),
video_info->widget_scale_factor, widget_dims,
+4
View File
@@ -552,6 +552,10 @@ void gfx_widgets_status_text_to_frame(void *data, char *status_text);
void gfx_widgets_iterate_main(void);
#endif
/* dims at display_aspect, same height: what the widgets lay out at
* when the output's pixels are not square; dims when it is 0 */
unsigned gfx_widgets_layout_dims(unsigned dims, float display_aspect);
/* The scale the widgets lay out at, from the settings, for @dims */
float gfx_widgets_scale_factor(void *data_disp, void *settings_data,
unsigned dims, bool fullscreen);
+3
View File
@@ -579,6 +579,9 @@ struct font_params
float x;
float y;
float scale;
/* Glyph width over glyph height, for pixels that are not square.
* 0 is taken as 1. */
float x_scale;
/* Drop shadow color multiplier. */
float drop_mod;
/* Drop shadow alpha */
+16 -1
View File
@@ -4265,6 +4265,17 @@ unsigned video_driver_get_ui_layer_dims(unsigned layer)
return video_driver_get_ui_dims();
}
float video_driver_ui_display_aspect(void)
{
#ifdef HAVE_MODELINE
video_driver_state_t *video_st = &video_driver_st;
if ( retro_atomic_load_acquire_int(&video_st->crt_switching_active)
&& video_st->crt_switch_st.gen)
return (float)video_st->crt_switch_st.gen->monitor_aspect;
#endif
return 0.0f;
}
const video_views_layout_t *video_driver_get_views_layout(void)
{
video_driver_state_t *video_st = &video_driver_st;
@@ -7575,6 +7586,7 @@ void video_driver_build_info(video_frame_info_t *video_info)
video_info->input_driver_grab_mouse_state = (input_flags & INP_FLAG_GRAB_MOUSE_STATE) ? true : false;
video_info->input_poll_time = input_driver_get_poll_time();
video_info->disp_userdata = disp_get_ptr();
video_info->widget_display_aspect = video_driver_ui_display_aspect();
#if defined(HAVE_GFX_WIDGETS) && defined(HAVE_THREADS)
/* The worker lays the widgets out at this, with the dims and the
* fullscreen state the main thread would have */
@@ -7582,7 +7594,9 @@ void video_driver_build_info(video_frame_info_t *video_info)
( video_info->widgets_active
&& retro_atomic_load_relaxed_int(&p_dispwidget->worker))
? gfx_widgets_scale_factor(video_info->disp_userdata, settings,
video_driver_get_ui_layer_dims(VIDEO_WINDOW_UI_NOTIFICATIONS),
gfx_widgets_layout_dims(
video_driver_get_ui_layer_dims(VIDEO_WINDOW_UI_NOTIFICATIONS),
video_info->widget_display_aspect),
video_info->fullscreen)
: 0.0f;
#endif
@@ -9082,6 +9096,7 @@ VIDEO_NOINLINE static void video_driver_frame_statistics(
video_info->osd_stat_params.y = 0.970f;
video_info->osd_stat_params.text_align = TEXT_ALIGN_LEFT;
video_info->osd_stat_params.scale = scale;
video_info->osd_stat_params.x_scale = 1.0f;
video_info->osd_stat_params.full_screen = true;
video_info->osd_stat_params.drop_x = 2;
video_info->osd_stat_params.drop_y = -2;
+7
View File
@@ -652,6 +652,7 @@ typedef struct video_frame_info
float x;
float y;
float scale;
float x_scale;
/* Drop shadow color multiplier. */
float drop_mod;
/* Drop shadow alpha */
@@ -722,6 +723,8 @@ typedef struct video_frame_info
/* The scale the worker lays the widgets out at, worked out from the
* settings as the frame is built */
float widget_scale_factor;
/* video_driver_ui_display_aspect() as the frame is built */
float widget_display_aspect;
#ifdef HAVE_OPENXR
/* 1 + the host's token for the eyes the core drew this frame from,
* given on the drawing thread before it is drawn; 0 for none */
@@ -2526,6 +2529,10 @@ unsigned video_driver_get_ui_layer_window(unsigned layer);
/* App thread: the size UI layer @layer lays out at this frame */
unsigned video_driver_get_ui_layer_dims(unsigned layer);
/* Main thread: width over height of the screen the output fills when
* its pixels are not square (a CRT at a super resolution), or 0. */
float video_driver_ui_display_aspect(void);
/* Main thread: the layout the last frame presented a core's views
* with, or NULL when it was drawn whole. */
const video_views_layout_t *video_driver_get_views_layout(void);
+2 -1
View File
@@ -370,7 +370,8 @@ static void gfx_widget_achievement_popup_frame(void* data, void* userdata)
if (dispctx && dispctx->scissor_end)
dispctx->scissor_end(video_info->userdata,
VIDEO_SCALE_PACK(video_width, video_height));
gfx_display_output_dims(p_disp,
VIDEO_SCALE_PACK(video_width, video_height)));
}
}
@@ -141,6 +141,13 @@ bool font_driver_matches(const font_data_t *font,
{ (void)font; (void)path; (void)size; return false; }
/* --- display: signatures copied from gfx/gfx_display.h --- */
void gfx_display_set_output_dims(gfx_display_t *p_disp,
unsigned output_dims)
{ (void)p_disp; (void)output_dims; }
unsigned gfx_display_output_dims(const gfx_display_t *p_disp,
unsigned video_dims)
{ (void)p_disp; return video_dims; }
float video_driver_ui_display_aspect(void) { return 0.0f; }
void gfx_display_draw_quad(gfx_display_t *p_disp, void *data,
unsigned video_dims,
int x, int y, unsigned dims,
@@ -151,6 +151,13 @@ void gfx_display_blend_end(gfx_display_ctx_driver_t *dispctx, void *data)
{ (void)dispctx; (void)data; }
/* --- display: signatures copied from gfx/gfx_display.h --- */
void gfx_display_set_output_dims(gfx_display_t *p_disp,
unsigned output_dims)
{ (void)p_disp; (void)output_dims; }
unsigned gfx_display_output_dims(const gfx_display_t *p_disp,
unsigned video_dims)
{ (void)p_disp; return video_dims; }
float video_driver_ui_display_aspect(void) { return 0.0f; }
void gfx_display_draw_quad(gfx_display_t *p_disp, void *data,
unsigned video_dims,
int x, int y, unsigned dims,