]> git.proxmox.com Git - qemu.git/blobdiff - hw/cirrus_vga.c
VNC server (Anthony Liguori)
[qemu.git] / hw / cirrus_vga.c
index 934cde99055d56eb5636c6ffb8eac0a584ada112..d186d797ac70888353b05a9930aec8de9ad2c6b4 100644 (file)
@@ -644,15 +644,90 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
                                             (s->cirrus_blt_srcaddr & ~7));
 }
 
-static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
+static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
 {
+    int sx, sy;
+    int dx, dy;
+    int width, height;
+    int depth;
+    int notify = 0;
+
+    depth = s->get_bpp((VGAState *)s) / 8;
+    s->get_resolution((VGAState *)s, &width, &height);
+
+    /* extra x, y */
+    sx = (src % (width * depth)) / depth;
+    sy = (src / (width * depth));
+    dx = (dst % (width *depth)) / depth;
+    dy = (dst / (width * depth));
+
+    /* normalize width */
+    w /= depth;
+
+    /* if we're doing a backward copy, we have to adjust
+       our x/y to be the upper left corner (instead of the lower
+       right corner) */
+    if (s->cirrus_blt_dstpitch < 0) {
+       sx -= (s->cirrus_blt_width / depth) - 1;
+       dx -= (s->cirrus_blt_width / depth) - 1;
+       sy -= s->cirrus_blt_height - 1;
+       dy -= s->cirrus_blt_height - 1;
+    }
+
+    /* are we in the visible portion of memory? */
+    if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
+       (sx + w) <= width && (sy + h) <= height &&
+       (dx + w) <= width && (dy + h) <= height) {
+       notify = 1;
+    }
+
+    /* make to sure only copy if it's a plain copy ROP */
+    if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
+       *s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
+       notify = 0;
+
+    /* we have to flush all pending changes so that the copy
+       is generated at the appropriate moment in time */
+    if (notify)
+       vga_hw_update();
+
     (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
                      s->vram_ptr + s->cirrus_blt_srcaddr,
                      s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
                      s->cirrus_blt_width, s->cirrus_blt_height);
-    cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
-                            s->cirrus_blt_dstpitch, s->cirrus_blt_width,
-                            s->cirrus_blt_height);
+
+    if (notify)
+       s->ds->dpy_copy(s->ds,
+                       sx, sy, dx, dy,
+                       s->cirrus_blt_width / depth,
+                       s->cirrus_blt_height);
+
+    /* we don't have to notify the display that this portion has
+       changed since dpy_copy implies this */
+
+    if (!notify)
+       cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+                                s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+                                s->cirrus_blt_height);
+}
+
+static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
+{
+    if (s->ds->dpy_copy) {
+       cirrus_do_copy(s, s->cirrus_blt_dstaddr - s->start_addr,
+                      s->cirrus_blt_srcaddr - s->start_addr,
+                      s->cirrus_blt_width, s->cirrus_blt_height);
+    } else {
+       (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
+                         s->vram_ptr + s->cirrus_blt_srcaddr,
+                         s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+                         s->cirrus_blt_width, s->cirrus_blt_height);
+
+       cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+                                s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+                                s->cirrus_blt_height);
+    }
+
     return 1;
 }