mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 09:43:56 -06:00
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 <akihiko.odaki@gmail.com> Message-Id: <20220226115516.59830-3-akihiko.odaki@gmail.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
362239c05f
commit
aeffd071ed
7 changed files with 42 additions and 34 deletions
|
@ -160,7 +160,6 @@ static void gui_update(void *opaque)
|
|||
uint64_t dcl_interval;
|
||||
DisplayState *ds = opaque;
|
||||
DisplayChangeListener *dcl;
|
||||
QemuConsole *con;
|
||||
|
||||
ds->refreshing = true;
|
||||
dpy_refresh(ds);
|
||||
|
@ -175,11 +174,6 @@ static void gui_update(void *opaque)
|
|||
}
|
||||
if (ds->update_interval != interval) {
|
||||
ds->update_interval = interval;
|
||||
QTAILQ_FOREACH(con, &consoles, next) {
|
||||
if (con->hw_ops->update_interval) {
|
||||
con->hw_ops->update_interval(con->hw, interval);
|
||||
}
|
||||
}
|
||||
trace_console_refresh(interval);
|
||||
}
|
||||
ds->last_update = qemu_clock_get_ms(QEMU_CLOCK_REALTIME);
|
||||
|
|
|
@ -140,8 +140,8 @@ void gd_egl_refresh(DisplayChangeListener *dcl)
|
|||
{
|
||||
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
|
||||
|
||||
vc->gfx.dcl.update_interval = gd_monitor_update_interval(
|
||||
vc->window ? vc->window : vc->gfx.drawing_area);
|
||||
gd_update_monitor_refresh_rate(
|
||||
vc, vc->window ? vc->window : vc->gfx.drawing_area);
|
||||
|
||||
if (!vc->gfx.esurface) {
|
||||
gd_egl_init(vc);
|
||||
|
|
|
@ -121,8 +121,7 @@ void gd_gl_area_refresh(DisplayChangeListener *dcl)
|
|||
{
|
||||
VirtualConsole *vc = container_of(dcl, VirtualConsole, gfx.dcl);
|
||||
|
||||
vc->gfx.dcl.update_interval = gd_monitor_update_interval(
|
||||
vc->window ? vc->window : vc->gfx.drawing_area);
|
||||
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : vc->gfx.drawing_area);
|
||||
|
||||
if (!vc->gfx.gls) {
|
||||
if (!gtk_widget_get_realized(vc->gfx.drawing_area)) {
|
||||
|
|
45
ui/gtk.c
45
ui/gtk.c
|
@ -710,11 +710,20 @@ static gboolean gd_window_close(GtkWidget *widget, GdkEvent *event,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static void gd_set_ui_info(VirtualConsole *vc, gint width, gint height)
|
||||
static void gd_set_ui_refresh_rate(VirtualConsole *vc, int refresh_rate)
|
||||
{
|
||||
QemuUIInfo info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info = *dpy_get_ui_info(vc->gfx.dcl.con);
|
||||
info.refresh_rate = refresh_rate;
|
||||
dpy_set_ui_info(vc->gfx.dcl.con, &info, true);
|
||||
}
|
||||
|
||||
static void gd_set_ui_size(VirtualConsole *vc, gint width, gint height)
|
||||
{
|
||||
QemuUIInfo info;
|
||||
|
||||
info = *dpy_get_ui_info(vc->gfx.dcl.con);
|
||||
info.width = width;
|
||||
info.height = height;
|
||||
dpy_set_ui_info(vc->gfx.dcl.con, &info, true);
|
||||
|
@ -738,33 +747,32 @@ static void gd_resize_event(GtkGLArea *area,
|
|||
{
|
||||
VirtualConsole *vc = (void *)opaque;
|
||||
|
||||
gd_set_ui_info(vc, width, height);
|
||||
gd_set_ui_size(vc, width, height);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If available, return the update interval of the monitor in ms,
|
||||
* else return 0 (the default update interval).
|
||||
*/
|
||||
int gd_monitor_update_interval(GtkWidget *widget)
|
||||
void gd_update_monitor_refresh_rate(VirtualConsole *vc, GtkWidget *widget)
|
||||
{
|
||||
#ifdef GDK_VERSION_3_22
|
||||
GdkWindow *win = gtk_widget_get_window(widget);
|
||||
int refresh_rate;
|
||||
|
||||
if (win) {
|
||||
GdkDisplay *dpy = gtk_widget_get_display(widget);
|
||||
GdkMonitor *monitor = gdk_display_get_monitor_at_window(dpy, win);
|
||||
int refresh_rate = gdk_monitor_get_refresh_rate(monitor); /* [mHz] */
|
||||
|
||||
if (refresh_rate) {
|
||||
/* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
|
||||
return MIN(1000 * 1000 / refresh_rate,
|
||||
GUI_REFRESH_INTERVAL_DEFAULT);
|
||||
}
|
||||
refresh_rate = gdk_monitor_get_refresh_rate(monitor); /* [mHz] */
|
||||
} else {
|
||||
refresh_rate = 0;
|
||||
}
|
||||
|
||||
gd_set_ui_refresh_rate(vc, refresh_rate);
|
||||
|
||||
/* T = 1 / f = 1 [s*Hz] / f = 1000*1000 [ms*mHz] / f */
|
||||
vc->gfx.dcl.update_interval = refresh_rate ?
|
||||
MIN(1000 * 1000 / refresh_rate, GUI_REFRESH_INTERVAL_DEFAULT) :
|
||||
GUI_REFRESH_INTERVAL_DEFAULT;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
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)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
vc->gfx.dcl.update_interval =
|
||||
gd_monitor_update_interval(vc->window ? vc->window : s->window);
|
||||
gd_update_monitor_refresh_rate(vc, vc->window ? vc->window : s->window);
|
||||
|
||||
fbw = surface_width(vc->gfx.ds);
|
||||
fbh = surface_height(vc->gfx.ds);
|
||||
|
@ -1691,7 +1698,7 @@ static gboolean gd_configure(GtkWidget *widget,
|
|||
{
|
||||
VirtualConsole *vc = opaque;
|
||||
|
||||
gd_set_ui_info(vc, cfg->width, cfg->height);
|
||||
gd_set_ui_size(vc, cfg->width, cfg->height);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue