Skip to content

Instantly share code, notes, and snippets.

@Saren-Arterius
Last active March 25, 2019 13:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Saren-Arterius/b31df23d5c359523f1ef430d27b0e834 to your computer and use it in GitHub Desktop.
Save Saren-Arterius/b31df23d5c359523f1ef430d27b0e834 to your computer and use it in GitHub Desktop.
Fail
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 9087db5dee..f58af5251a 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1183,6 +1183,10 @@ static const GraphicHwOps qxl_ops = {
.gfx_update = qxl_hw_update,
};
+static unsigned long ref_time = 0;
+static unsigned long next_ref_time = 0;
+static unsigned long frame = 0;
+
static void qxl_enter_vga_mode(PCIQXLDevice *d)
{
if (d->mode == QXL_MODE_VGA) {
@@ -1193,7 +1197,7 @@ static void qxl_enter_vga_mode(PCIQXLDevice *d)
spice_qxl_driver_unload(&d->ssd.qxl);
#endif
graphic_console_set_hwops(d->ssd.dcl.con, d->vga.hw_ops, &d->vga);
- update_displaychangelistener(&d->ssd.dcl, GUI_REFRESH_INTERVAL_DEFAULT);
+ update_displaychangelistener(&d->ssd.dcl, next_gui_refresh_interval(&frame, &ref_time, &next_ref_time));
qemu_spice_create_host_primary(&d->ssd);
d->mode = QXL_MODE_VGA;
qemu_spice_display_switch(&d->ssd, d->ssd.ds);
diff --git a/include/ui/console.h b/include/ui/console.h
index c17803c530..cd5ebd38f6 100644
--- a/include/ui/console.h
+++ b/include/ui/console.h
@@ -8,6 +8,7 @@
#include "qapi/qapi-types-ui.h"
#ifdef CONFIG_OPENGL
+#include <sys/time.h>
# include <epoxy/gl.h>
# include "ui/shader.h"
#endif
@@ -27,6 +28,7 @@
/* in ms */
#define GUI_REFRESH_INTERVAL_DEFAULT 30
+#define GUI_REFRESH_DESIRED_FPS 60
#define GUI_REFRESH_INTERVAL_IDLE 3000
/* Color number is match to standard vga palette */
@@ -373,6 +375,37 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
*dest = ch;
}
+
+static inline unsigned next_gui_refresh_interval(unsigned long *frame, unsigned long *ref_time, unsigned long *next_ref_time)
+{
+ struct timeval current_time;
+ gettimeofday(&current_time, NULL);
+ unsigned long system_us = (current_time.tv_sec * (int)1e6) + current_time.tv_usec;
+ if (*frame == 0) {
+ *ref_time = system_us - (1e6);
+ *next_ref_time = system_us;
+ *frame = GUI_REFRESH_DESIRED_FPS;
+ }
+ (*frame)++;
+ if (*frame == GUI_REFRESH_DESIRED_FPS * 2) {
+ *frame = GUI_REFRESH_DESIRED_FPS;
+ *ref_time = *next_ref_time;
+ *next_ref_time = system_us;
+ }
+ long diff = system_us - *ref_time;
+ long dpf = diff / *frame;
+ long desired_us = (1e6 / GUI_REFRESH_DESIRED_FPS);
+ long ms;
+ long low = 1000 / GUI_REFRESH_DESIRED_FPS;
+ if (dpf <= desired_us) {
+ ms = low + 1;
+ } else {
+ ms = low;
+ }
+ // printf("%lu %lu %lu %lu %lu %lu\n", *frame, *ref_time, *next_ref_time, diff, dpf, ms);
+ return ms;
+}
+
typedef struct GraphicHwOps {
void (*invalidate)(void *opaque);
void (*gfx_update)(void *opaque);
diff --git a/ui/console.c b/ui/console.c
index 3a285bae00..f950af6efb 100644
--- a/ui/console.c
+++ b/ui/console.c
@@ -193,6 +193,10 @@ static DisplayState *get_alloc_displaystate(void);
static void text_console_update_cursor_timer(void);
static void text_console_update_cursor(void *opaque);
+static unsigned long ref_time = 0;
+static unsigned long next_ref_time = 0;
+static unsigned long frame = 0;
+
static void gui_update(void *opaque)
{
uint64_t interval = GUI_REFRESH_INTERVAL_IDLE;
@@ -205,9 +209,10 @@ static void gui_update(void *opaque)
dpy_refresh(ds);
ds->refreshing = false;
+ uint64_t ngfi = next_gui_refresh_interval(&frame, &ref_time, &next_ref_time);
QLIST_FOREACH(dcl, &ds->listeners, next) {
dcl_interval = dcl->update_interval ?
- dcl->update_interval : GUI_REFRESH_INTERVAL_DEFAULT;
+ dcl->update_interval : ngfi;
if (interval > dcl_interval) {
interval = dcl_interval;
}
diff --git a/ui/sdl.c b/ui/sdl.c
index 190b16f575..3bd3d1f0b7 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -744,6 +744,9 @@ static void handle_mousebutton(SDL_Event *ev)
sdl_send_mouse_event(0, 0, bev->x, bev->y, buttonstate);
}
}
+static unsigned long ref_time1 = 0;
+static unsigned long next_ref_time1 = 0;
+static unsigned long frame1 = 0;
static void handle_activation(SDL_Event *ev)
{
@@ -762,7 +765,7 @@ static void handle_activation(SDL_Event *ev)
if (ev->active.state & SDL_APPACTIVE) {
if (ev->active.gain) {
/* Back to default interval */
- update_displaychangelistener(dcl, GUI_REFRESH_INTERVAL_DEFAULT);
+ update_displaychangelistener(dcl, next_gui_refresh_interval(&frame1, &ref_time1, &next_ref_time1));
} else {
/* Sleeping interval. Not using the long default here as
* sdl_refresh does not only update the guest screen, but
@@ -772,6 +775,10 @@ static void handle_activation(SDL_Event *ev)
}
}
+static unsigned long ref_time2 = 0;
+static unsigned long next_ref_time2 = 0;
+static unsigned long frame2 = 0;
+
static void sdl_refresh(DisplayChangeListener *dcl)
{
SDL_Event ev1, *ev = &ev1;
@@ -834,7 +841,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
if (idle_counter < SDL_MAX_IDLE_COUNT) {
idle_counter++;
if (idle_counter >= SDL_MAX_IDLE_COUNT) {
- dcl->update_interval = GUI_REFRESH_INTERVAL_DEFAULT;
+ dcl->update_interval = next_gui_refresh_interval(&frame2, &ref_time2, &next_ref_time2);
}
}
} else {
diff --git a/ui/sdl2.c b/ui/sdl2.c
index a10b6e3a08..738dab0b21 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -514,6 +514,10 @@ static void handle_mousewheel(SDL_Event *ev)
qemu_input_event_sync();
}
+static unsigned long ref_time1 = 0;
+static unsigned long next_ref_time1 = 0;
+static unsigned long frame1 = 0;
+
static void handle_windowevent(SDL_Event *ev)
{
struct sdl2_console *scon = get_scon_from_window(ev->window.windowID);
@@ -557,7 +561,7 @@ static void handle_windowevent(SDL_Event *ev)
}
break;
case SDL_WINDOWEVENT_RESTORED:
- update_displaychangelistener(&scon->dcl, GUI_REFRESH_INTERVAL_DEFAULT);
+ update_displaychangelistener(&scon->dcl, next_gui_refresh_interval(&frame1, &ref_time1, &next_ref_time1));
break;
case SDL_WINDOWEVENT_MINIMIZED:
update_displaychangelistener(&scon->dcl, 500);
@@ -585,6 +589,10 @@ static void handle_windowevent(SDL_Event *ev)
}
}
+static unsigned long ref_time2 = 0;
+static unsigned long next_ref_time2 = 0;
+static unsigned long frame2 = 0;
+
void sdl2_poll_events(struct sdl2_console *scon)
{
SDL_Event ev1, *ev = &ev1;
@@ -644,7 +652,7 @@ void sdl2_poll_events(struct sdl2_console *scon)
if (scon->idle_counter < SDL2_MAX_IDLE_COUNT) {
scon->idle_counter++;
if (scon->idle_counter >= SDL2_MAX_IDLE_COUNT) {
- scon->dcl.update_interval = GUI_REFRESH_INTERVAL_DEFAULT;
+ scon->dcl.update_interval = next_gui_refresh_interval(&frame2, &ref_time2, &next_ref_time2);
}
}
} else {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment