mirror of
https://github.com/libretro/RetroArch.git
synced 2026-11-09 03:29:43 -10:00
video_driver: extract cached-frame state to file-scope statics
Follow-up to the cached-frame redesign series (934dcf5..2d9af0d).
After the API migration landed, no TU outside gfx/video_driver.c
referenced frame_cache_data / frame_cache_width /
frame_cache_height / frame_cache_pitch -- the privacy was
enforced by convention. This commit makes it structural: the
four fields move out of video_driver_state_t and become
file-scope statics in video_driver.c.
Effect:
- The fields cannot be referenced from another TU even by
accident, since they're not in the struct anymore and they're
static. Future code can't reintroduce the pre-redesign UAF
pattern by typo.
- sizeof(video_driver_state_t) shrinks by 24 bytes on 64-bit
(one pointer + one size_t + two unsigned). Only one instance
exists, so the size win is symbolic; the readability win is
the point.
- All internal video_driver.c sites that previously did
video_st->frame_cache_* now do bare frame_cache_*. Identical
semantics; the lock-and-callback contract on cached_frame_read
/ publish / invalidate is unchanged.
Stale comments in command.c (the reinit snapshot block) updated
to reference the publish API instead of the no-longer-existing
field. A residual mention of 'frame_cache_data' in runloop.c
and gfx/drivers/d3d12.c is comment-only and accurate as a
description of the cached frame's role.
Compile-checked: gfx/video_driver.c plus every consumer file
that touched the old fields (runloop.c, retroarch.c, command.c,
tasks/task_*.c, cheevos/cheevos.c) all build clean against the
extracted statics.
This commit is contained in:
1 parent
2d9af0dcc8
commit
a7ccc0438a
3 files changed
+63
-54
No files matched your search
@@ -2578,27 +2578,29 @@ void command_event_reinit(const int flags)
|
||||
*sec_joypad = NULL;
|
||||
#endif
|
||||
/* Snapshot the last cached core frame before tearing the video
|
||||
* driver down. video_driver_free() nulls frame_cache_data as part
|
||||
* of the reinit cycle (the pointer was borrowed from the core's
|
||||
* own framebuffer and isn't guaranteed to stay live across the
|
||||
* driver swap), so without a snapshot the new driver would come
|
||||
* up with no core image to replay. Restored + replayed below so
|
||||
* the paused-core background remains visible when reinit is
|
||||
* triggered from inside the menu (e.g. HDR mode toggle).
|
||||
* driver down. video_driver_free() invalidates the cache as
|
||||
* part of the reinit cycle (the pointer was borrowed from the
|
||||
* core's own framebuffer and isn't guaranteed to stay live
|
||||
* across the driver swap), so without a snapshot the new
|
||||
* driver would come up with no core image to replay. Restored
|
||||
* + replayed below so the paused-core background remains
|
||||
* visible when reinit is triggered from inside the menu (e.g.
|
||||
* HDR mode toggle).
|
||||
*
|
||||
* The snapshot buffer is static and reused across reinits — we
|
||||
* need it to outlive command_event_reinit because we hand the
|
||||
* pointer to video_st->frame_cache_data for the new driver to
|
||||
* read via video_driver_cached_frame(), and the core's next real
|
||||
* frame will replace the pointer at its leisure. Resizing in
|
||||
* place on each call keeps it bounded at one buffer's worth.
|
||||
* need it to outlive command_event_reinit because we publish
|
||||
* the pointer back through video_driver_cached_frame_publish
|
||||
* for the new driver to read via video_driver_cached_frame(),
|
||||
* and the core's next real frame will replace the pointer at
|
||||
* its leisure. Resizing in place on each call keeps it
|
||||
* bounded at one buffer's worth.
|
||||
*
|
||||
* The actual copy happens inside the cached_frame_read callback
|
||||
* (which is what this function was hand-rolling before the
|
||||
* unified read API existed -- exactly the same pattern,
|
||||
* lifted into one place). HW-render frames are skipped: the
|
||||
* callback receives data == NULL for those, so we don't even
|
||||
* allocate. */
|
||||
* The actual copy happens inside the cached_frame_read
|
||||
* callback (which is what this function was hand-rolling
|
||||
* before the unified read API existed -- exactly the same
|
||||
* pattern, lifted into one place). HW-render frames are
|
||||
* skipped: the callback receives data == NULL for those, so
|
||||
* we don't even allocate. */
|
||||
static void *cached_snapshot = NULL;
|
||||
static size_t cached_snapshot_cap = 0;
|
||||
unsigned cached_snapshot_w = 0;
|
||||
|
||||
+43
-31
@@ -492,6 +492,18 @@ static video_driver_state_t video_driver_st = { 0 };
|
||||
static const video_display_server_t *current_display_server =
|
||||
&dispserv_null;
|
||||
|
||||
/* Cached-frame state. Private to this TU; all access goes through
|
||||
* video_driver_cached_frame_{info,read,is_hw_render,publish,
|
||||
* invalidate} (any-thread, locked) or the same-thread
|
||||
* video_driver_cached_frame() replay path. Extracted from
|
||||
* video_driver_state_t after the API migration landed so the
|
||||
* privacy is structural (file-scope static) rather than
|
||||
* convention (struct field accessed only through helpers). */
|
||||
static const void *frame_cache_data = NULL;
|
||||
static unsigned frame_cache_width = 0;
|
||||
static unsigned frame_cache_height = 0;
|
||||
static size_t frame_cache_pitch = 0;
|
||||
|
||||
struct retro_hw_render_callback *video_driver_get_hw_context(void)
|
||||
{
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
@@ -2462,8 +2474,8 @@ static void video_viewport_get_scaled_integer(
|
||||
int padding_y = 0;
|
||||
float vp_bias_x = settings->floats.video_vp_bias_x;
|
||||
float vp_bias_y = settings->floats.video_vp_bias_y;
|
||||
unsigned content_width = video_st->frame_cache_width;
|
||||
unsigned content_height = video_st->frame_cache_height;
|
||||
unsigned content_width = frame_cache_width;
|
||||
unsigned content_height = frame_cache_height;
|
||||
#if defined(RARCH_MOBILE)
|
||||
if (width < height)
|
||||
{
|
||||
@@ -2611,8 +2623,8 @@ static void video_viewport_get_scaled_integer(
|
||||
|
||||
/* Reset width to exact width */
|
||||
content_width = (rotation % 2)
|
||||
? ((video_st->frame_cache_height <= 4) ? video_st->av_info.geometry.base_height : video_st->frame_cache_height)
|
||||
: ((video_st->frame_cache_width <= 4) ? video_st->av_info.geometry.base_width : video_st->frame_cache_width);
|
||||
? ((frame_cache_height <= 4) ? video_st->av_info.geometry.base_height : frame_cache_height)
|
||||
: ((frame_cache_width <= 4) ? video_st->av_info.geometry.base_width : frame_cache_width);
|
||||
|
||||
overscale_w = (width / content_width) + !!(width % content_width);
|
||||
|
||||
@@ -3206,12 +3218,12 @@ void video_driver_cached_frame(void)
|
||||
|
||||
if (runloop_st->current_core.flags & RETRO_CORE_FLAG_INITED)
|
||||
cbs->frame_cb(
|
||||
(video_st->frame_cache_data != RETRO_HW_FRAME_BUFFER_VALID)
|
||||
? video_st->frame_cache_data
|
||||
(frame_cache_data != RETRO_HW_FRAME_BUFFER_VALID)
|
||||
? frame_cache_data
|
||||
: NULL,
|
||||
video_st->frame_cache_width,
|
||||
video_st->frame_cache_height,
|
||||
video_st->frame_cache_pitch);
|
||||
frame_cache_width,
|
||||
frame_cache_height,
|
||||
frame_cache_pitch);
|
||||
|
||||
recording_st->data = recording;
|
||||
}
|
||||
@@ -3266,14 +3278,14 @@ bool video_driver_cached_frame_info(
|
||||
bool has_frame;
|
||||
|
||||
cached_frame_lock_acquire();
|
||||
data = video_st->frame_cache_data;
|
||||
data = frame_cache_data;
|
||||
has_frame = (data != NULL);
|
||||
|
||||
if (has_frame)
|
||||
{
|
||||
if (width) *width = video_st->frame_cache_width;
|
||||
if (height) *height = video_st->frame_cache_height;
|
||||
if (pitch) *pitch = video_st->frame_cache_pitch;
|
||||
if (width) *width = frame_cache_width;
|
||||
if (height) *height = frame_cache_height;
|
||||
if (pitch) *pitch = frame_cache_pitch;
|
||||
if (has_cpu_pixels) *has_cpu_pixels =
|
||||
(data != RETRO_HW_FRAME_BUFFER_VALID);
|
||||
}
|
||||
@@ -3315,13 +3327,13 @@ void video_driver_cached_frame_read(
|
||||
* guarantee the redesign introduces: the pointer handed to the
|
||||
* callback cannot be freed out from under it. */
|
||||
cached_frame_lock_acquire();
|
||||
data = video_st->frame_cache_data;
|
||||
data = frame_cache_data;
|
||||
hw_or_empty = (!data || data == RETRO_HW_FRAME_BUFFER_VALID);
|
||||
if (!hw_or_empty)
|
||||
{
|
||||
width = video_st->frame_cache_width;
|
||||
height = video_st->frame_cache_height;
|
||||
pitch = video_st->frame_cache_pitch;
|
||||
width = frame_cache_width;
|
||||
height = frame_cache_height;
|
||||
pitch = frame_cache_pitch;
|
||||
}
|
||||
|
||||
/* Hand the callback NULL when no CPU pixels are available, so
|
||||
@@ -3337,8 +3349,8 @@ bool video_driver_cached_frame_is_hw_render(void)
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
bool is_hw;
|
||||
cached_frame_lock_acquire();
|
||||
is_hw = video_st->frame_cache_data
|
||||
&& video_st->frame_cache_data == RETRO_HW_FRAME_BUFFER_VALID;
|
||||
is_hw = frame_cache_data
|
||||
&& frame_cache_data == RETRO_HW_FRAME_BUFFER_VALID;
|
||||
cached_frame_lock_release();
|
||||
return is_hw;
|
||||
}
|
||||
@@ -3355,10 +3367,10 @@ void video_driver_cached_frame_publish(
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
cached_frame_lock_acquire();
|
||||
if (data)
|
||||
video_st->frame_cache_data = data;
|
||||
video_st->frame_cache_width = width;
|
||||
video_st->frame_cache_height = height;
|
||||
video_st->frame_cache_pitch = pitch;
|
||||
frame_cache_data = data;
|
||||
frame_cache_width = width;
|
||||
frame_cache_height = height;
|
||||
frame_cache_pitch = pitch;
|
||||
cached_frame_lock_release();
|
||||
}
|
||||
|
||||
@@ -3373,10 +3385,10 @@ void video_driver_cached_frame_invalidate(void)
|
||||
{
|
||||
video_driver_state_t *video_st = &video_driver_st;
|
||||
cached_frame_lock_acquire();
|
||||
video_st->frame_cache_data = NULL;
|
||||
video_st->frame_cache_width = 0;
|
||||
video_st->frame_cache_height = 0;
|
||||
video_st->frame_cache_pitch = 0;
|
||||
frame_cache_data = NULL;
|
||||
frame_cache_width = 0;
|
||||
frame_cache_height = 0;
|
||||
frame_cache_pitch = 0;
|
||||
cached_frame_lock_release();
|
||||
}
|
||||
|
||||
@@ -4892,8 +4904,8 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
" Blocking: %6.2f %%\n"
|
||||
" Samples: %8d\n"
|
||||
,
|
||||
video_st->frame_cache_width,
|
||||
video_st->frame_cache_height,
|
||||
frame_cache_width,
|
||||
frame_cache_height,
|
||||
av_info->geometry.base_width,
|
||||
av_info->geometry.base_height,
|
||||
av_info->geometry.max_width,
|
||||
@@ -4907,9 +4919,9 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
video_info.scale_width,
|
||||
video_info.scale_height,
|
||||
(float)video_info.scale_width / ((rotation % 2)
|
||||
? (float)video_st->frame_cache_height : (float)video_st->frame_cache_width),
|
||||
? (float)frame_cache_height : (float)frame_cache_width),
|
||||
(float)video_info.scale_height / ((rotation % 2)
|
||||
? (float)video_st->frame_cache_width : (float)video_st->frame_cache_height),
|
||||
? (float)frame_cache_width : (float)frame_cache_height),
|
||||
video_info.refresh_rate,
|
||||
last_fps,
|
||||
frame_time / 1000.0f,
|
||||
|
||||
@@ -829,8 +829,6 @@ typedef struct
|
||||
|
||||
void *current_display_server_data;
|
||||
|
||||
const void *frame_cache_data;
|
||||
|
||||
const struct
|
||||
retro_hw_render_context_negotiation_interface *
|
||||
hw_render_context_negotiation;
|
||||
@@ -849,7 +847,6 @@ typedef struct
|
||||
uintptr_t display;
|
||||
uintptr_t window;
|
||||
|
||||
size_t frame_cache_pitch;
|
||||
size_t window_title_len;
|
||||
|
||||
uint32_t flags;
|
||||
@@ -858,8 +855,6 @@ typedef struct
|
||||
unsigned state_scale;
|
||||
unsigned state_out_bpp;
|
||||
#endif
|
||||
unsigned frame_cache_width;
|
||||
unsigned frame_cache_height;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned scale_width;
|
||||
|
||||
Reference in new issue
Block a user