aboutsummaryrefslogtreecommitdiff
path: root/hw/display/qxl.c
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2016-06-22 14:07:24 +0200
committerGerd Hoffmann <kraxel@redhat.com>2016-07-06 10:31:11 +0200
commit1331eab216c9dc4e50a48a34d14926b31a7fd611 (patch)
tree53053847b57470993293d24db0e058d23f6e17f9 /hw/display/qxl.c
parent3cb5158f15604a9f50287f2f06777d5835ff4c15 (diff)
qxl: fix surface migration
Create a helper function qxl_dirty_one_surface() to mark a single qxl surface as dirty. Use the new qxl_get_check_slot_offset function and lookup the memory region from the slot instead of assuming the surface is stored in vram. Use the new helper function in qxl_dirty_surfaces, for both primary and off-screen surfaces. For off-screen surfaces this is no functional change. For primary surfaces this will dirty only the memory actually used instead of the whole surface0 region. It will also work correctly in case the guest places the primary surface in vram instead of the surface0 region (linux kms driver does that). https://bugzilla.redhat.com/show_bug.cgi?id=1235732 Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> Message-id: 1466597244-5938-3-git-send-email-kraxel@redhat.com
Diffstat (limited to 'hw/display/qxl.c')
-rw-r--r--hw/display/qxl.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/hw/display/qxl.c b/hw/display/qxl.c
index 8101f698a1..65a3653898 100644
--- a/hw/display/qxl.c
+++ b/hw/display/qxl.c
@@ -1809,9 +1809,23 @@ static void qxl_hw_update(void *opaque)
qxl_render_update(qxl);
}
+static void qxl_dirty_one_surface(PCIQXLDevice *qxl, QXLPHYSICAL pqxl,
+ uint32_t height, int32_t stride)
+{
+ uint64_t offset;
+ uint32_t slot, size;
+ bool rc;
+
+ rc = qxl_get_check_slot_offset(qxl, pqxl, &slot, &offset);
+ assert(rc == true);
+ size = height * abs(stride);
+ trace_qxl_surfaces_dirty(qxl->id, (int)offset, size);
+ qxl_set_dirty(qxl->guest_slots[slot].mr,
+ qxl->guest_slots[slot].offset + offset, size);
+}
+
static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
{
- uintptr_t vram_start;
int i;
if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
@@ -1819,16 +1833,13 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
}
/* dirty the primary surface */
- qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
- qxl->shadow_rom.surface0_area_size);
-
- vram_start = (uintptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
+ qxl_dirty_one_surface(qxl, qxl->guest_primary.surface.mem,
+ qxl->guest_primary.surface.height,
+ qxl->guest_primary.surface.stride);
/* dirty the off-screen surfaces */
for (i = 0; i < qxl->ssd.num_surfaces; i++) {
QXLSurfaceCmd *cmd;
- intptr_t surface_offset;
- int surface_size;
if (qxl->guest_surfaces.cmds[i] == 0) {
continue;
@@ -1838,15 +1849,9 @@ static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
MEMSLOT_GROUP_GUEST);
assert(cmd);
assert(cmd->type == QXL_SURFACE_CMD_CREATE);
- surface_offset = (intptr_t)qxl_phys2virt(qxl,
- cmd->u.surface_create.data,
- MEMSLOT_GROUP_GUEST);
- assert(surface_offset);
- surface_offset -= vram_start;
- surface_size = cmd->u.surface_create.height *
- abs(cmd->u.surface_create.stride);
- trace_qxl_surfaces_dirty(qxl->id, i, (int)surface_offset, surface_size);
- qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
+ qxl_dirty_one_surface(qxl, cmd->u.surface_create.data,
+ cmd->u.surface_create.height,
+ cmd->u.surface_create.stride);
}
}