diff mbox series

[2/2] hw/display/vmware_vga: do not discard screen updates

Message ID 20220104091135.61226-3-carwynellis@gmail.com
State New
Headers show
Series hw/display/vmware_vga: supress debug output and fix | expand

Commit Message

Carwyn Ellis Jan. 4, 2022, 9:11 a.m. UTC
In certain circumstances, typically when there is lots changing on the
screen, updates will be discarded resulting in garbled output.

This change firstly increases the screen update FIFO size to ensure it's
large enough to accomodate all updates deferred in a given screen
refresh cycle.

When updating the screen all updates are applied to ensure the display
output is rendered correctly.

Signed-off-by: Carwyn Ellis <carwynellis@gmail.com>
---
 hw/display/vmware_vga.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

Comments

Gerd Hoffmann Jan. 4, 2022, 12:23 p.m. UTC | #1
Hi,

> This change firstly increases the screen update FIFO size to ensure it's
> large enough to accomodate all updates deferred in a given screen
> refresh cycle.

How do you know it's large enough?

> @@ -385,7 +385,14 @@ static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
>  {
>      struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++];
>  
> -    s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
> +    if (s->redraw_fifo_last >= REDRAW_FIFO_LEN) {
> +        VMWARE_VGA_DEBUG("%s: Discarding updates - FIFO length %d exceeded\n",
> +            "vmsvga_update_rect_delayed",
> +            REDRAW_FIFO_LEN

Hmm, apparently you don't know ;)

How about just calling vmsvga_update_rect_flush()
when the fifo is (almost) full?

Which guest do you use btw?  I'm kind-of surprised this is still being
used even though it hasn't seen any development (beside fixing a bug now
and then) for a decade or so and the feature gap to recent vmware is
huge ...

take care,
  Gerd
Carwyn Ellis Jan. 4, 2022, 1:17 p.m. UTC | #2
> On 4 Jan 2022, at 12:23, Gerd Hoffmann <kraxel@redhat.com> wrote:
> 
>  Hi,
> 
>> This change firstly increases the screen update FIFO size to ensure it's
>> large enough to accomodate all updates deferred in a given screen
>> refresh cycle.
> 
> How do you know it's large enough?
> 
>> @@ -385,7 +385,14 @@ static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
>> {
>>     struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++];
>> 
>> -    s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
>> +    if (s->redraw_fifo_last >= REDRAW_FIFO_LEN) {
>> +        VMWARE_VGA_DEBUG("%s: Discarding updates - FIFO length %d exceeded\n",
>> +            "vmsvga_update_rect_delayed",
>> +            REDRAW_FIFO_LEN
> 
> Hmm, apparently you don't know ;)
> 
> How about just calling vmsvga_update_rect_flush()
> when the fifo is (almost) full?

Yeah will give that a shot. Wasn’t sure how it’d play so did the simplest thing possible.

> 
> Which guest do you use btw?  I'm kind-of surprised this is still being
> used even though it hasn't seen any development (beside fixing a bug now
> and then) for a decade or so and the feature gap to recent vmware is
> huge ...
> 

This is an old vmware vm that rarely gets used. Figured I’d see if I could get it working over the holidays after making the move off an intel mac to m1, and noticed the issue with the output. In this case using the already configured vmware drivers was the least worst option.

> take care,
>  Gerd
> 

Cheers
Carwyn
diff mbox series

Patch

diff --git a/hw/display/vmware_vga.c b/hw/display/vmware_vga.c
index 8080e085d1..28556f39c6 100644
--- a/hw/display/vmware_vga.c
+++ b/hw/display/vmware_vga.c
@@ -82,7 +82,7 @@  struct vmsvga_state_s {
     uint32_t fifo_next;
     uint32_t fifo_stop;
 
-#define REDRAW_FIFO_LEN  512
+#define REDRAW_FIFO_LEN  8192
     struct vmsvga_rect_s {
         int x, y, w, h;
     } redraw_fifo[REDRAW_FIFO_LEN];
@@ -385,7 +385,14 @@  static inline void vmsvga_update_rect_delayed(struct vmsvga_state_s *s,
 {
     struct vmsvga_rect_s *rect = &s->redraw_fifo[s->redraw_fifo_last++];
 
-    s->redraw_fifo_last &= REDRAW_FIFO_LEN - 1;
+    if (s->redraw_fifo_last >= REDRAW_FIFO_LEN) {
+        VMWARE_VGA_DEBUG("%s: Discarding updates - FIFO length %d exceeded\n",
+            "vmsvga_update_rect_delayed",
+            REDRAW_FIFO_LEN
+        );
+        s->redraw_fifo_last = REDRAW_FIFO_LEN - 1;
+    }
+
     rect->x = x;
     rect->y = y;
     rect->w = w;
@@ -402,11 +409,13 @@  static inline void vmsvga_update_rect_flush(struct vmsvga_state_s *s)
     }
     /* 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_first = 0;
+    s->redraw_fifo_last = 0;
 }
 
 #ifdef HW_RECT_ACCEL
@@ -607,13 +616,14 @@  static inline uint32_t vmsvga_fifo_read(struct vmsvga_state_s *s)
 static void vmsvga_fifo_run(struct vmsvga_state_s *s)
 {
     uint32_t cmd, colour;
-    int args, len, maxloop = 1024;
+    int args, len = 1024;
     int x, y, dx, dy, width, height;
     struct vmsvga_cursor_definition_s cursor;
     uint32_t cmd_start;
 
     len = vmsvga_fifo_length(s);
-    while (len > 0 && --maxloop > 0) {
+
+    while (len > 0) {
         /* May need to go back to the start of the command if incomplete */
         cmd_start = s->fifo_stop;