ui/console: return completion status from gfx_update callback
Replace the two-field design (gfx_update void callback + gfx_update_async flag) with a single bool return value from gfx_update. Returning true means the update completed synchronously and graphic_hw_update_done() should be called by the console layer. Returning false means the update is deferred and the device will call graphic_hw_update_done() itself later (as done by QXL/SPICE and Apple GFX). This simplifies the interface and makes the async contract explicit at each call site rather than relying on a separate struct field. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Marc-André Lureau committed
Mar 5, 2026 at 13:58 UTC
c6e94d24fb81b482dcce9df8311062e4847d6cc6
32 files changed
+132
-89
hw/arm/musicpal.c
+2
-1
@@ -152,7 +152,7 @@ static inline void set_lcd_pixel32(musicpal_lcd_state *s,
152
}
153
}
154
155
-static void lcd_refresh(void *opaque)
155
+static bool lcd_refresh(void *opaque)
156
{
157
musicpal_lcd_state *s = opaque;
158
int x, y, col;
@@ -171,6 +171,7 @@ static void lcd_refresh(void *opaque)
171
}
172
173
dpy_gfx_update(s->con, 0, 0, 128*3, 64*3);
174
+ return true;
175
}
176
177
static void lcd_invalidate(void *opaque)
hw/display/apple-gfx.m
+5
-5
@@ -330,25 +330,25 @@ static void apple_gfx_render_frame_completed_bh(void *opaque)
330
}
331
}
332
333
-static void apple_gfx_fb_update_display(void *opaque)
333
+static bool apple_gfx_fb_update_display(void *opaque)
334
{
335
AppleGFXState *s = opaque;
336
+ bool done = true;
337
338
assert(bql_locked());
339
if (s->new_frame_ready) {
340
dpy_gfx_update_full(s->con);
341
s->new_frame_ready = false;
341
- graphic_hw_update_done(s->con);
342
} else if (s->pending_frames > 0) {
343
s->gfx_update_requested = true;
344
- } else {
345
- graphic_hw_update_done(s->con);
344
+ done = false;
345
}
346
+
347
+ return done;
348
}
349
350
static const GraphicHwOps apple_gfx_fb_ops = {
351
.gfx_update = apple_gfx_fb_update_display,
351
- .gfx_update_async = true,
352
};
353
354
/* ------ Mouse cursor and display mode setting ------ */
hw/display/artist.c
+3
-1
@@ -1311,7 +1311,7 @@ static void artist_draw_line(void *opaque, uint8_t *d, const uint8_t *src,
1311
}
1312
}
1313
1314
-static void artist_update_display(void *opaque)
1314
+static bool artist_update_display(void *opaque)
1315
{
1316
ARTISTState *s = opaque;
1317
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -1326,6 +1326,8 @@ static void artist_update_display(void *opaque)
1326
if (first >= 0) {
1327
dpy_gfx_update(s->con, 0, first, s->width, last - first + 1);
1328
}
1329
+
1330
+ return true;
1331
}
1332
1333
static void artist_invalidate(void *opaque)
hw/display/bcm2835_fb.c
+4
-3
@@ -150,7 +150,7 @@ static bool fb_use_offsets(BCM2835FBConfig *config)
150
config->yres_virtual > config->yres;
151
}
152
153
-static void fb_update_display(void *opaque)
153
+static bool fb_update_display(void *opaque)
154
{
155
BCM2835FBState *s = opaque;
156
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -161,7 +161,7 @@ static void fb_update_display(void *opaque)
161
uint32_t xoff = 0, yoff = 0;
162
163
if (s->lock || !s->config.xres) {
164
- return;
164
+ return true;
165
}
166
167
src_width = bcm2835_fb_get_pitch(&s->config);
@@ -174,7 +174,7 @@ static void fb_update_display(void *opaque)
174
175
switch (surface_bits_per_pixel(surface)) {
176
case 0:
177
- return;
177
+ return true;
178
case 8:
179
break;
180
case 15:
@@ -212,6 +212,7 @@ static void fb_update_display(void *opaque)
212
}
213
214
s->invalidate = false;
215
+ return true;
216
}
217
218
void bcm2835_fb_validate_config(BCM2835FBConfig *config)
hw/display/bochs-display.c
+4
-2
@@ -198,7 +198,7 @@ static int bochs_display_get_mode(BochsDisplayState *s,
198
return 0;
199
}
200
201
-static void bochs_display_update(void *opaque)
201
+static bool bochs_display_update(void *opaque)
202
{
203
BochsDisplayState *s = opaque;
204
DirtyBitmapSnapshot *snap = NULL;
@@ -212,7 +212,7 @@ static void bochs_display_update(void *opaque)
212
ret = bochs_display_get_mode(s, &mode);
213
if (ret < 0) {
214
/* no (valid) video mode */
215
- return;
215
+ return true;
216
}
217
218
if (memcmp(&s->mode, &mode, sizeof(mode)) != 0) {
@@ -255,6 +255,8 @@ static void bochs_display_update(void *opaque)
255
256
g_free(snap);
257
}
258
+
259
+ return true;
260
}
261
262
static const GraphicHwOps bochs_display_gfx_ops = {
hw/display/cg3.c
+3
-2
@@ -85,7 +85,7 @@ struct CG3State {
85
uint8_t dac_index, dac_state;
86
};
87
88
-static void cg3_update_display(void *opaque)
88
+static bool cg3_update_display(void *opaque)
89
{
90
CG3State *s = opaque;
91
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -98,7 +98,7 @@ static void cg3_update_display(void *opaque)
98
DirtyBitmapSnapshot *snap = NULL;
99
100
if (surface_bits_per_pixel(surface) != 32) {
101
- return;
101
+ return true;
102
}
103
width = s->width;
104
height = s->height;
@@ -154,6 +154,7 @@ static void cg3_update_display(void *opaque)
154
qemu_irq_raise(s->irq);
155
}
156
g_free(snap);
157
+ return true;
158
}
159
160
static void cg3_invalidate_display(void *opaque)
hw/display/dm163.c
+3
-1
@@ -285,7 +285,7 @@ static uint32_t *update_display_of_row(DM163State *s, uint32_t *dest,
285
return dest;
286
}
287
288
-static void dm163_update_display(void *opaque)
288
+static bool dm163_update_display(void *opaque)
289
{
290
DM163State *s = (DM163State *)opaque;
291
DisplaySurface *surface = qemu_console_surface(s->console);
@@ -300,6 +300,8 @@ static void dm163_update_display(void *opaque)
300
}
301
dest = update_display_of_row(s, dest, row);
302
}
303
+
304
+ return true;
305
}
306
307
static const GraphicHwOps dm163_ops = {
hw/display/exynos4210_fimd.c
+4
-2
@@ -1270,7 +1270,7 @@ static void exynos4210_update_resolution(Exynos4210fimdState *s)
1270
}
1271
}
1272
1273
-static void exynos4210_fimd_update(void *opaque)
1273
+static bool exynos4210_fimd_update(void *opaque)
1274
{
1275
Exynos4210fimdState *s = (Exynos4210fimdState *)opaque;
1276
DisplaySurface *surface;
@@ -1287,7 +1287,7 @@ static void exynos4210_fimd_update(void *opaque)
1287
1288
if (!s || !s->console || !s->enabled ||
1289
surface_bits_per_pixel(qemu_console_surface(s->console)) == 0) {
1290
- return;
1290
+ return true;
1291
}
1292
1293
global_width = (s->vidtcon[2] & FIMD_VIDTCON2_SIZE_MASK) + 1;
@@ -1348,6 +1348,8 @@ static void exynos4210_fimd_update(void *opaque)
1348
exynos4210_fimd_enable(s, false);
1349
}
1350
exynos4210_fimd_update_irq(s);
1351
+
1352
+ return true;
1353
}
1354
1355
static void exynos4210_fimd_reset(DeviceState *d)
hw/display/g364fb.c
+6
-3
@@ -238,15 +238,16 @@ static void g364fb_draw_blank(G364State *s)
238
s->blanked = 1;
239
}
240
241
-static void g364fb_update_display(void *opaque)
241
+static bool g364fb_update_display(void *opaque)
242
{
243
G364State *s = opaque;
244
DisplaySurface *surface = qemu_console_surface(s->con);
245
246
qemu_flush_coalesced_mmio_buffer();
247
248
- if (s->width == 0 || s->height == 0)
249
- return;
248
+ if (s->width == 0 || s->height == 0) {
249
+ return true;
250
+ }
251
252
if (s->width != surface_width(surface) ||
253
s->height != surface_height(surface)) {
@@ -262,6 +263,8 @@ static void g364fb_update_display(void *opaque)
263
}
264
265
qemu_irq_raise(s->irq);
266
+
267
+ return true;
268
}
269
270
static inline void g364fb_invalidate_display(void *opaque)
hw/display/imx6ul_lcdif.c
+4
-3
@@ -152,7 +152,7 @@ static void imx6ul_lcdif_draw_line_xrgb8888(void *opaque, uint8_t *dst,
152
}
153
}
154
155
-static void imx6ul_lcdif_update_display(void *opaque)
155
+static bool imx6ul_lcdif_update_display(void *opaque)
156
{
157
IMX6ULLCDIFState *s = opaque;
158
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -167,7 +167,7 @@ static void imx6ul_lcdif_update_display(void *opaque)
167
int src_width;
168
169
if (!imx6ul_lcdif_is_running(s) || width == 0 || height == 0) {
170
- return;
170
+ return true;
171
}
172
173
switch (FIELD_EX32(ctrl, CTRL, WORD_LENGTH)) {
@@ -180,7 +180,7 @@ static void imx6ul_lcdif_update_display(void *opaque)
180
fn = imx6ul_lcdif_draw_line_xrgb8888;
181
break;
182
default:
183
- return;
183
+ return true;
184
}
185
186
if (surface_width(surface) != width || surface_height(surface) != height) {
@@ -207,6 +207,7 @@ static void imx6ul_lcdif_update_display(void *opaque)
207
}
208
209
s->invalidate = false;
210
+ return true;
211
}
212
213
static void imx6ul_lcdif_invalidate_display(void *opaque)
hw/display/jazz_led.c
+4
-2
@@ -144,7 +144,7 @@ static void draw_vertical_line(DisplaySurface *ds,
144
}
145
}
146
147
-static void jazz_led_update_display(void *opaque)
147
+static bool jazz_led_update_display(void *opaque)
148
{
149
LedState *s = opaque;
150
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -186,7 +186,7 @@ static void jazz_led_update_display(void *opaque)
186
color_led = rgb_to_pixel32(0x00, 0xff, 0x00);
187
break;
188
default:
189
- return;
189
+ return true;
190
}
191
192
/* display segments */
@@ -218,6 +218,8 @@ static void jazz_led_update_display(void *opaque)
218
219
s->state = REDRAW_NONE;
220
dpy_gfx_update_full(s->con);
221
+
222
+ return true;
223
}
224
225
static void jazz_led_invalidate_display(void *opaque)
hw/display/macfb.c
+4
-2
@@ -454,7 +454,7 @@ static gchar *macfb_mode_list(void)
454
}
455
456
457
-static void macfb_update_display(void *opaque)
457
+static bool macfb_update_display(void *opaque)
458
{
459
MacfbState *s = opaque;
460
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -462,7 +462,7 @@ static void macfb_update_display(void *opaque)
462
qemu_flush_coalesced_mmio_buffer();
463
464
if (s->width == 0 || s->height == 0) {
465
- return;
465
+ return true;
466
}
467
468
if (s->width != surface_width(surface) ||
@@ -471,6 +471,8 @@ static void macfb_update_display(void *opaque)
471
}
472
473
macfb_draw_graphic(s);
474
+
475
+ return true;
476
}
477
478
static void macfb_update_irq(MacfbState *s)
hw/display/next-fb.c
+3
-1
@@ -67,7 +67,7 @@ static void nextfb_draw_line(void *opaque, uint8_t *d, const uint8_t *s,
67
}
68
}
69
70
-static void nextfb_update(void *opaque)
70
+static bool nextfb_update(void *opaque)
71
{
72
NeXTFbState *s = NEXTFB(opaque);
73
int dest_width = 4;
@@ -90,6 +90,8 @@ static void nextfb_update(void *opaque)
90
s, &first, &last);
91
92
dpy_gfx_update(s->con, 0, 0, s->cols, s->rows);
93
+
94
+ return true;
95
}
96
97
static void nextfb_invalidate(void *opaque)
hw/display/omap_lcdc.c
+8
-6
@@ -197,7 +197,7 @@ static void draw_line16_32(void *opaque, uint8_t *d, const uint8_t *s,
197
} while (-- width != 0);
198
}
199
200
-static void omap_update_display(void *opaque)
200
+static bool omap_update_display(void *opaque)
201
{
202
struct omap_lcd_panel_s *omap_lcd = opaque;
203
DisplaySurface *surface;
@@ -207,12 +207,12 @@ static void omap_update_display(void *opaque)
207
hwaddr frame_base;
208
209
if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable) {
210
- return;
210
+ return true;
211
}
212
213
surface = qemu_console_surface(omap_lcd->con);
214
if (!surface_bits_per_pixel(surface)) {
215
- return;
215
+ return true;
216
}
217
218
frame_offset = 0;
@@ -256,7 +256,7 @@ static void omap_update_display(void *opaque)
256
257
default:
258
/* Unsupported at the moment. */
259
- return;
259
+ return true;
260
}
261
262
/* Resolution */
@@ -278,7 +278,7 @@ static void omap_update_display(void *opaque)
278
omap_lcd->sync_error = 1;
279
omap_lcd_interrupts(omap_lcd);
280
omap_lcd->enable = 0;
281
- return;
281
+ return true;
282
}
283
284
/* Content */
@@ -291,7 +291,7 @@ static void omap_update_display(void *opaque)
291
omap_lcd->dma->current_frame ^= 1;
292
293
if (!surface_bits_per_pixel(surface)) {
294
- return;
294
+ return true;
295
}
296
297
first = 0;
@@ -323,6 +323,8 @@ static void omap_update_display(void *opaque)
323
dpy_gfx_update(omap_lcd->con, 0, first, width, last - first + 1);
324
}
325
omap_lcd->invalidate = 0;
326
+
327
+ return true;
328
}
329
330
static void omap_invalidate_display(void *opaque) {
hw/display/pl110.c
+3
-2
@@ -210,7 +210,7 @@ static int pl110_enabled(PL110State *s)
210
return (s->cr & PL110_CR_EN) && (s->cr & PL110_CR_PWR);
211
}
212
213
-static void pl110_update_display(void *opaque)
213
+static bool pl110_update_display(void *opaque)
214
{
215
PL110State *s = (PL110State *)opaque;
216
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -221,7 +221,7 @@ static void pl110_update_display(void *opaque)
221
int last;
222
223
if (!pl110_enabled(s)) {
224
- return;
224
+ return true;
225
}
226
227
if (s->cr & PL110_CR_BGR)
@@ -306,6 +306,7 @@ static void pl110_update_display(void *opaque)
306
dpy_gfx_update(s->con, 0, first, s->cols, last - first + 1);
307
}
308
s->invalidate = 0;
309
+ return true;
310
}
311
312
static void pl110_invalidate_display(void * opaque)
hw/display/qxl-render.c
+3
-3
@@ -173,7 +173,7 @@ end:
173
* callbacks are called by spice_server thread, deferring to bh called from the
174
* io thread.
175
*/
176
-void qxl_render_update(PCIQXLDevice *qxl)
176
+bool qxl_render_update(PCIQXLDevice *qxl)
177
{
178
QXLCookie *cookie;
179
@@ -183,8 +183,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
183
qxl->mode == QXL_MODE_UNDEFINED) {
184
qxl_render_update_area_unlocked(qxl);
185
qemu_mutex_unlock(&qxl->ssd.lock);
186
- graphic_hw_update_done(qxl->ssd.dcl.con);
187
- return;
186
+ return true;
187
}
188
189
qxl->guest_primary.commands = 0;
@@ -195,6 +194,7 @@ void qxl_render_update(PCIQXLDevice *qxl)
194
qxl_set_rect_to_surface(qxl, &cookie->u.render.area);
195
qxl_spice_update_area(qxl, 0, &cookie->u.render.area, NULL,
196
0, 1 /* clear_dirty_region */, QXL_ASYNC, cookie);
197
+ return false;
198
}
199
200
void qxl_render_update_area_bh(void *opaque)
hw/display/qxl.c
+3
-4
@@ -122,7 +122,7 @@ static void qxl_reset_memslots(PCIQXLDevice *d);
122
static void qxl_reset_surfaces(PCIQXLDevice *d);
123
static void qxl_ring_set_dirty(PCIQXLDevice *qxl);
124
125
-static void qxl_hw_update(void *opaque);
125
+static bool qxl_hw_update(void *opaque);
126
127
void qxl_set_guest_bug(PCIQXLDevice *qxl, const char *msg, ...)
128
{
@@ -1144,7 +1144,6 @@ static const QXLInterface qxl_interface = {
1144
1145
static const GraphicHwOps qxl_ops = {
1146
.gfx_update = qxl_hw_update,
1147
- .gfx_update_async = true,
1147
};
1148
1149
static void qxl_enter_vga_mode(PCIQXLDevice *d)
@@ -1928,11 +1927,11 @@ static void qxl_send_events(PCIQXLDevice *d, uint32_t events)
1927
1928
/* graphics console */
1929
1931
-static void qxl_hw_update(void *opaque)
1930
+static bool qxl_hw_update(void *opaque)
1931
{
1932
PCIQXLDevice *qxl = opaque;
1933
1935
- qxl_render_update(qxl);
1934
+ return qxl_render_update(qxl);
1935
}
1936
1937
static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
hw/display/qxl.h
+1
-1
@@ -187,7 +187,7 @@ int qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
187
188
/* qxl-render.c */
189
void qxl_render_resize(PCIQXLDevice *qxl);
190
-void qxl_render_update(PCIQXLDevice *qxl);
190
+bool qxl_render_update(PCIQXLDevice *qxl);
191
int qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);
192
void qxl_render_update_area_done(PCIQXLDevice *qxl, QXLCookie *cookie);
193
void qxl_render_update_area_bh(void *opaque);
hw/display/ramfb-standalone.c
+3
-1
@@ -20,7 +20,7 @@ struct RAMFBStandaloneState {
20
bool use_legacy_x86_rom;
21
};
22
23
-static void display_update_wrapper(void *dev)
23
+static bool display_update_wrapper(void *dev)
24
{
25
RAMFBStandaloneState *ramfb = RAMFB(dev);
26
@@ -29,6 +29,8 @@ static void display_update_wrapper(void *dev)
29
} else {
30
ramfb_display_update(ramfb->con, ramfb->state);
31
}
32
+
33
+ return true;
34
}
35
36
static const GraphicHwOps wrapper_ops = {
hw/display/sm501.c
+5
-3
@@ -1716,7 +1716,7 @@ static void draw_hwc_line_32(uint8_t *d, const uint8_t *s, int width,
1716
}
1717
}
1718
1719
-static void sm501_update_display(void *opaque)
1719
+static bool sm501_update_display(void *opaque)
1720
{
1721
SM501State *s = opaque;
1722
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -1740,7 +1740,7 @@ static void sm501_update_display(void *opaque)
1740
1741
if (!((crt ? s->dc_crt_control : s->dc_panel_control)
1742
& SM501_DC_CRT_CONTROL_ENABLE)) {
1743
- return;
1743
+ return true;
1744
}
1745
1746
palette = (uint32_t *)(crt ? &s->dc_palette[SM501_DC_CRT_PALETTE -
@@ -1761,7 +1761,7 @@ static void sm501_update_display(void *opaque)
1761
default:
1762
qemu_log_mask(LOG_GUEST_ERROR, "sm501: update display"
1763
"invalid control register value.\n");
1764
- return;
1764
+ return true;
1765
}
1766
1767
/* set up to draw hardware cursor */
@@ -1833,6 +1833,8 @@ static void sm501_update_display(void *opaque)
1833
if (y_start >= 0) {
1834
dpy_gfx_update(s->con, 0, y_start, width, y - y_start);
1835
}
1836
+
1837
+ return true;
1838
}
1839
1840
static const GraphicHwOps sm501_ops = {
hw/display/ssd0303.c
+6
-4
@@ -203,7 +203,7 @@ static int ssd0303_event(I2CSlave *i2c, enum i2c_event event)
203
return 0;
204
}
205
206
-static void ssd0303_update_display(void *opaque)
206
+static bool ssd0303_update_display(void *opaque)
207
{
208
ssd0303_state *s = (ssd0303_state *)opaque;
209
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -218,11 +218,11 @@ static void ssd0303_update_display(void *opaque)
218
uint8_t mask;
219
220
if (!s->redraw)
221
- return;
221
+ return true;
222
223
switch (surface_bits_per_pixel(surface)) {
224
case 0:
225
- return;
225
+ return true;
226
case 15:
227
dest_width = 2;
228
break;
@@ -237,7 +237,7 @@ static void ssd0303_update_display(void *opaque)
237
break;
238
default:
239
BADF("Bad color depth\n");
240
- return;
240
+ return true;
241
}
242
dest_width *= MAGNIFY;
243
memset(colortab, 0xff, dest_width);
@@ -269,6 +269,8 @@ static void ssd0303_update_display(void *opaque)
269
}
270
s->redraw = 0;
271
dpy_gfx_update(s->con, 0, 0, 96 * MAGNIFY, 16 * MAGNIFY);
272
+
273
+ return true;
274
}
275
276
static void ssd0303_invalidate_display(void * opaque)
hw/display/ssd0323.c
+6
-5
@@ -181,7 +181,7 @@ static uint32_t ssd0323_transfer(SSIPeripheral *dev, uint32_t data)
181
return 0;
182
}
183
184
-static void ssd0323_update_display(void *opaque)
184
+static bool ssd0323_update_display(void *opaque)
185
{
186
ssd0323_state *s = (ssd0323_state *)opaque;
187
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -197,11 +197,11 @@ static void ssd0323_update_display(void *opaque)
197
int dest_width;
198
199
if (!s->redraw)
200
- return;
200
+ return true;
201
202
switch (surface_bits_per_pixel(surface)) {
203
case 0:
204
- return;
204
+ return true;
205
case 15:
206
dest_width = 2;
207
break;
@@ -216,7 +216,7 @@ static void ssd0323_update_display(void *opaque)
216
break;
217
default:
218
BADF("Bad color depth\n");
219
- return;
219
+ return true;
220
}
221
p = colortab;
222
for (i = 0; i < 16; i++) {
@@ -240,7 +240,7 @@ static void ssd0323_update_display(void *opaque)
240
break;
241
default:
242
BADF("Bad color depth\n");
243
- return;
243
+ return true;
244
}
245
p += dest_width;
246
}
@@ -271,6 +271,7 @@ static void ssd0323_update_display(void *opaque)
271
}
272
s->redraw = 0;
273
dpy_gfx_update(s->con, 0, 0, 128 * MAGNIFY, 64 * MAGNIFY);
274
+ return true;
275
}
276
277
static void ssd0323_invalidate_display(void * opaque)
hw/display/tcx.c
+4
-2
@@ -209,7 +209,7 @@ static inline void tcx24_draw_line32(TCXState *s1, uint8_t *d,
209
/* Fixed line length 1024 allows us to do nice tricks not possible on
210
VGA... */
211
212
-static void tcx_update_display(void *opaque)
212
+static bool tcx_update_display(void *opaque)
213
{
214
TCXState *ts = opaque;
215
DisplaySurface *surface = qemu_console_surface(ts->con);
@@ -257,9 +257,10 @@ static void tcx_update_display(void *opaque)
257
ts->width, y - y_start);
258
}
259
g_free(snap);
260
+ return true;
261
}
262
262
-static void tcx24_update_display(void *opaque)
263
+static bool tcx24_update_display(void *opaque)
264
{
265
TCXState *ts = opaque;
266
DisplaySurface *surface = qemu_console_surface(ts->con);
@@ -312,6 +313,7 @@ static void tcx24_update_display(void *opaque)
313
ts->width, y - y_start);
314
}
315
g_free(snap);
316
+ return true;
317
}
318
319
static void tcx_invalidate_display(void *opaque)
hw/display/vga.c
+3
-1
@@ -1783,7 +1783,7 @@ static void vga_draw_blank(VGACommonState *s, int full_update)
1783
#define GMODE_GRAPH 1
1784
#define GMODE_BLANK 2
1785
1786
-static void vga_update_display(void *opaque)
1786
+static bool vga_update_display(void *opaque)
1787
{
1788
VGACommonState *s = opaque;
1789
DisplaySurface *surface = qemu_console_surface(s->con);
@@ -1818,6 +1818,8 @@ static void vga_update_display(void *opaque)
1818
break;
1819
}
1820
}
1821
+
1822
+ return true;
1823
}
1824
1825
/* force a full display refresh */
hw/display/virtio-gpu-base.c
+2
-1
@@ -83,8 +83,9 @@ static void virtio_gpu_invalidate_display(void *opaque)
83
{
84
}
85
86
-static void virtio_gpu_update_display(void *opaque)
86
+static bool virtio_gpu_update_display(void *opaque)
87
{
88
+ return true;
89
}
90
91
static void virtio_gpu_text_update(void *opaque, console_ch_t *chardata)
hw/display/virtio-vga.c
+3
-3
@@ -19,15 +19,15 @@ static void virtio_vga_base_invalidate_display(void *opaque)
19
}
20
}
21
22
-static void virtio_vga_base_update_display(void *opaque)
22
+static bool virtio_vga_base_update_display(void *opaque)
23
{
24
VirtIOVGABase *vvga = opaque;
25
VirtIOGPUBase *g = vvga->vgpu;
26
27
if (g->enable) {
28
- g->hw_ops->gfx_update(g);
28
+ return g->hw_ops->gfx_update(g);
29
} else {
30
- vvga->vga.hw_ops->gfx_update(&vvga->vga);
30
+ return vvga->vga.hw_ops->gfx_update(&vvga->vga);
31
}
32
}
33
hw/display/vmware_vga.c
+4
-3
@@ -1135,14 +1135,13 @@ static inline void vmsvga_check_size(struct vmsvga_state_s *s)
1135
}
1136
}
1137
1138
-static void vmsvga_update_display(void *opaque)
1138
+static bool vmsvga_update_display(void *opaque)
1139
{
1140
struct vmsvga_state_s *s = opaque;
1141
1142
if (!s->enable || !s->config) {
1143
/* in standard vga mode */
1144
- s->vga.hw_ops->gfx_update(&s->vga);
1145
- return;
1144
+ return s->vga.hw_ops->gfx_update(&s->vga);
1145
}
1146
1147
vmsvga_check_size(s);
@@ -1154,6 +1153,8 @@ static void vmsvga_update_display(void *opaque)
1153
s->invalidated = 0;
1154
dpy_gfx_update_full(s->vga.con);
1155
}
1156
+
1157
+ return true;
1158
}
1159
1160
static void vmsvga_reset(DeviceState *dev)
hw/display/xenfb.c
+4
-2
@@ -709,14 +709,14 @@ static void xenfb_send_refresh_period(struct XenFB *xenfb, int period)
709
* Our screen might be inactive. When asked for
710
* an update we know it is active.
711
*/
712
-static void xenfb_update(void *opaque)
712
+static bool xenfb_update(void *opaque)
713
{
714
struct XenFB *xenfb = opaque;
715
DisplaySurface *surface;
716
int i;
717
718
if (xenfb->c.xendev.be_state != XenbusStateConnected)
719
- return;
719
+ return true;
720
721
if (!xenfb->feature_update) {
722
/* we don't get update notifications, thus use the
@@ -770,6 +770,8 @@ static void xenfb_update(void *opaque)
770
}
771
xenfb->up_count = 0;
772
xenfb->up_fullscreen = 0;
773
+
774
+ return true;
775
}
776
777
static void xenfb_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
hw/display/xlnx_dp.c
+6
-4
@@ -1252,12 +1252,12 @@ static inline void xlnx_dp_blend_surface(XlnxDPState *s)
1252
surface_height(s->g_plane.surface));
1253
}
1254
1255
-static void xlnx_dp_update_display(void *opaque)
1255
+static bool xlnx_dp_update_display(void *opaque)
1256
{
1257
XlnxDPState *s = XLNX_DP(opaque);
1258
1259
if ((s->core_registers[DP_TRANSMITTER_ENABLE] & 0x01) == 0) {
1260
- return;
1260
+ return true;
1261
}
1262
1263
xlnx_dpdma_trigger_vsync_irq(s->dpdma);
@@ -1272,14 +1272,14 @@ static void xlnx_dp_update_display(void *opaque)
1272
*/
1273
s->core_registers[DP_INT_STATUS] |= (1 << 21);
1274
xlnx_dp_update_irq(s);
1275
- return;
1275
+ return true;
1276
}
1277
1278
if (xlnx_dp_global_alpha_enabled(s)) {
1279
if (!xlnx_dpdma_start_operation(s->dpdma, 0, false)) {
1280
s->core_registers[DP_INT_STATUS] |= (1 << 21);
1281
xlnx_dp_update_irq(s);
1282
- return;
1282
+ return true;
1283
}
1284
xlnx_dp_blend_surface(s);
1285
}
@@ -1288,6 +1288,8 @@ static void xlnx_dp_update_display(void *opaque)
1288
* XXX: We might want to update only what changed.
1289
*/
1290
dpy_gfx_update_full(s->console);
1291
+
1292
+ return true;
1293
}
1294
1295
static const GraphicHwOps xlnx_dp_gfx_ops = {
hw/vfio/display.c
+10
-7
@@ -285,7 +285,7 @@ static void vfio_display_free_dmabufs(VFIOPCIDevice *vdev)
285
}
286
}
287
288
-static void vfio_display_dmabuf_update(void *opaque)
288
+static bool vfio_display_dmabuf_update(void *opaque)
289
{
290
VFIOPCIDevice *vdev = opaque;
291
VFIODisplay *dpy = vdev->dpy;
@@ -298,7 +298,7 @@ static void vfio_display_dmabuf_update(void *opaque)
298
if (dpy->ramfb) {
299
ramfb_display_update(dpy->con, dpy->ramfb);
300
}
301
- return;
301
+ return true;
302
}
303
304
width = qemu_dmabuf_get_width(primary->buf);
@@ -340,6 +340,8 @@ static void vfio_display_dmabuf_update(void *opaque)
340
if (free_bufs) {
341
vfio_display_free_dmabufs(vdev);
342
}
343
+
344
+ return true;
345
}
346
347
static int vfio_display_get_flags(void *opaque)
@@ -399,7 +401,7 @@ void vfio_display_reset(VFIOPCIDevice *vdev)
401
dpy_gfx_update_full(vdev->dpy->con);
402
}
403
402
-static void vfio_display_region_update(void *opaque)
404
+static bool vfio_display_region_update(void *opaque)
405
{
406
VFIOPCIDevice *vdev = opaque;
407
VFIODisplay *dpy = vdev->dpy;
@@ -414,18 +416,18 @@ static void vfio_display_region_update(void *opaque)
416
if (ret < 0) {
417
error_report("ioctl VFIO_DEVICE_QUERY_GFX_PLANE: %s",
418
strerror(errno));
417
- return;
419
+ return true;
420
}
421
if (!plane.drm_format || !plane.size) {
422
if (dpy->ramfb) {
423
ramfb_display_update(dpy->con, dpy->ramfb);
424
dpy->region.surface = NULL;
425
}
424
- return;
426
+ return true;
427
}
428
format = qemu_drm_format_to_pixman(plane.drm_format);
429
if (!format) {
428
- return;
430
+ return true;
431
}
432
433
if (dpy->region.buffer.size &&
@@ -476,11 +478,12 @@ static void vfio_display_region_update(void *opaque)
478
dpy_gfx_update(dpy->con, 0, 0,
479
surface_width(dpy->region.surface),
480
surface_height(dpy->region.surface));
479
- return;
481
+ return true;
482
483
err:
484
vfio_region_exit(&dpy->region.buffer);
485
vfio_region_finalize(&dpy->region.buffer);
486
+ return true;
487
}
488
489
static const GraphicHwOps vfio_display_region_ops = {
include/ui/console.h
+8
-3
@@ -368,9 +368,14 @@ enum {
368
typedef struct GraphicHwOps {
369
int (*get_flags)(void *opaque); /* optional, default 0 */
370
void (*invalidate)(void *opaque);
371
- void (*gfx_update)(void *opaque);
372
- bool gfx_update_async; /* if true, calls graphic_hw_update_done() */
373
- void (*text_update)(void *opaque, console_ch_t *text);
371
+ /*
372
+ * Returns true if the update is handled synchronously, false if deferred
373
+ * and graphic_hw_update_done() will be called when ready (to resume waiting
374
+ * tasks/coroutines).
375
+ * Optional.
376
+ */
377
+ bool (*gfx_update)(void *opaque);
378
+ void (*text_update)(void *opaque, uint32_t *text);
379
void (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
380
void (*gl_block)(void *opaque, bool block);
381
} GraphicHwOps;
ui/console.c
+1
-6
@@ -136,15 +136,10 @@ void graphic_hw_update_done(QemuConsole *con)
136
137
void graphic_hw_update(QemuConsole *con)
138
{
139
- bool async = false;
139
if (!con) {
140
return;
141
}
143
- if (con->hw_ops->gfx_update) {
144
- con->hw_ops->gfx_update(con->hw);
145
- async = con->hw_ops->gfx_update_async;
146
- }
147
- if (!async) {
142
+ if (!con->hw_ops->gfx_update || con->hw_ops->gfx_update(con->hw)) {
143
graphic_hw_update_done(con);
144
}
145
}