Skip to content

Commit aeffd07

Browse files
akihikodakikraxel
authored andcommittedJun 14, 2022
ui: Deliver refresh rate via QemuUIInfo
This change adds a new member, refresh_rate to QemuUIInfo in include/ui/console.h. It represents the refresh rate of the physical display backend, and it is more appropriate than GUI update interval as the refresh rate which the emulated device reports: - sdl may set GUI update interval shorter than the refresh rate of the physical display to respond to user-generated events. - sdl and vnc aggressively changes GUI update interval, but a guests is typically not designed to respond to frequent refresh rate changes, or frequent "display mode" changes in general. The frequency of refresh rate changes of the physical display backend matches better to the guest's expectation. QemuUIInfo also has other members representing "display mode", which makes it suitable for refresh rate representation. It has a throttling of update notifications, and prevents frequent changes of the display mode. Signed-off-by: Akihiko Odaki <[email protected]> Message-Id: <[email protected]> Signed-off-by: Gerd Hoffmann <[email protected]>
1 parent 362239c commit aeffd07

File tree

7 files changed

+42
-34
lines changed

7 files changed

+42
-34
lines changed
 

‎hw/display/xenfb.c

+11-3
Original file line numberDiff line numberDiff line change
@@ -777,16 +777,24 @@ static void xenfb_update(void *opaque)
777777
xenfb->up_fullscreen = 0;
778778
}
779779

780-
static void xenfb_update_interval(void *opaque, uint64_t interval)
780+
static void xenfb_ui_info(void *opaque, uint32_t idx, QemuUIInfo *info)
781781
{
782782
struct XenFB *xenfb = opaque;
783+
uint32_t refresh_rate;
783784

784785
if (xenfb->feature_update) {
785786
#ifdef XENFB_TYPE_REFRESH_PERIOD
786787
if (xenfb_queue_full(xenfb)) {
787788
return;
788789
}
789-
xenfb_send_refresh_period(xenfb, interval);
790+
791+
refresh_rate = info->refresh_rate;
792+
if (!refresh_rate) {
793+
refresh_rate = 75;
794+
}
795+
796+
/* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
797+
xenfb_send_refresh_period(xenfb, 1000 * 1000 / refresh_rate);
790798
#endif
791799
}
792800
}
@@ -983,5 +991,5 @@ struct XenDevOps xen_framebuffer_ops = {
983991
static const GraphicHwOps xenfb_ops = {
984992
.invalidate = xenfb_invalidate,
985993
.gfx_update = xenfb_update,
986-
.update_interval = xenfb_update_interval,
994+
.ui_info = xenfb_ui_info,
987995
};

‎include/ui/console.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ typedef struct QemuUIInfo {
139139
int yoff;
140140
uint32_t width;
141141
uint32_t height;
142+
uint32_t refresh_rate;
142143
} QemuUIInfo;
143144

144145
/* cursor data format is 32bit RGBA */
@@ -431,7 +432,6 @@ typedef struct GraphicHwOps {
431432
void (*gfx_update)(void *opaque);
432433
bool gfx_update_async; /* if true, calls graphic_hw_update_done() */
433434
void (*text_update)(void *opaque, console_ch_t *text);
434-
void (*update_interval)(void *opaque, uint64_t interval);
435435
void (*ui_info)(void *opaque, uint32_t head, QemuUIInfo *info);
436436
void (*gl_block)(void *opaque, bool block);
437437
} GraphicHwOps;

‎include/ui/gtk.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ extern bool gtk_use_gl_area;
155155

156156
/* ui/gtk.c */
157157
void gd_update_windowsize(VirtualConsole *vc);
158-
int gd_monitor_update_interval(GtkWidget *widget);
158+
void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget);
159159
void gd_hw_gl_flushed(void *vc);
160160

161161
/* ui/gtk-egl.c */

‎ui/console.c

-6
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,6 @@ static void gui_update(void *opaque)
160160
uint64_t dcl_interval;
161161
DisplayState *ds = opaque;
162162
DisplayChangeListener *dcl;
163-
QemuConsole *con;
164163

165164
ds->refreshing = true;
166165
dpy_refresh(ds);
@@ -175,11 +174,6 @@ static void gui_update(void *opaque)
175174
}
176175
if (ds->update_interval != interval) {
177176
ds->update_interval = interval;
178-
QTAILQ_FOREACH(con, &consoles, next) {
179-
if (con->hw_ops->update_interval) {
180-
con->hw_ops->update_interval(con->hw, interval);
181-
}
182-
}
183177
trace_console_refresh(interval);
184178
}
185179
ds->last_update = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);

