diff options
author | Søren Sandmann <ssp@redhat.com> | 2010-10-25 17:21:17 -0400 |
---|---|---|
committer | Søren Sandmann <ssp@redhat.com> | 2010-10-25 17:21:17 -0400 |
commit | cbcb7f83abdd07d351e15b307c6e2a3e884fd505 (patch) | |
tree | 8e9dc5d068c02951b983df7c8cb2b7fd895102d8 | |
parent | febd2f947558c725ef0571e530e7d1277ab907aa (diff) |
Migrate pixmaps out of video memory before mode setting
After mode setting migrate them back in.
-rw-r--r-- | src/qxl.h | 9 | ||||
-rw-r--r-- | src/qxl_driver.c | 35 | ||||
-rw-r--r-- | src/qxl_surface.c | 205 |
3 files changed, 165 insertions, 84 deletions
@@ -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) |