aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarwyn Ellis <carwynellis@gmail.com>2022-02-06 18:39:56 +0000
committerGerd Hoffmann <kraxel@redhat.com>2022-04-22 11:47:08 +0200
commit67ae04273736f103b31fb5d1f9e5170dfee3d64c (patch)
tree4e8e8da774366ec1a00881468d422d55bcdca4ab
parenta74782936dc6e979ce371dabda4b1c05624ea87f (diff)
hw/display/vmware_vga: do not discard screen updates
In certain circumstances, typically when there is lots changing on the screen, updates will be discarded resulting in garbled output. This change simplifies the traversal of the display update FIFO queue when applying updates. We just track the queue length and iterate up to the end of the queue. Additionally when adding updates to the queue, if the buffer reaches capacity we force a flush before accepting further events. Signed-off-by: Carwyn Ellis <carwynellis@gmail.com> Message-Id: <20220206183956.10694-3-carwynellis@gmail.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
-rw-r--r--hw/display/trace-events1
-rw-r--r--hw/display/vmware_vga.c41
2 files changed, 24 insertions, 18 deletions
diff --git a/hw/display/trace-events b/hw/display/trace-events
index 91efc88f04..0c0ffcbe42 100644
--- a/hw/display/trace-events
+++ b/hw/display/trace-events
@@ -24,6 +24,7 @@ vmware_setmode(uint32_t w, uint32_t h, uint32_t bpp) "%dx%d @ %d bpp"
vmware_verify_rect_less_than_zero(const char *name, const char *param, int x) "%s: %s was < 0 (%d)"
vmware_verify_rect_greater_than_bound(const char *name, const char *param, int bound, int x) "%s: %s was > %d (%d)"
vmware_verify_rect_surface_bound_exceeded(const char *name, const char *component, int bound, const char *param1, int value1, const char *param2, int value2) "%s: %s > %d (%s: %d, %s: %d)"
+vmware_update_rect_delayed_flush(void) "display update FIFO full - forcing flush"
# virtio-gpu-base.c
virtio_gpu_features(bool virgl) "virgl %d"
diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 45d06cbe25..cedbbde522 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -80,7 +80,7 @@ struct vmsvga_state_s {
struct vmsvga_rect_s {
int x, y, w, h;
} redraw_fifo[REDRAW_FIFO_LEN];
- int redraw_fifo_first, redraw_fifo_last;
+ int redraw_fifo_last;
};
#define TYPE_VMWARE_SVGA "vmware-svga"
@@ -380,33 +380,39 @@ static inline void vmsvga_update_rect(struct vmsvga_state_s *s,
dpy_gfx_update(s->vga.con, x, y, w, h);
}
-static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
- int x, int y, int w, int h)
-{
- struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++];
-
- s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
- rect->x = x;
- rect->y = y;
- rect->w = w;
- rect->h = h;
-}
-
static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
{
struct vmsvga_rect_s *rect;
if (s->invalidated) {
- s->redraw_fifo_first = s->redraw_fifo_last;
+ s->redraw_fifo_last = 0;
return;
}
/* Overlapping region updates can be optimised out here - if someone
* knows a smart algorithm to do that, please share. */
- while (s->redraw_fifo_first != s->redraw_fifo_last) {
- rect = &s->redraw_fifo[s->redraw_fifo_first++];
- s->redraw_fifo_first &= REDRAW_FIFO_LEN - 1;
+ for (int i = 0; i < s->redraw_fifo_last; i++) {
+ rect = &s->redraw_fifo[i];
vmsvga_update_rect(s, rect->x, rect->y, rect->w, rect->h);
}
+
+ s->redraw_fifo_last = 0;
+}
+
+static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
+ int x, int y, int w, int h)
+{
+
+ if (s->redraw_fifo_last >= REDRAW_FIFO_LEN) {
+ trace_vmware_update_rect_delayed_flush();
+ vmsvga_update_rect_flush(s);
+ }
+
+ struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++];
+
+ rect->x = x;
+ rect->y = y;
+ rect->w = w;
+ rect->h = h;
}
#ifdef HW_RECT_ACCEL
@@ -1161,7 +1167,6 @@ static void vmsvga_reset(DeviceState *dev)
s->config = 0;
s->svgaid = SVGA_ID;
s->cursor.on = 0;
- s->redraw_fifo_first = 0;
s->redraw_fifo_last = 0;
s->syncing = 0;