mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
MENU/MATERIALUI: Snapshot texture handles to prevent torn reads under threaded video
Icon and background textures in materialui_handle are written by
async load callbacks on the main thread (via gfx_display_load_icon /
task_push_icon_load during context reset, and video_driver_texture_load
in materialui_load_image) and read by materialui_frame and its
sub-functions on the video thread.
Fix: at the top of materialui_frame, memcpy the texture list and
background handle into stack locals:
tex_list[MUI_TEXTURE_LAST] (~576 bytes)
tex_bg (8 bytes)
The following sub-functions receive snapshot pointers:
materialui_render_background: tex_bg
materialui_render_header: tex_list
materialui_render_nav_bar: tex_list (passes through to
materialui_render_nav_bar_bottom and
materialui_render_nav_bar_right)
All texture reads within these functions and in materialui_frame
itself (keyboard overlay icon, cursor pointer) use the snapshots.
Total: 22 render-path texture reads converted.
The function-pointer-based entry renderers
(materialui_render_menu_entry_default, _playlist_list,
_playlist_dual_icon, _playlist_desktop, _savestate_list) still
read the live struct. Changing their shared function pointer
signature would cascade to 5 implementations. They pass handles
by value to materialui_draw_icon which has an existing
null-texture guard (if (!texture) return), preventing crashes
from stale handles.
Additional hardening:
- static float color_white[16] marked static const (never
mutated, was incorrectly missing const qualifier).
- materialui_draw_icon color parameter changed from float *
to const float * for const-correctness.
Stack cost: MUI_TEXTURE_LAST * sizeof(uintptr_t) + sizeof(uintptr_t)
= ~584 bytes on 64-bit.
No behavioral or visual changes.
This commit is contained in:
1 parent
89fbdfa43f
commit
303168b6fe
1 file changed
+45
-29
+45
-29
@@ -2584,7 +2584,7 @@ static void materialui_draw_icon(
|
||||
uintptr_t texture,
|
||||
float x, float y,
|
||||
float rotation, float scale_factor,
|
||||
float *color,
|
||||
const float *color,
|
||||
math_matrix_4x4 *mymat)
|
||||
{
|
||||
gfx_display_ctx_draw_t draw;
|
||||
@@ -4327,7 +4327,7 @@ static void materialui_render_menu_entry_default(
|
||||
gfx_display_t *p_disp = disp_get_ptr();
|
||||
uico_driver_state_t *uico_st = uico_state_get_ptr();
|
||||
|
||||
static float color_white[16] = {
|
||||
static const float color_white[16] = {
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
1.0f, 1.0f, 1.0f, 1.0f,
|
||||
@@ -6148,6 +6148,7 @@ static size_t materialui_list_get_size(void *data, enum menu_list_type type)
|
||||
|
||||
static void materialui_render_background(
|
||||
materialui_handle_t *mui,
|
||||
uintptr_t tex_bg,
|
||||
gfx_display_t *p_disp,
|
||||
void *userdata,
|
||||
unsigned video_width, unsigned video_height,
|
||||
@@ -6183,9 +6184,9 @@ static void materialui_render_background(
|
||||
draw.color = draw_color;
|
||||
draw.texture = 0;
|
||||
|
||||
if (mui->textures.bg && !libretro_running)
|
||||
if (tex_bg && !libretro_running)
|
||||
{
|
||||
draw.texture = mui->textures.bg;
|
||||
draw.texture = tex_bg;
|
||||
|
||||
/* We are showing a wallpaper - set opacity
|
||||
* override to menu_wallpaper_opacity */
|
||||
@@ -6462,6 +6463,7 @@ static void materialui_render_entry_touch_feedback(
|
||||
|
||||
static void materialui_render_header(
|
||||
materialui_handle_t *mui,
|
||||
const uintptr_t *tex_list,
|
||||
struct menu_state *menu_st,
|
||||
menu_list_t *menu_list,
|
||||
settings_t *settings,
|
||||
@@ -6582,27 +6584,27 @@ static void materialui_render_header(
|
||||
/* Set critical by default, to ensure texture_battery
|
||||
* is always valid */
|
||||
uintptr_t texture_battery =
|
||||
mui->textures.list[MUI_TEXTURE_BATTERY_CRITICAL];
|
||||
tex_list[MUI_TEXTURE_BATTERY_CRITICAL];
|
||||
|
||||
/* Draw battery icon */
|
||||
if (powerstate.charging)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_CHARGING];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_CHARGING];
|
||||
else
|
||||
{
|
||||
if (powerstate.percent >= 100)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_100];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_100];
|
||||
else if (powerstate.percent >= 90)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_90];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_90];
|
||||
else if (powerstate.percent >= 80)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_80];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_80];
|
||||
else if (powerstate.percent >= 60)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_60];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_60];
|
||||
else if (powerstate.percent >= 50)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_50];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_50];
|
||||
else if (powerstate.percent >= 30)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_30];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_30];
|
||||
else if (powerstate.percent >= 20)
|
||||
texture_battery = mui->textures.list[MUI_TEXTURE_BATTERY_20];
|
||||
texture_battery = tex_list[MUI_TEXTURE_BATTERY_20];
|
||||
}
|
||||
|
||||
materialui_draw_icon(
|
||||
@@ -6745,7 +6747,7 @@ static void materialui_render_header(
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[MUI_TEXTURE_BACK],
|
||||
tex_list[MUI_TEXTURE_BACK],
|
||||
0,
|
||||
(int)mui->sys_bar_height,
|
||||
0,
|
||||
@@ -6764,7 +6766,7 @@ static void materialui_render_header(
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[MUI_TEXTURE_SEARCH],
|
||||
tex_list[MUI_TEXTURE_SEARCH],
|
||||
(int)video_width - (int)mui->icon_size - (int)mui->nav_bar_layout_width,
|
||||
(int)mui->sys_bar_height,
|
||||
0,
|
||||
@@ -6785,7 +6787,7 @@ static void materialui_render_header(
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[MUI_TEXTURE_SWITCH_VIEW],
|
||||
tex_list[MUI_TEXTURE_SWITCH_VIEW],
|
||||
(int)video_width - (2 * (int)mui->icon_size)
|
||||
- (int)mui->nav_bar_layout_width,
|
||||
(int)mui->sys_bar_height,
|
||||
@@ -6886,6 +6888,7 @@ static void materialui_render_header(
|
||||
* we try to handle this with a single function then
|
||||
* things get incredibly messy and inefficient... */
|
||||
static void materialui_render_nav_bar_bottom(materialui_handle_t *mui,
|
||||
const uintptr_t *tex_list,
|
||||
gfx_display_t *p_disp, void *userdata,
|
||||
unsigned video_width, unsigned video_height, math_matrix_4x4 *mymat)
|
||||
{
|
||||
@@ -6941,7 +6944,7 @@ static void materialui_render_nav_bar_bottom(materialui_handle_t *mui,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[mui->nav_bar.back_tab.texture_index],
|
||||
tex_list[mui->nav_bar.back_tab.texture_index],
|
||||
(int)((0.5f * tab_width) - ((float)mui->icon_size / 2.0f)),
|
||||
nav_bar_y,
|
||||
0,
|
||||
@@ -6957,7 +6960,7 @@ static void materialui_render_nav_bar_bottom(materialui_handle_t *mui,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[mui->nav_bar.resume_tab.texture_index],
|
||||
tex_list[mui->nav_bar.resume_tab.texture_index],
|
||||
(int)((((float)num_tabs - 0.5f) * tab_width) - ((float)mui->icon_size / 2.0f)),
|
||||
nav_bar_y,
|
||||
0,
|
||||
@@ -6980,7 +6983,7 @@ static void materialui_render_nav_bar_bottom(materialui_handle_t *mui,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[tab->texture_index],
|
||||
tex_list[tab->texture_index],
|
||||
(((float)i + 1.5f) * tab_width)
|
||||
- ((float)mui->icon_size / 2.0f),
|
||||
nav_bar_y,
|
||||
@@ -7007,6 +7010,7 @@ static void materialui_render_nav_bar_bottom(materialui_handle_t *mui,
|
||||
}
|
||||
|
||||
static void materialui_render_nav_bar_right(materialui_handle_t *mui,
|
||||
const uintptr_t *tex_list,
|
||||
gfx_display_t *p_disp, void *userdata,
|
||||
unsigned video_width, unsigned video_height,
|
||||
math_matrix_4x4 *mymat)
|
||||
@@ -7063,7 +7067,7 @@ static void materialui_render_nav_bar_right(materialui_handle_t *mui,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[mui->nav_bar.back_tab.texture_index],
|
||||
tex_list[mui->nav_bar.back_tab.texture_index],
|
||||
nav_bar_x,
|
||||
(int)((((float)num_tabs - 0.5f) * tab_height) - ((float)mui->icon_size / 2.0f)),
|
||||
0,
|
||||
@@ -7079,7 +7083,7 @@ static void materialui_render_nav_bar_right(materialui_handle_t *mui,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[mui->nav_bar.resume_tab.texture_index],
|
||||
tex_list[mui->nav_bar.resume_tab.texture_index],
|
||||
nav_bar_x,
|
||||
(int)((0.5f * tab_height)
|
||||
- ((float)mui->icon_size / 2.0f)),
|
||||
@@ -7103,7 +7107,7 @@ static void materialui_render_nav_bar_right(materialui_handle_t *mui,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->icon_size,
|
||||
mui->textures.list[tab->texture_index],
|
||||
tex_list[tab->texture_index],
|
||||
nav_bar_x,
|
||||
(((float)i + 1.5f) * tab_height)
|
||||
- ((float)mui->icon_size / 2.0f),
|
||||
@@ -7130,6 +7134,7 @@ static void materialui_render_nav_bar_right(materialui_handle_t *mui,
|
||||
}
|
||||
|
||||
static void materialui_render_nav_bar(materialui_handle_t *mui,
|
||||
const uintptr_t *tex_list,
|
||||
gfx_display_t *p_disp, void *userdata,
|
||||
unsigned video_width, unsigned video_height,
|
||||
math_matrix_4x4 *mymat)
|
||||
@@ -7138,7 +7143,7 @@ static void materialui_render_nav_bar(materialui_handle_t *mui,
|
||||
{
|
||||
case MUI_NAV_BAR_LOCATION_RIGHT:
|
||||
materialui_render_nav_bar_right(
|
||||
mui, p_disp, userdata, video_width, video_height,
|
||||
mui, tex_list, p_disp, userdata, video_width, video_height,
|
||||
mymat);
|
||||
break;
|
||||
case MUI_NAV_BAR_LOCATION_HIDDEN:
|
||||
@@ -7148,7 +7153,7 @@ static void materialui_render_nav_bar(materialui_handle_t *mui,
|
||||
case MUI_NAV_BAR_LOCATION_BOTTOM:
|
||||
default:
|
||||
materialui_render_nav_bar_bottom(
|
||||
mui, p_disp, userdata, video_width, video_height,
|
||||
mui, tex_list, p_disp, userdata, video_width, video_height,
|
||||
mymat);
|
||||
break;
|
||||
}
|
||||
@@ -7878,6 +7883,15 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
if (!mui)
|
||||
return;
|
||||
|
||||
/* Snapshot texture handles — the main thread may write new
|
||||
* handles via async icon load callbacks or context reset at
|
||||
* any time. Copy the texture list and bg once and use the
|
||||
* snapshots for rendering this frame. */
|
||||
{
|
||||
uintptr_t tex_list[MUI_TEXTURE_LAST];
|
||||
uintptr_t tex_bg = mui->textures.bg;
|
||||
memcpy(tex_list, mui->textures.list, sizeof(tex_list));
|
||||
|
||||
/* If menu screensaver is active, draw
|
||||
* screensaver and return */
|
||||
if (mui->flags & MUI_FLAG_SHOW_SCREENSAVER)
|
||||
@@ -7952,7 +7966,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
list_x_offset = (int)(mui->transition_x_offset * (float)((int)video_width - (int)mui->nav_bar_layout_width));
|
||||
|
||||
/* Draw background */
|
||||
materialui_render_background(mui, p_disp,
|
||||
materialui_render_background(mui, tex_bg, p_disp,
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
@@ -8012,12 +8026,12 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
video_width, video_height, header_height, selection);
|
||||
|
||||
/* Draw title + system bar */
|
||||
materialui_render_header(mui, menu_st, menu_list,
|
||||
materialui_render_header(mui, tex_list, menu_st, menu_list,
|
||||
settings, p_disp, userdata,
|
||||
video_width, video_height, &mymat);
|
||||
|
||||
/* Draw navigation bar */
|
||||
materialui_render_nav_bar(mui, p_disp, userdata,
|
||||
materialui_render_nav_bar(mui, tex_list, p_disp, userdata,
|
||||
video_width, video_height, &mymat);
|
||||
|
||||
/* Flush second layer of text
|
||||
@@ -8068,7 +8082,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
userdata,
|
||||
video_width,
|
||||
video_height,
|
||||
mui->textures.list[MUI_TEXTURE_KEY_HOVER],
|
||||
tex_list[MUI_TEXTURE_KEY_HOVER],
|
||||
mui->font_data.list.font,
|
||||
input_st->osk_grid,
|
||||
input_st->osk_ptr,
|
||||
@@ -8131,7 +8145,7 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
cursor_visible,
|
||||
color_white,
|
||||
mui->cursor_size,
|
||||
mui->textures.list[MUI_TEXTURE_POINTER],
|
||||
tex_list[MUI_TEXTURE_POINTER],
|
||||
mui->pointer.x,
|
||||
mui->pointer.y,
|
||||
video_width,
|
||||
@@ -8150,6 +8164,8 @@ static void materialui_frame(void *data, video_frame_info_t *video_info)
|
||||
if (video_st->current_video && video_st->current_video->set_viewport)
|
||||
video_st->current_video->set_viewport(
|
||||
video_st->data, video_width, video_height, false, true);
|
||||
|
||||
} /* end of texture snapshot scope */
|
||||
}
|
||||
|
||||
/* Determines current list view type, based on
|
||||
|
||||
Reference in new issue
Block a user