‎ui/gtk-egl.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
140140
{
141141
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
142142

143-
vc->gfx.dcl.update_interval = gd_monitor_update_interval(
144-
vc->window ? vc->window : vc->gfx.drawing_area);
143+
gd_update_monitor_refresh_rate(
144+
vc, vc->window ? vc->window : vc->gfx.drawing_area);
145145

146146
if (!vc->gfx.esurface) {
147147
gd_egl_init(vc);

‎ui/gtk-gl-area.c

+1-2
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,7 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
121121
{
122122
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
123123

124-
vc->gfx.dcl.update_interval = gd_monitor_update_interval(
125-
vc->window ? vc->window : vc->gfx.drawing_area);
124+
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area);
126125

127126
if (!vc->gfx.gls) {
128127
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {

‎ui/gtk.c

+26-19
Original file line numberDiff line numberDiff line change
@@ -710,11 +710,20 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
710710
return TRUE;
711711
}
712712

713-
static void gd_set_ui_info(VirtualConsole *vc, gint width, gint height)
713+
static void gd_set_ui_refresh_rate(VirtualConsole *vc, int refresh_rate)
714714
{
715715
QemuUIInfo info;
716716

717-
memset(&info, 0, sizeof(info));
717+
info = *dpy_get_ui_info(vc->gfx.dcl.con);
718+
info.refresh_rate = refresh_rate;
719+
dpy_set_ui_info(vc->gfx.dcl.con, &info, true);
720+
}
721+
722+
static void gd_set_ui_size(VirtualConsole *vc, gint width, gint height)
723+
{
724+
QemuUIInfo info;
725+
726+
info = *dpy_get_ui_info(vc->gfx.dcl.con);
718727
info.width = width;
719728
info.height = height;
720729
dpy_set_ui_info(vc->gfx.dcl.con, &info, true);
@@ -738,33 +747,32 @@ static void gd_resize_event(GtkGLArea *area,
738747
{
739748
VirtualConsole *vc = (void *)opaque;
740749

741-
gd_set_ui_info(vc, width, height);
750+
gd_set_ui_size(vc, width, height);
742751
}
743752

744753
#endif
745754

746-
/*
747-
* If available, return the update interval of the monitor in ms,
748-
* else return 0 (the default update interval).
749-
*/
750-
int gd_monitor_update_interval(GtkWidget *widget)
755+
void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget)
751756
{
752757
#ifdef GDK_VERSION_3_22
753758
GdkWindow *win = gtk_widget_get_window(widget);
759+
int refresh_rate;
754760

755761
if (win) {
756762
GdkDisplay *dpy = gtk_widget_get_display(widget);
757763
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
758-
int refresh_rate = gdk_monitor_get_refresh_rate(monitor); /* [mHz] */
759-
760-
if (refresh_rate) {
761-
/* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
762-
return MIN(1000 * 1000 / refresh_rate,
763-
GUI_REFRESH_INTERVAL_DEFAULT);
764-
}
764+
refresh_rate = gdk_monitor_get_refresh_rate(monitor); /* [mHz] */
765+
} else {
766+
refresh_rate = 0;
765767
}
768+
769+
gd_set_ui_refresh_rate(vc, refresh_rate);
770+
771+
/* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
772+
vc->gfx.dcl.update_interval = refresh_rate ?
773+
MIN(1000 * 1000 / refresh_rate, GUI_REFRESH_INTERVAL_DEFAULT) :
774+
GUI_REFRESH_INTERVAL_DEFAULT;
766775
#endif
767-
return 0;
768776
}
769777

770778
static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
@@ -801,8 +809,7 @@ static gboolean gd_draw_event(GtkWidget *widget, cairo_t *cr, void *opaque)
801809
return FALSE;
802810
}
803811

804-
vc->gfx.dcl.update_interval =
805-
gd_monitor_update_interval(vc->window ? vc->window : s->window);
812+
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : s->window);
806813

807814
fbw = surface_width(vc->gfx.ds);
808815
fbh = surface_height(vc->gfx.ds);
@@ -1691,7 +1698,7 @@ static gboolean gd_configure(GtkWidget *widget,
16911698
{
16921699
VirtualConsole *vc = opaque;
16931700

1694-
gd_set_ui_info(vc, cfg->width, cfg->height);
1701+
gd_set_ui_size(vc, cfg->width, cfg->height);
16951702
return FALSE;
16961703
}
16971704

0 commit comments

Comments
 (0)
Please sign in to comment.