Last active
March 25, 2019 13:30
-
-
Save Saren-Arterius/b31df23d5c359523f1ef430d27b0e834 to your computer and use it in GitHub Desktop.
Fail
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(¤t_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