@samitouri / QOSamiQemu / commits / 3faf2b0ae1

ui/console-vc: decouple VT100 display updates via function pointer

Replace direct dpy_gfx_update() calls from the VT100 emulation code with an indirect call through a new image_update function pointer in QemuVT100. This decouples the VT100 terminal emulation from the QEMU display layer, allowing different backends to provide their own image update implementation. The QemuVT100 typedef is changed to a forward-declared struct so the function pointer signature can reference QemuVT100 itself. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>

Marc-André Lureau committed Feb 19, 2026 at 12:39 UTC 3faf2b0ae1affe926ea818a3f354753874f3d1bf
1 file changed +22 -6
ui/console-vc.c
+22 -6
@@ -47,8 +47,11 @@ enum TTYState {
47 TTY_STATE_OSC,
48 };
49
50 -typedef struct QemuVT100 {
50 +typedef struct QemuVT100 QemuVT100;
51 +
52 +struct QemuVT100 {
53 pixman_image_t *image;
54 + void (*image_update)(QemuVT100 *vt, int x, int y, int width, int height);
55
56 int width;
57 int height;
@@ -65,7 +68,7 @@ typedef struct QemuVT100 {
68 int update_y0;
69 int update_x1;
70 int update_y1;
68 -} QemuVT100;
71 +};
72
73 typedef struct QemuTextConsole {
74 QemuConsole parent;
@@ -221,6 +224,11 @@ static void vt100_show_cursor(QemuVT100 *vt, int show)
224 }
225 }
226
227 +static void vt100_image_update(QemuVT100 *vt, int x, int y, int width, int height)
228 +{
229 + vt->image_update(vt, x, y, width, height);
230 +}
231 +
232 static void console_refresh(QemuTextConsole *s)
233 {
234 QemuVT100 *vt = &s->vt;
@@ -250,7 +258,7 @@ static void console_refresh(QemuTextConsole *s)
258 }
259 }
260 vt100_show_cursor(&s->vt, 1);
253 - dpy_gfx_update(QEMU_CONSOLE(s), 0, 0, w, h);
261 + vt100_image_update(&s->vt, 0, 0, w, h);
262 }
263
264 static void console_scroll(QemuTextConsole *s, int ydelta)
@@ -1028,9 +1036,9 @@ static int vc_chr_write(Chardev *chr, const uint8_t *buf, int len)
1036 }
1037 vt100_show_cursor(vt, 1);
1038 if (vt->update_x0 < vt->update_x1) {
1031 - dpy_gfx_update(QEMU_CONSOLE(s), vt->update_x0, vt->update_y0,
1032 - vt->update_x1 - vt->update_x0,
1033 - vt->update_y1 - vt->update_y0);
1039 + vt100_image_update(vt, vt->update_x0, vt->update_y0,
1040 + vt->update_x1 - vt->update_x0,
1041 + vt->update_y1 - vt->update_y0);
1042 }
1043 return len;
1044 }
@@ -1128,6 +1136,13 @@ void qemu_text_console_update_size(QemuTextConsole *c)
1136 dpy_text_resize(QEMU_CONSOLE(c), c->vt.width, c->vt.height);
1137 }
1138
1139 +static void text_console_image_update(QemuVT100 *vt, int x, int y, int width, int height)
1140 +{
1141 + QemuTextConsole *console = container_of(vt, QemuTextConsole, vt);
1142 +
1143 + dpy_gfx_update(QEMU_CONSOLE(console), x, y, width, height);
1144 +}
1145 +
1146 static bool vc_chr_open(Chardev *chr, ChardevBackend *backend, Error **errp)
1147 {
1148 ChardevVC *vc = backend->u.vc.data;
@@ -1158,6 +1173,7 @@ static bool vc_chr_open(Chardev *chr, ChardevBackend *backend, Error **errp)
1173 }
1174
1175 dpy_gfx_replace_surface(QEMU_CONSOLE(s), qemu_create_displaysurface(width, height));
1176 + s->vt.image_update = text_console_image_update;
1177
1178 s->chr = chr;
1179 drv->console = s;