mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
(Menu/Widgets) Retire fonts rebuilt from a render path instead of freeing
XMB was not the only caller freeing a font from a path that runs before
the video driver's frame function. The same free-then-create sits in
four more places, all reached per frame:
ozone_init_font ozone_render -> ozone_set_layout, six fonts
materialui_init_font materialui_render -> materialui_layout, three
gfx_widgets_font_init gfx_widgets_iterate -> gfx_widgets_layout, six
menu_screensaver menu_screensaver_iterate, on a dimension change
All four fire on a menu scale factor change, which is the operation that
crashed D3D12 in XMB for years before 45f8bf4a. Whether they have been
crashing quietly or merely could is not something the code can answer;
the structure is the same either way.
Build the replacement before releasing the old handle and retire the old
one through font_driver_free_deferred(). The screensaver has no
replacement to build at that point — it clears the font and lets the
effect init rebuild it below — so it only needs the retire.
Building first has a second benefit at three of the four sites: a font
that fails to load now leaves the previous one in place rather than
leaving the caller with none. Ozone's init in particular returns false
on failure and its caller clears HAS_ALL_ASSETS, but it was returning
with font_data->font already NULL.
The teardown frees in these files are left alone: they run when the
context is going away, where there is no later frame to wait for and
the queue is drained wholesale.
This commit is contained in:
1 parent
bdd3f3e57b
commit
0e45cec310
4 files changed
+52
-26
No files matched your search
+18
-10
@@ -943,19 +943,27 @@ static void gfx_widgets_font_init(
|
||||
if (scaled_size < 9)
|
||||
scaled_size = 9;
|
||||
|
||||
/* Free existing font */
|
||||
if (font_data->font)
|
||||
{
|
||||
font_driver_free(font_data->font);
|
||||
font_data->font = NULL;
|
||||
}
|
||||
|
||||
/* Get approximate glyph width */
|
||||
font_data->glyph_width = scaled_size * (3.0f / 4.0f);
|
||||
|
||||
/* Create font */
|
||||
font_data->font = gfx_display_font_file(p_disp,
|
||||
font_path, scaled_size, is_threaded);
|
||||
/* Create font.
|
||||
*
|
||||
* Built before the old one is released, and the old one retired
|
||||
* rather than freed: gfx_widgets_layout() reaches here from
|
||||
* gfx_widgets_iterate(), which runs before the video driver's
|
||||
* frame function, so freeing the atlas outright can pull it out
|
||||
* from under a command list that still references it. */
|
||||
{
|
||||
font_data_t *old_font = font_data->font;
|
||||
|
||||
font_data->font = gfx_display_font_file(p_disp,
|
||||
font_path, scaled_size, is_threaded);
|
||||
|
||||
if (!font_data->font)
|
||||
font_data->font = old_font;
|
||||
else if (old_font)
|
||||
font_driver_free_deferred(old_font);
|
||||
}
|
||||
|
||||
/* Get font metadata. gfx_display_font_file() can fail, and there is
|
||||
* no implicit font to fall back on any more, so the approximate
|
||||
|
||||
@@ -9451,17 +9451,12 @@ static void materialui_init_font(gfx_display_t *p_disp,
|
||||
const char *wideglyph_str = msg_hash_get_wideglyph_str();
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *dir_assets = settings->paths.directory_assets;
|
||||
font_data_t *old_font = font_data->font;
|
||||
fontpath[0] = '\0';
|
||||
|
||||
/* We assume the average glyph aspect ratio is close to 3:4 */
|
||||
font_data->glyph_width = (int)((font_size * (3.0f / 4.0f)) + 0.5f);
|
||||
|
||||
if (font_data->font)
|
||||
{
|
||||
font_driver_free(font_data->font);
|
||||
font_data->font = NULL;
|
||||
}
|
||||
|
||||
{
|
||||
const char *lang_font = font_driver_language_font_file();
|
||||
|
||||
@@ -9478,9 +9473,20 @@ static void materialui_init_font(gfx_display_t *p_disp,
|
||||
strlcpy(fontpath, default_fontpath, sizeof(fontpath));
|
||||
}
|
||||
|
||||
/* Built before the old one is released, and the old one retired
|
||||
* rather than freed: materialui_layout() reaches here from
|
||||
* materialui_render(), which runs before the video driver's frame
|
||||
* function, so freeing the atlas outright can pull it out from
|
||||
* under a command list that still references it. Building first
|
||||
* also keeps the previous font in place if this fails. */
|
||||
font_data->font = gfx_display_font_file(p_disp,
|
||||
fontpath, font_size, video_is_threaded);
|
||||
|
||||
if (!font_data->font)
|
||||
font_data->font = old_font;
|
||||
else if (old_font)
|
||||
font_driver_free_deferred(old_font);
|
||||
|
||||
/* Follow the menu language, so a language change can rebuild this
|
||||
* where it stands instead of asking for a restart. */
|
||||
font_driver_set_language_font(font_data->font, pkg_dir, default_fontpath);
|
||||
|
||||
+16
-8
@@ -10002,13 +10002,7 @@ static bool ozone_init_font(
|
||||
int glyph_width = 0;
|
||||
gfx_display_t *p_disp = disp_get_ptr();
|
||||
const char *wideglyph_str = msg_hash_get_wideglyph_str();
|
||||
|
||||
/* Free existing */
|
||||
if (font_data->font)
|
||||
{
|
||||
font_driver_free(font_data->font);
|
||||
font_data->font = NULL;
|
||||
}
|
||||
font_data_t *old_font = font_data->font;
|
||||
|
||||
/* Enforce minimum readable font size for small screens */
|
||||
if (font_size < 9)
|
||||
@@ -10018,9 +10012,23 @@ static bool ozone_init_font(
|
||||
font_data->line_height = (int)(font_size + 0.5f);
|
||||
font_data->glyph_width = (int)((font_size * (3.0f / 4.0f)) + 0.5f);
|
||||
|
||||
/* Create font */
|
||||
/* Create font.
|
||||
*
|
||||
* Built before the old one is released, and the old one retired
|
||||
* rather than freed: ozone_set_layout() reaches here from
|
||||
* ozone_render(), which runs before the video driver's frame
|
||||
* function, so freeing the atlas outright can pull it out from
|
||||
* under a command list that still references it. Building first
|
||||
* also means a failure below leaves the previous font in place
|
||||
* instead of leaving Ozone with none. */
|
||||
if (!(font_data->font = gfx_display_font_file(p_disp, font_path, font_size, is_threaded)))
|
||||
{
|
||||
font_data->font = old_font;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (old_font)
|
||||
font_driver_free_deferred(old_font);
|
||||
|
||||
/* Get font metadata */
|
||||
if ((glyph_width = font_driver_get_message_width(font_data->font, "a", 1, 1.0f)) > 0)
|
||||
|
||||
@@ -460,10 +460,14 @@ static bool menu_screensaver_update_state(
|
||||
{
|
||||
menu_screensaver_set_dimensions(screensaver, width, height);
|
||||
|
||||
/* Free any existing font */
|
||||
/* Retire any existing font. This runs from
|
||||
* menu_screensaver_iterate(), before the video driver's frame
|
||||
* function, and the font is rebuilt below, so releasing it
|
||||
* outright can pull the atlas out from under a command list
|
||||
* that still references it. */
|
||||
if (screensaver->font_data.font)
|
||||
{
|
||||
font_driver_free(screensaver->font_data.font);
|
||||
font_driver_free_deferred(screensaver->font_data.font);
|
||||
video_coord_array_free(&screensaver->font_data.raster_block.carr);
|
||||
screensaver->font_data.font = NULL;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user