Metal: inline single-call helpers in render path

Fold the following private methods into their callers:

  MetalDriver:
    -_beginFrame, -_drawCore, -_drawMenu:, -_renderMessage:data:
      → -renderFrame:data:width:height:frameCount:pitch:msg:info:

  FrameView:
    -_convertFormat → -drawWithContext:
    -_initHistory   → -_updateHistory

  TexturedView:
    -_convertFormat → -drawWithContext:

Each of these had exactly one caller and existed only as a name for a
short block of code. Inlining them removes a layer of indirection and,
as a side effect, cleans up some duplicated work the function
boundaries were hiding:

 - _context.rce is now fetched once per frame instead of three times
   (was refetched in _drawCore, _drawMenu:, and the inline overlay
   block).
 - menu_is_alive is computed once instead of twice per frame.
 - video_frame_info_t* no longer crosses a method boundary just to
   read MENU_ST_FLAG_ALIVE.

setViewportWidth:height:forceFull:allowRotate: and MetalMenu's
-updateFrame: are kept as-is; both are entry points for C trampolines
(metal_set_viewport, metal_raster_thread).

No functional change.
This commit is contained in:
U-DESKTOP-SPFP6AQ\twistedtechre committed 2026-04-22 20:50:23 +02:00
1 parent 371f419886
commit 5298e70285
1 file changed
+114 -158
+114 -158
View File
@@ -1504,7 +1504,7 @@ static const NSUInteger kConstantAlignment = 4;
return _frame;
}
- (void)_convertFormat
- (void)drawWithContext:(Context *)ctx
{
if ( _format == RPixelFormatBGRA8Unorm
|| _format == RPixelFormatBGRX8Unorm)
@@ -1517,11 +1517,6 @@ static const NSUInteger kConstantAlignment = 4;
_srcDirty = NO;
}
- (void)drawWithContext:(Context *)ctx
{
[self _convertFormat];
}
- (void)drawWithEncoder:(id<MTLRenderCommandEncoder>)rce
{
[rce setVertexBytes:&_v length:sizeof(_v) atIndex:BufferIndexPositions];
@@ -2468,8 +2463,18 @@ font_renderer_t metal_raster_font = {
@autoreleasepool
{
bool statistics_show = video_info->statistics_show;
bool menu_is_alive = (video_info->menu_st_flags & MENU_ST_FLAG_ALIVE) ? true : false;
id<MTLRenderCommandEncoder> rce;
[self _beginFrame];
/* Begin frame: re-evaluate viewport, push to context if it changed,
* then begin the command buffer / render pass. */
{
video_viewport_t vp = *_viewport;
video_driver_update_viewport(_viewport, NO, _keepAspect, YES);
if (memcmp(&vp, _viewport, sizeof(vp)) != 0)
_context.viewport = _viewport;
[_context begin];
}
_frameView.frameCount = frameCount;
if (frame && width && height)
@@ -2478,12 +2483,46 @@ font_renderer_t metal_raster_font = {
[_frameView updateFrame:frame pitch:pitch];
}
[self _drawCore];
[self _drawMenu:video_info];
rce = _context.rce;
/* Draw core: back buffer + optional encoder pass. */
[_frameView drawWithContext:_context];
if ((_frameView.drawState & ViewDrawStateEncoder) != 0)
{
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineStateNoAlpha];
if (_frameView.filter == RTextureFilterNearest)
[rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw];
else
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
[_frameView drawWithEncoder:rce];
}
/* Draw menu: textured menu frame if present, otherwise delegate to
* the menu driver for widget-based menus. */
if (_menu.enabled)
{
if (_menu.hasFrame)
{
[_menu.view drawWithContext:_context];
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineState];
if (_menu.view.filter == RTextureFilterNearest)
[rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw];
else
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
[_menu.view drawWithEncoder:rce];
}
#if defined(HAVE_MENU)
else
{
[_context resetRenderViewport:kFullscreenViewport];
menu_driver_frame(menu_is_alive, video_info);
}
#endif
}
#ifdef HAVE_OVERLAY
id<MTLRenderCommandEncoder> rce = _context.rce;
if (_overlay.enabled)
{
[_context resetRenderViewport:_overlay.fullscreen ? kFullscreenViewport : kVideoViewport];
@@ -2495,16 +2534,11 @@ font_renderer_t metal_raster_font = {
#endif
/* Only show statistics when menu is not visible and content is running */
if (statistics_show && frame && width && height)
if (statistics_show && frame && width && height && !menu_is_alive)
{
bool menu_is_alive = (video_info->menu_st_flags & MENU_ST_FLAG_ALIVE) ? true : false;
if (!menu_is_alive)
{
struct font_params *osd_params = (struct font_params *)&video_info->osd_stat_params;
if (osd_params)
font_driver_render_msg(data, video_info->stat_text, osd_params, NULL);
}
struct font_params *osd_params = (struct font_params *)&video_info->osd_stat_params;
if (osd_params)
font_driver_render_msg(data, video_info->stat_text, osd_params, NULL);
}
#ifdef HAVE_GFX_WIDGETS
@@ -2512,120 +2546,51 @@ font_renderer_t metal_raster_font = {
gfx_widgets_frame(video_info);
#endif
/* Render on-screen message: optional background quad + text. */
if (msg && *msg)
[self _renderMessage:msg data:data];
{
settings_t *settings = config_get_ptr();
bool msg_bgcolor_enable = settings->bools.video_msg_bgcolor_enable;
if (msg_bgcolor_enable)
{
int msg_width = font_driver_get_message_width(NULL,
msg, strlen(msg), 1.0f);
float font_size = settings->floats.video_font_size;
unsigned bgcolor_red = settings->uints.video_msg_bgcolor_red;
unsigned bgcolor_green= settings->uints.video_msg_bgcolor_green;
unsigned bgcolor_blue = settings->uints.video_msg_bgcolor_blue;
float bgcolor_opacity = settings->floats.video_msg_bgcolor_opacity;
float x = settings->floats.video_msg_pos_x;
float y = 1.0f - settings->floats.video_msg_pos_y;
float width_n = msg_width / (float)_viewport->full_width;
float height_n = font_size / (float)_viewport->full_height;
float x2 = 0.005f; /* extend background around text */
float y2 = 0.005f;
float r = bgcolor_red / 255.0f;
float g = bgcolor_green / 255.0f;
float b = bgcolor_blue / 255.0f;
float a = bgcolor_opacity;
y -= height_n;
x -= x2;
y -= y2;
width_n += x2;
height_n += y2;
[_context resetRenderViewport:kFullscreenViewport];
[_context drawQuadX:x y:y w:width_n h:height_n r:r g:g b:b a:a];
}
font_driver_render_msg(data, msg, NULL, NULL);
}
[self _endFrame];
}
return YES;
}
- (void)_renderMessage:(const char *)msg
data:(void*)data
{
settings_t *settings = config_get_ptr();
bool msg_bgcolor_enable = settings->bools.video_msg_bgcolor_enable;
if (msg_bgcolor_enable)
{
float r, g, b, a;
int msg_width =
font_driver_get_message_width(NULL,
msg, strlen(msg), 1.0f);
float font_size = settings->floats.video_font_size;
unsigned bgcolor_red
= settings->uints.video_msg_bgcolor_red;
unsigned bgcolor_green
= settings->uints.video_msg_bgcolor_green;
unsigned bgcolor_blue
= settings->uints.video_msg_bgcolor_blue;
float bgcolor_opacity = settings->floats.video_msg_bgcolor_opacity;
float x = settings->floats.video_msg_pos_x;
float y = 1.0f - settings->floats.video_msg_pos_y;
float width = msg_width / (float)_viewport->full_width;
float height = font_size / (float)_viewport->full_height;
float x2 = 0.005f; /* extend background around text */
float y2 = 0.005f;
y -= height;
x -= x2;
y -= y2;
width += x2;
height += y2;
r = bgcolor_red / 255.0f;
g = bgcolor_green / 255.0f;
b = bgcolor_blue / 255.0f;
a = bgcolor_opacity;
[_context resetRenderViewport:kFullscreenViewport];
[_context drawQuadX:x y:y w:width h:height r:r g:g b:b a:a];
}
font_driver_render_msg(data, msg, NULL, NULL);
}
- (void)_beginFrame
{
video_viewport_t vp = *_viewport;
video_driver_update_viewport(_viewport, NO, _keepAspect, YES);
if (memcmp(&vp, _viewport, sizeof(vp)) != 0)
_context.viewport = _viewport;
[_context begin];
}
- (void)_drawCore
{
id<MTLRenderCommandEncoder> rce = _context.rce;
/* draw back buffer */
[_frameView drawWithContext:_context];
if ((_frameView.drawState & ViewDrawStateEncoder) != 0)
{
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineStateNoAlpha];
if (_frameView.filter == RTextureFilterNearest)
[rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw];
else
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
[_frameView drawWithEncoder:rce];
}
}
- (void)_drawMenu:(video_frame_info_t *)video_info
{
bool menu_is_alive = (video_info->menu_st_flags & MENU_ST_FLAG_ALIVE) ? true : false;
if (!_menu.enabled)
return;
id<MTLRenderCommandEncoder> rce = _context.rce;
if (_menu.hasFrame)
{
[_menu.view drawWithContext:_context];
[rce setVertexBytes:_context.uniforms length:sizeof(*_context.uniforms) atIndex:BufferIndexUniforms];
[rce setRenderPipelineState:_t_pipelineState];
if (_menu.view.filter == RTextureFilterNearest)
[rce setFragmentSamplerState:_samplerStateNearest atIndex:SamplerIndexDraw];
else
[rce setFragmentSamplerState:_samplerStateLinear atIndex:SamplerIndexDraw];
[_menu.view drawWithEncoder:rce];
}
#if defined(HAVE_MENU)
else
{
[_context resetRenderViewport:kFullscreenViewport];
menu_driver_frame(menu_is_alive, video_info);
}
#endif
}
- (void)_endFrame { [_context end]; }
/* TODO/FIXME (sgc): resize*/
- (void)setNeedsResize { }
@@ -2921,19 +2886,6 @@ typedef struct MTLALIGN(16)
- (CGRect)frame { return _frame; }
- (void)_convertFormat
{
if ( _format == RPixelFormatBGRA8Unorm
|| _format == RPixelFormatBGRX8Unorm)
return;
if (!_srcDirty)
return;
[_context convertFormat:_format from:_src to:_texture];
_srcDirty = NO;
}
- (void)_updateHistory
{
if (_shader)
@@ -2941,7 +2893,20 @@ typedef struct MTLALIGN(16)
if (_shader->history_size)
{
if (init_history)
[self _initHistory];
{
int i;
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:(NSUInteger)_size.width
height:(NSUInteger)_size.height
mipmapped:false];
td.usage = MTLTextureUsageShaderRead
| MTLTextureUsageShaderWrite
| MTLTextureUsageRenderTarget;
for (i = 0; i < _shader->history_size + 1; i++)
[self _initTexture:&_engine.frame.texture[i] withDescriptor:td];
init_history = NO;
}
else
{
int k;
@@ -3033,22 +2998,6 @@ typedef struct MTLALIGN(16)
t->size_data.w = 1.0f / td.height;
}
- (void)_initHistory
{
int i;
MTLTextureDescriptor *td = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
width:(NSUInteger)_size.width
height:(NSUInteger)_size.height
mipmapped:false];
td.usage = MTLTextureUsageShaderRead
| MTLTextureUsageShaderWrite
| MTLTextureUsageRenderTarget;
for (i = 0; i < _shader->history_size + 1; i++)
[self _initTexture:&_engine.frame.texture[i] withDescriptor:td];
init_history = NO;
}
- (void)drawWithEncoder:(id<MTLRenderCommandEncoder>)rce
{
if (_texture)
@@ -3064,7 +3013,14 @@ typedef struct MTLALIGN(16)
{
int i;
_texture = _engine.frame.texture[0].view;
[self _convertFormat];
if ( (_format != RPixelFormatBGRA8Unorm)
&& (_format != RPixelFormatBGRX8Unorm)
&& _srcDirty)
{
[_context convertFormat:_format from:_src to:_texture];
_srcDirty = NO;
}
if (!_shader || _shader->passes == 0)
return;