Metal: render immediate draws (mouse-face highlight) outside the frame cycle (F1)

note_mouse_highlight -> show_mouse_face draws the mouse-face highlight by
calling draw_glyph_string directly, outside the update_begin/end cycle, so
no Metal render encoder was active and mtl_draw_glyph_string returned early:
the highlight never appeared (the NS backend draws immediately via lockFocus).

Split the drawing body into mtl_draw_glyph_string_impl and make the public
mtl_draw_glyph_string open a self-contained frame (beginFrame uses LOAD, so
the static texture is preserved), draw, then endFrame to present, whenever it
is called with no encoder active. The same path also restores normal text
when the mouse leaves (clear_mouse_face).

Verified by hovering a mouse-face region with cliclick: the region row
background switches to the highlight face (209,210,210) vs (244,244,244) for
a normal row, with +6 draw_glyph_string calls and no-fd == 0; AE vs NS
unchanged at ~0.88%.
This commit is contained in:
Andros Fenollosa 2026-06-02 16:30:43 +02:00
parent e4ece37534
commit 71d289939a

View file

@ -1914,7 +1914,7 @@ mtl_draw_glyph_string_box (struct glyph_string *s, MtlFrameData *fd)
}
static void
mtl_draw_glyph_string (struct glyph_string *s)
mtl_draw_glyph_string_impl (struct glyph_string *s)
{
mtl_dgs_call_count++;
@ -2035,6 +2035,31 @@ mtl_draw_glyph_string (struct glyph_string *s)
mtl_draw_glyph_string_box (s, fd);
}
/* The redisplay engine also draws OUTSIDE the update_begin/end cycle: mouse-face
highlight (note_mouse_highlight show_mouse_face) and other immediate draws
call draw_glyph_string directly, with no Metal render encoder active. The NS
backend draws immediately via lockFocus; we must open a self-contained frame
(LOAD preserves the static texture), draw, then present. Without this the
mouse-face highlight never appeared (the draw was silently dropped). */
static void
mtl_draw_glyph_string (struct glyph_string *s)
{
MtlFrameData *fd = mtl_get_frame_data (s->f);
if (!fd) return;
BOOL opened_here = NO;
if (!fd.encoder)
{
[fd beginFrame];
opened_here = YES;
}
mtl_draw_glyph_string_impl (s);
if (opened_here)
[fd endFrame];
}
static void
mtl_clear_frame (struct frame *f)
{