summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <ssp@redhat.com>2010-10-24 20:28:11 -0400
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-01-26 08:12:19 -0500
commitffcfa53e0d8456d283bf2861fc72f94e08b9b37b (patch)
treead78dbc3dc115d67254479d0f2a40e2caed45cda
parent11d8429b82215a676219ed6c5515f02b61052c49 (diff)
Add qxl_surface_evacuates/replace_all() methods.
These functions will be used to migrate surfaces out of video memory when we have to reset the device.
-rw-r--r--src/qxl.h2
-rw-r--r--src/qxl_driver.c4
-rw-r--r--src/qxl_surface.c145
3 files changed, 103 insertions, 48 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 1f9e3f7..79a2d80 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -762,7 +762,7 @@ void qxl_ring_wait_idle (struct qxl_ring *ring);
/*
* Surface
*/
-void qxl_surface_init (qxl_screen_t *qxl, int n_surfaces);
+void qxl_surface_init (qxl_screen_t *qxl);
qxl_surface_t * qxl_surface_create_primary (qxl_screen_t *qxl,
struct qxl_mode *mode);
qxl_surface_t * qxl_surface_create (qxl_screen_t *qxl,
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index cb24921..e7a8c95 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -343,7 +343,7 @@ qxl_reset (qxl_screen_t *qxl)
ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
- qxl_surface_init (qxl, qxl->rom->n_surfaces);
+ qxl_surface_init (qxl);
/* Mem slots */
ErrorF ("slots start: %d, slots end: %d\n",
@@ -861,7 +861,7 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
sizeof (uint64_t),
8, 0);
- qxl_surface_init (qxl, qxl->rom->n_surfaces);
+ qxl_surface_init (qxl);
/* xf86DPMSInit(pScreen, xf86DPMSSet, 0); */
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 71fbebd..a7e53a7 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -30,6 +30,17 @@ struct qxl_surface_t
} u;
};
+typedef struct evacuated_surface_t evacuated_surface_t;
+
+struct evacuated_surface_t
+{
+ pixman_image_t *image;
+ PixmapPtr pixmap;
+ int Bpp;
+
+ evacuated_surface_t *next;
+};
+
#if 0
void
qxl_surface_free_all (qxl_screen_t *qxl)
@@ -46,10 +57,13 @@ qxl_surface_free_all (qxl_screen_t *qxl)
#endif
void
-qxl_surface_init (qxl_screen_t *qxl, int n_surfaces)
+qxl_surface_init (qxl_screen_t *qxl)
{
+ int n_surfaces;
int i;
+ n_surfaces = qxl->rom->n_surfaces;
+
if (!qxl->all_surfaces)
qxl->all_surfaces = calloc (n_surfaces, sizeof (qxl_surface_t));
else
@@ -480,6 +494,26 @@ qxl_surface_set_pixmap (qxl_surface_t *surface, PixmapPtr pixmap)
surface->pixmap = pixmap;
}
+static void
+free_surface_content (qxl_surface_t *surface)
+{
+ if (surface->dev_image)
+ pixman_image_unref (surface->dev_image);
+ if (surface->host_image)
+ pixman_image_unref (surface->host_image);
+
+ if (surface->prev)
+ surface->prev->next = surface->next;
+ else
+ surface->qxl->live_surfaces = surface->next;
+
+ if (surface->next)
+ surface->next->prev = surface->prev;
+
+ surface->prev = NULL;
+ surface->next = NULL;
+}
+
void
qxl_surface_destroy (qxl_surface_t *surface)
{
@@ -487,22 +521,6 @@ qxl_surface_destroy (qxl_surface_t *surface)
if (--surface->ref_count == 0)
{
- if (surface->dev_image)
- pixman_image_unref (surface->dev_image);
- if (surface->host_image)
- pixman_image_unref (surface->host_image);
-
- if (surface->prev)
- surface->prev->next = surface->next;
- else
- qxl->live_surfaces = surface->next;
-
- if (surface->next)
- surface->next->prev = surface->prev;
-
- surface->prev = NULL;
- surface->next = NULL;
-
if (surface->id != 0)
{
struct qxl_surface_cmd *cmd;
@@ -511,6 +529,8 @@ qxl_surface_destroy (qxl_surface_t *surface)
push_surface_cmd (qxl, cmd);
}
+
+ free_surface_content (surface);
}
}
@@ -546,18 +566,11 @@ qxl_surface_flush (qxl_surface_t *surface)
;
}
-
/* access */
static void
download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
{
struct qxl_ram_header *ram_header = get_ram_header (surface->qxl);
-
-#if 0
- ErrorF ("Downloading %d: %d %d %d %d %p\n", surface->id, x1, y1, x2 - x1, y2 - y1, surface->address);
-
- before = *((uint32_t *)surface->address - 1);
-#endif
ram_header->update_area.top = y1;
ram_header->update_area.bottom = y2;
@@ -568,27 +581,6 @@ download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
outb (surface->qxl->io_base + QXL_IO_UPDATE_AREA, 0);
-#if 0
- after = *((uint32_t *)surface->address - 1);
-#endif
-
-#if 0
- if (surface->id != 0 && before != after)
- abort();
-#endif
-
-#if 0
- uint32_t pix = 0xff8033ff;
-
- submit_fill (surface->qxl, surface->id, &qrect, pix);
-
- pixman_color_t p = { 0xd999, 0xa999, 0x3333, 0xffff };
- pixman_image_t *pink = pixman_image_create_solid_fill (&p);
-
- pixman_image_composite (PIXMAN_OP_SRC, pink, NULL, surface->host_image,
- 0, 0, 0, 0, x1, y1, x2 - x1, y2 - y1);
-#endif
-
pixman_image_composite (PIXMAN_OP_SRC,
surface->dev_image,
NULL,
@@ -679,6 +671,69 @@ qxl_surface_prepare_access (qxl_surface_t *surface,
return TRUE;
}
+void *
+qxl_surface_evacuate_all (qxl_screen_t *qxl)
+{
+ evacuated_surface_t *evacuated_surfaces = NULL;
+ qxl_surface_t *s;
+
+ for (s = qxl->live_surfaces; s != NULL; s = s->next)
+ {
+ evacuated_surface_t *evacuated = malloc (sizeof (evacuated_surface_t));
+ int width, height;
+
+ width = pixman_image_get_width (s->host_image);
+ height = pixman_image_get_height (s->host_image);
+
+ download_box (s, 0, 0, width, height);
+
+ evacuated->image = s->host_image;
+ evacuated->pixmap = s->pixmap;
+ evacuated->Bpp = s->Bpp;
+
+ s->host_image = NULL;
+
+ free_surface_content (s);
+
+ evacuated->next = evacuated_surfaces;
+ evacuated_surfaces = evacuated;
+ }
+
+ free (qxl->all_surfaces);
+ qxl->all_surfaces = NULL;
+ qxl->live_surfaces = NULL;
+ qxl->free_surfaces = NULL;
+
+ return evacuated_surfaces;
+}
+
+void
+qxl_surface_replace_all (qxl_screen_t *qxl, void *data)
+{
+ evacuated_surface_t *ev;
+
+ ev = data;
+ while (ev != NULL)
+ {
+ evacuated_surface_t *next = ev->next;
+ int width = pixman_image_get_width (ev->image);
+ int height = pixman_image_get_height (ev->image);
+ qxl_surface_t *surface;
+
+ surface = qxl_surface_create (qxl, width, height, ev->Bpp * 8);
+
+ set_surface (ev->pixmap, surface);
+
+ qxl_surface_set_pixmap (surface, ev->pixmap);
+
+ free (ev);
+
+ ev = next;
+ }
+
+ qxl_surface_init (qxl);
+}
+
static void
translate_rect (struct qxl_rect *rect)
{