]> xenbits.xensource.com Git - qemu-xen-4.1-testing.git/commitdiff
xenfb: let xenfb_guest_copy() handle dept h=32 case
authorIan Jackson <ian.jackson@eu.citrix.com>
Tue, 14 Dec 2010 18:39:14 +0000 (18:39 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Tue, 14 Dec 2010 18:39:14 +0000 (18:39 +0000)
In hw/xenfb.c, xenfb_guest_copy only handles xenfb->depth=8 and 24
cases, I guess it assumes in xenfb->depth=16 or 32 cases, buffer is
shared. But that's not always the case: the code path that allows us
to have a shared buffer when xenfb->depth=16 or 32 is xenfb->do_resize
set, but on a guest vnc console, when enter CTRL+ALT+2 switch to qemu
monitor console then CTRL+ALT+1 back to guest window, the
xenfb->do_resize is not set, that is, buffer is not shared, and
xenfb_guest_copy does not handle xenfb->depth=32 case, the result is:
guest screen cannot be restored.

To fix above problem, this patch does two things:

1. Set xenfb->do_resize in xenfb_invalidate so that in console switch
case, buffer is shared when xenfb->depth=16 or 32. The screen cannot
be restored bug in above description can be solved.

2. To avoid that other special cases have the same problem, it's
better to let xenfb_guest_copy handle all cases, so add processing to
xenfb->depth=16 and 32 in xenfb_guest_copy.

Signed-off-by: Chun Yan Liu <cyliu@novell.com>
Acked-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
hw/xenfb.c

index 29a873f5fe9fba9b5f43f0801df58053de7f1a8a..05c51cc46c9cd6a380791014043a57142c79af7a 100644 (file)
@@ -630,6 +630,18 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
                 oops = 1;
             }
             break;
+    case 16:
+            if (bpp == 16) {
+                for (line = y; line < (y+h); line++) {
+                        memcpy (data + (line * linesize) + (x * bpp / 8), xenfb->pixels + xenfb->offset
+                              + (line * xenfb->row_stride) + (x * xenfb->depth / 8), w * xenfb->depth / 8);
+                }
+            } else if (bpp == 32) {
+                BLT(uint16_t, uint32_t,   5, 6, 5,   8, 8, 8);
+            } else {
+                oops = 1;
+            }
+            break;
         case 24:
             if (bpp == 16) {
                 BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
@@ -639,6 +651,18 @@ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h)
                 oops = 1;
             }
             break;
+        case 32:
+            if (bpp == 16) {
+                BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);
+            } else if (bpp == 32) {
+                for (line = y; line < (y+h); line++) {
+                        memcpy (data + (line * linesize) + (x * bpp / 8), xenfb->pixels + xenfb->offset
+                              + (line * xenfb->row_stride) + (x * xenfb->depth / 8), w * xenfb->depth / 8);
+                }
+            } else {
+                oops = 1;
+            }
+            break;
         default:
             oops = 1;
        }
@@ -792,6 +816,7 @@ static void xenfb_update(void *opaque)
 static void xenfb_invalidate(void *opaque)
 {
     struct XenFB *xenfb = opaque;
+    xenfb->do_resize = 1;
     xenfb->up_fullscreen = 1;
 }