summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann <ssp@redhat.com>2010-10-25 17:21:17 -0400
committerSøren Sandmann <ssp@redhat.com>2010-10-25 17:21:17 -0400
commitcbcb7f83abdd07d351e15b307c6e2a3e884fd505 (patch)
tree8e9dc5d068c02951b983df7c8cb2b7fd895102d8
parentfebd2f947558c725ef0571e530e7d1277ab907aa (diff)
Migrate pixmaps out of video memory before mode setting
After mode setting migrate them back in.
-rw-r--r--src/qxl.h9
-rw-r--r--src/qxl_driver.c35
-rw-r--r--src/qxl_surface.c205
3 files changed, 165 insertions, 84 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 79a2d80..d1f7190 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -769,6 +769,12 @@ qxl_surface_t * qxl_surface_create (qxl_screen_t *qxl,
int width,
int height,
int bpp);
+void
+qxl_surface_sanity_check (qxl_screen_t *qxl);
+void *
+qxl_surface_evacuate_all (qxl_screen_t *qxl);
+void
+qxl_surface_replace_all (qxl_screen_t *qxl, void *data);
void qxl_surface_set_pixmap (qxl_surface_t *surface,
PixmapPtr pixmap);
/* Call this to ask the device to destroy the surface */
@@ -821,6 +827,9 @@ static inline qxl_surface_t *get_surface (PixmapPtr pixmap)
static inline void set_surface (PixmapPtr pixmap, qxl_surface_t *surface)
{
+ if (surface == NULL)
+ ErrorF ("pixmap %p now has surface %p\n", pixmap, surface);
+
dixSetPrivate(&pixmap->devPrivates, &uxa_pixmap_index, surface);
}
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index e7a8c95..24d9e4b 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -361,7 +361,8 @@ qxl_reset (qxl_screen_t *qxl)
qxl->main_mem_slot = qxl->rom->slots_start;
slot = &qxl->mem_slots[qxl->main_mem_slot];
slot->start_phys_addr = (unsigned long)qxl->ram_physical;
- slot->end_phys_addr = (unsigned long)slot->start_phys_addr + (unsigned long)qxl->rom->num_pages * getpagesize();
+ slot->end_phys_addr =
+ (unsigned long)slot->start_phys_addr + (unsigned long)qxl->rom->num_pages * getpagesize();
slot->start_virt_addr = (uint64_t)(uintptr_t)qxl->ram;
slot->end_virt_addr = slot->start_virt_addr + (unsigned long)qxl->rom->num_pages * getpagesize();
@@ -429,6 +430,9 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
int mode_index = (int)(unsigned long)p->Private;
struct qxl_mode *m = qxl->modes + mode_index;
ScreenPtr pScreen;
+ void *evacuated;
+
+ evacuated = qxl_surface_evacuate_all (qxl);
if (qxl->primary)
qxl_surface_destroy (qxl->primary);
@@ -459,6 +463,8 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
if (qxl->surf_mem)
qxl_mem_free_all (qxl->surf_mem);
+ qxl_surface_replace_all (qxl, evacuated);
+
return TRUE;
}
@@ -651,6 +657,8 @@ qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
if (w > 32767 || h > 32767)
return NULL;
+ qxl_surface_sanity_check (qxl);
+
#if 0
ErrorF ("Create pixmap: %d %d @ %d (usage: %d)\n", w, h, depth, usage);
#endif
@@ -667,6 +675,7 @@ qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
-1, -1, -1,
NULL);
+ ErrorF ("Create pixmap %p with surface %p\n", pixmap, surface);
set_surface (pixmap, surface);
qxl_surface_set_pixmap (surface, pixmap);
@@ -679,7 +688,9 @@ qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
#endif
pixmap = fbCreatePixmap (screen, w, h, depth, usage);
- }
+
+ ErrorF ("Create pixmap %p without surface\n", pixmap);
+}
return pixmap;
}
@@ -687,12 +698,24 @@ qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
static Bool
qxl_destroy_pixmap (PixmapPtr pixmap)
{
- qxl_surface_t *surface;
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86Screens[screen->myNum];
+ qxl_screen_t *qxl = scrn->driverPrivate;
+ qxl_surface_t *surface = NULL;
- if (pixmap->refcnt == 1 && (surface = get_surface (pixmap)))
+ qxl_surface_sanity_check (qxl);
+
+ if (pixmap->refcnt == 1)
{
- qxl_surface_destroy (surface);
- set_surface (pixmap, NULL);
+ surface = get_surface (pixmap);
+
+ ErrorF ("- Destroy %p (had surface %p)\n", pixmap, surface);
+
+ if (surface)
+ {
+ qxl_surface_destroy (surface);
+ set_surface (pixmap, NULL);
+ }
}
fbDestroyPixmap (pixmap);
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index a7e53a7..f316e1c 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -1,5 +1,7 @@
#include "qxl.h"
+typedef struct evacuated_surface_t evacuated_surface_t;
+
struct qxl_surface_t
{
qxl_screen_t * qxl;
@@ -30,8 +32,6 @@ struct qxl_surface_t
} u;
};
-typedef struct evacuated_surface_t evacuated_surface_t;
-
struct evacuated_surface_t
{
pixman_image_t *image;
@@ -41,6 +41,25 @@ struct evacuated_surface_t
evacuated_surface_t *next;
};
+void
+qxl_surface_sanity_check (qxl_screen_t *qxl)
+{
+ qxl_surface_t *s;
+
+ for (s = qxl->live_surfaces; s != NULL; s = s->next)
+ {
+ PixmapPtr pixmap = s->pixmap;
+
+ if (! (get_surface (pixmap) == s) )
+ {
+ ErrorF ("Surface %p has pixmap %p, but pixmap %p has surface %p\n",
+ s, pixmap, pixmap, get_surface (pixmap));
+
+ assert (0);
+ }
+ }
+}
+
#if 0
void
qxl_surface_free_all (qxl_screen_t *qxl)
@@ -187,6 +206,8 @@ qxl_surface_create_primary (qxl_screen_t *qxl,
surface->host_image = host_image;
surface->qxl = qxl;
surface->Bpp = PIXMAN_FORMAT_BPP (format) / 8;
+ surface->next = NULL;
+ surface->prev = NULL;
#if 0
ErrorF ("primary %p\n", surface->address);
@@ -492,15 +513,21 @@ void
qxl_surface_set_pixmap (qxl_surface_t *surface, PixmapPtr pixmap)
{
surface->pixmap = pixmap;
+
+ assert (get_surface (pixmap) == surface);
+
+ ErrorF ("Surface %p now has pixmap %p\n", surface, pixmap);
}
static void
-free_surface_content (qxl_surface_t *surface)
+unlink_surface (qxl_surface_t *surface)
{
if (surface->dev_image)
pixman_image_unref (surface->dev_image);
if (surface->host_image)
pixman_image_unref (surface->host_image);
+
+ ErrorF ("Unlinking %p\n", surface);
if (surface->prev)
surface->prev->next = surface->next;
@@ -509,37 +536,37 @@ free_surface_content (qxl_surface_t *surface)
if (surface->next)
surface->next->prev = surface->prev;
+
+ surface->pixmap = NULL;
surface->prev = NULL;
surface->next = NULL;
}
void
-qxl_surface_destroy (qxl_surface_t *surface)
+qxl_surface_unref (qxl_screen_t *qxl, uint32_t id)
{
- qxl_screen_t *qxl = surface->qxl;
-
- if (--surface->ref_count == 0)
+ if (id != 0)
{
- if (surface->id != 0)
+ qxl_surface_t *surface = qxl->all_surfaces + id;
+
+ if (--surface->ref_count == 0)
{
struct qxl_surface_cmd *cmd;
-
+
cmd = make_surface_cmd (qxl, surface->id, QXL_SURFACE_CMD_DESTROY);
-
+
push_surface_cmd (qxl, cmd);
}
-
- free_surface_content (surface);
}
}
void
-qxl_surface_unref (qxl_screen_t *qxl, uint32_t id)
+qxl_surface_destroy (qxl_surface_t *surface)
{
- qxl_surface_t *surface = qxl->all_surfaces + id;
+ unlink_surface (surface);
- qxl_surface_destroy (surface);
+ qxl_surface_unref (surface->qxl, surface->id);
}
void
@@ -671,69 +698,6 @@ 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)
{
@@ -814,6 +778,91 @@ qxl_surface_finish_access (qxl_surface_t *surface, PixmapPtr pixmap)
pScreen->ModifyPixmapHeader(pixmap, w, h, -1, -1, 0, NULL);
}
+void *
+qxl_surface_evacuate_all (qxl_screen_t *qxl)
+{
+ evacuated_surface_t *evacuated_surfaces = NULL;
+ qxl_surface_t *s;
+
+ ErrorF ("Evacuating all\n");
+
+ s = qxl->live_surfaces;
+ while (s != NULL)
+ {
+ qxl_surface_t *next = 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;
+
+ assert (get_surface (evacuated->pixmap) == s);
+
+ ErrorF ("%d => %p\n", s->id, evacuated->pixmap);
+ evacuated->Bpp = s->Bpp;
+
+ s->host_image = NULL;
+
+ unlink_surface (s);
+
+ evacuated->next = evacuated_surfaces;
+ evacuated_surfaces = evacuated;
+
+ s = next;
+ }
+
+ 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;
+
+ ErrorF ("Replacing all\n");
+ qxl_surface_init (qxl);
+
+ 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);
+ ErrorF ("%d => %p\n", surface->id, ev->pixmap);
+
+ assert (surface->host_image);
+ assert (surface->dev_image);
+
+ pixman_image_unref (surface->host_image);
+ surface->host_image = ev->image;
+
+ upload_box (surface, 0, 0, width, height);
+
+ set_surface (ev->pixmap, surface);
+
+ qxl_surface_set_pixmap (surface, ev->pixmap);
+
+ free (ev);
+
+ ev = next;
+ }
+
+ qxl_surface_sanity_check (qxl);
+
+}
static void
print_region (const char *header, RegionPtr pRegion)