Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright 2010 Red Hat, Inc.
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * on the rights to use, copy, modify, merge, publish, distribute, sub
      8  * license, and/or sell copies of the Software, and to permit persons to whom
      9  * the Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
     19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     21  */
     22 
     23 /* The life cycle of surfaces
     24  *
     25  *    free => live => dead => destroyed => free
     26  *
     27  * A 'free' surface is one that is not allocated on the device. These
     28  * are stored on the 'free_surfaces' list.
     29  *
     30  * A 'live' surface is one that the X server is using for something. It
     31  * has an associated pixmap. It is allocated in the device. These are stored on
     32  * the "live_surfaces" list.
     33  *
     34  * A 'dead' surface is one that the X server is no using any more, but
     35  * is still allocated in the device. These surfaces may be stored in the
     36  * cache, from where they can be resurrected. The cache holds a ref on the
     37  * surfaces.
     38  *
     39  * A 'destroyed' surface is one whose ref count has reached 0. It is no
     40  * longer being referenced by either the server or the device or the cache.
     41  * When a surface enters this state, the associated pixman images are freed, and
     42  * a destroy command is sent. This will eventually trigger a 'recycle' call,
     43  * which puts the surface into the 'free' state.
     44  *
     45  */
     46 #ifdef HAVE_CONFIG_H
     47 #include "config.h"
     48 #endif
     49 
     50 #include "qxl.h"
     51 #include "qxl_surface.h"
     52 #ifdef DEBUG_SURFACE_LIFECYCLE
     53 #include <stdio.h>
     54 
     55 static FILE* surface_log;
     56 #endif
     57 
     58 typedef struct evacuated_surface_t evacuated_surface_t;
     59 
     60 struct evacuated_surface_t
     61 {
     62     pixman_image_t	*image;
     63     PixmapPtr		 pixmap;
     64     int			 bpp;
     65 
     66     evacuated_surface_t *prev;
     67     evacuated_surface_t *next;
     68 };
     69 
     70 #define N_CACHED_SURFACES 64
     71 
     72 /*
     73  * Surface cache
     74  */
     75 struct surface_cache_t
     76 {
     77     qxl_screen_t *qxl;
     78 
     79     /* Array of surfaces (not a linked list).
     80      * All surfaces, excluding the primary one, indexed by surface id.
     81      */
     82     qxl_surface_t *all_surfaces;
     83 
     84     /* All surfaces that the driver is currently using (linked through next/prev) */
     85     qxl_surface_t *live_surfaces;
     86 
     87     /* All surfaces that need to be allocated (linked through next, but not prev) */
     88     qxl_surface_t *free_surfaces;
     89 
     90     /* Surfaces that are already allocated, but not in used by the driver,
     91      * linked through next
     92      */
     93     qxl_surface_t *cached_surfaces[N_CACHED_SURFACES];
     94 };
     95 
     96 #ifdef DEBUG_SURFACE_LIFECYCLE
     97 static void debug_surface_open(void)
     98 {
     99     if (surface_log)
    100         return;
    101     surface_log = fopen("/tmp/xf86-video-qxl.surface.log", "w+");
    102     if (!surface_log)
    103     {
    104         fprintf(stderr, "error creating surface log file (DEBUG_SURFACE_LIFECYCLE)\n");
    105         exit(-1);
    106     }
    107 }
    108 
    109 static int surface_count(qxl_surface_t *surface)
    110 {
    111     int i;
    112 
    113     for (i = 0; surface ;++i, surface = surface->next);
    114     return i;
    115 }
    116 
    117 static void debug_surface_log(surface_cache_t *cache)
    118 {
    119     int  live_n, free_n;
    120 
    121     debug_surface_open();
    122     live_n = surface_count(cache->live_surfaces);
    123     free_n = surface_count(cache->free_surfaces);
    124     fprintf(surface_log, "live,free,sum = %d, %d, %d\n", live_n, free_n,
    125             live_n + free_n);
    126     fflush(surface_log);
    127 }
    128 
    129 #else
    130 #define debug_surface_log(cache)
    131 #endif
    132 
    133 
    134 static Bool
    135 surface_cache_init (surface_cache_t *cache, qxl_screen_t *qxl)
    136 {
    137     int n_surfaces = qxl->rom->n_surfaces;
    138     int i;
    139 
    140     if (!cache->all_surfaces)
    141     {
    142         /* all_surfaces is not freed when evacuating, since surfaces are still
    143          * tied to pixmaps that may be destroyed after evacuation before
    144          * recreation */
    145         cache->all_surfaces = calloc (n_surfaces, sizeof (qxl_surface_t));
    146         if (!cache->all_surfaces)
    147             return FALSE;
    148     }
    149 
    150     memset (cache->all_surfaces, 0, n_surfaces * sizeof (qxl_surface_t));
    151     memset (cache->cached_surfaces, 0, N_CACHED_SURFACES * sizeof (qxl_surface_t *));
    152 
    153     cache->free_surfaces = NULL;
    154     cache->live_surfaces = NULL;
    155 
    156     for (i = 0; i < n_surfaces; ++i)
    157     {
    158 	cache->all_surfaces[i].id = i;
    159 	cache->all_surfaces[i].cache = cache;
    160 	cache->all_surfaces[i].qxl = qxl;
    161 	cache->all_surfaces[i].dev_image = NULL;
    162 	cache->all_surfaces[i].host_image = NULL;
    163 	cache->all_surfaces[i].evacuated = NULL;
    164 
    165 	REGION_INIT (
    166 	    NULL, &(cache->all_surfaces[i].access_region), (BoxPtr)NULL, 0);
    167 	cache->all_surfaces[i].access_type = UXA_ACCESS_RO;
    168 
    169 	if (i) /* surface 0 is the primary surface */
    170 	{
    171 	    cache->all_surfaces[i].next = cache->free_surfaces;
    172 	    cache->free_surfaces = &(cache->all_surfaces[i]);
    173 	    cache->all_surfaces[i].in_use = FALSE;
    174 	}
    175     }
    176 
    177     return TRUE;
    178 }
    179 
    180 surface_cache_t *
    181 qxl_surface_cache_create (qxl_screen_t *qxl)
    182 {
    183     surface_cache_t *cache = malloc (sizeof *cache);
    184 
    185     if (!cache)
    186 	return NULL;
    187 
    188     memset(cache, 0, sizeof(*cache));
    189     cache->qxl = qxl;
    190     if (!surface_cache_init (cache, qxl))
    191     {
    192 	free (cache);
    193 	return NULL;
    194     }
    195 
    196     return cache;
    197 }
    198 
    199 void
    200 qxl_surface_cache_sanity_check (surface_cache_t *qxl)
    201 {
    202 #if 0
    203     qxl_surface_t *s;
    204 
    205     for (s = qxl->live_surfaces; s != NULL; s = s->next)
    206     {
    207 	PixmapPtr pixmap = s->pixmap;
    208 
    209 	if (! (get_surface (pixmap) == s) )
    210 	{
    211 	    ErrorF ("Surface %p has pixmap %p, but pixmap %p has surface %p\n",
    212 		    s, pixmap, pixmap, get_surface (pixmap));
    213 
    214 	    assert (0);
    215 	}
    216     }
    217 #endif
    218 }
    219 
    220 static void
    221 print_cache_info (surface_cache_t *cache)
    222 {
    223     int i;
    224     int n_surfaces = 0;
    225 
    226     ErrorF ("Cache contents:  ");
    227     for (i = 0; i < N_CACHED_SURFACES; ++i)
    228     {
    229 	if (cache->cached_surfaces[i])
    230 	{
    231 	    ErrorF ("%4d ", cache->cached_surfaces[i]->id);
    232 	    n_surfaces++;
    233 	}
    234 	else
    235 	    ErrorF ("null ");
    236     }
    237 
    238     ErrorF ("    total: %d\n", n_surfaces);
    239 }
    240 
    241 static qxl_surface_t *
    242 surface_get_from_cache (surface_cache_t *cache, int width, int height, int bpp)
    243 {
    244     int i;
    245 
    246     for (i = 0; i < N_CACHED_SURFACES; ++i)
    247     {
    248 	qxl_surface_t *s = cache->cached_surfaces[i];
    249 
    250 	if (s && bpp == s->bpp)
    251 	{
    252 	    int w = pixman_image_get_width (s->host_image);
    253 	    int h = pixman_image_get_height (s->host_image);
    254 
    255 	    if (width <= w && width * 4 > w && height <= h && height * 4 > h)
    256 	    {
    257 		cache->cached_surfaces[i] = NULL;
    258 
    259 		return s;
    260 	    }
    261 	}
    262     }
    263 
    264     return NULL;
    265 }
    266 
    267 static int n_live;
    268 
    269 void
    270 qxl_surface_recycle (surface_cache_t *cache, uint32_t id)
    271 {
    272     qxl_surface_t *surface = cache->all_surfaces + id;
    273 
    274     n_live--;
    275     if (surface->bo)
    276 	cache->qxl->bo_funcs->bo_decref (cache->qxl, surface->bo);
    277     surface->bo = NULL;
    278     surface->next = cache->free_surfaces;
    279     cache->free_surfaces = surface;
    280 }
    281 
    282 /*
    283  * mode is used for the whole virtual screen, not for a specific head.
    284  * For a single head where virtual size is equal to the head size, they are
    285  * equal. For multiple heads this mode will not match any existing heads and
    286  * will be the containing virtual size.
    287  */
    288 qxl_surface_t *
    289 qxl_surface_cache_create_primary (qxl_screen_t *qxl,
    290 				  struct QXLMode	*mode)
    291 {
    292     pixman_format_code_t format;
    293     uint8_t *dev_addr;
    294     pixman_image_t *dev_image, *host_image;
    295     qxl_surface_t *surface;
    296     surface_cache_t	*cache = qxl->surface_cache;
    297     struct qxl_bo *bo;
    298 
    299     if (mode->bits == 16)
    300     {
    301 	format = PIXMAN_x1r5g5b5;
    302     }
    303     else if (mode->bits == 32)
    304     {
    305 	format = PIXMAN_x8r8g8b8;
    306     }
    307     else
    308     {
    309 	xf86DrvMsg (qxl->pScrn->scrnIndex, X_ERROR,
    310 		    "Unknown bit depth %d\n", mode->bits);
    311 	return NULL;
    312     }
    313 
    314     bo = qxl->bo_funcs->create_primary(qxl, mode->x_res, mode->y_res, mode->stride, mode->bits);
    315 
    316     dev_addr = qxl->bo_funcs->bo_map(bo);
    317     dev_image = pixman_image_create_bits (format, mode->x_res, mode->y_res,
    318 					  (uint32_t *)dev_addr, (qxl->kms_enabled ? mode->stride : -mode->stride));
    319 
    320     host_image = pixman_image_create_bits (format,
    321 					   qxl->virtual_x, qxl->virtual_y,
    322 					   NULL, mode->stride);
    323 #if 0
    324     xf86DrvMsg(cache->qxl->pScrn->scrnIndex, X_ERROR,
    325                "testing dev_image memory (%d x %d)\n",
    326                mode->x_res, mode->y_res);
    327     memset(qxl->ram, 0, mode->stride * mode->y_res);
    328     xf86DrvMsg(cache->qxl->pScrn->scrnIndex, X_ERROR,
    329                "testing host_image memory\n");
    330     memset(qxl->fb, 0, mode->stride * mode->y_res);
    331 #endif
    332 
    333     surface = malloc (sizeof *surface);
    334     surface->id = 0;
    335     surface->dev_image = dev_image;
    336     surface->host_image = host_image;
    337     surface->cache = cache;
    338     surface->qxl = qxl;
    339     surface->bpp = mode->bits;
    340     surface->next = NULL;
    341     surface->prev = NULL;
    342     surface->evacuated = NULL;
    343     surface->bo = bo;
    344     surface->image_bo = NULL;
    345 
    346     REGION_INIT (NULL, &(surface->access_region), (BoxPtr)NULL, 0);
    347     surface->access_type = UXA_ACCESS_RO;
    348 
    349     return surface;
    350 }
    351 
    352 void *
    353 qxl_surface_get_host_bits(qxl_surface_t *surface)
    354 {
    355     if (!surface)
    356 	return NULL;
    357     return (void *) pixman_image_get_data(surface->host_image);
    358 }
    359 
    360 
    361 
    362 
    363 static struct qxl_bo *
    364 make_surface_cmd (surface_cache_t *cache, uint32_t id, QXLSurfaceCmdType type)
    365 {
    366     struct qxl_bo *cmd_bo;
    367     struct QXLSurfaceCmd *cmd;
    368     qxl_screen_t *qxl = cache->qxl;
    369 
    370     cmd_bo = qxl->bo_funcs->cmd_alloc (qxl, sizeof *cmd, "surface command");
    371     cmd = qxl->bo_funcs->bo_map(cmd_bo);
    372 
    373     cmd->release_info.id = pointer_to_u64 (cmd_bo) | 2;
    374     cmd->type = type;
    375     cmd->flags = 0;
    376     cmd->surface_id = id;
    377 
    378     qxl->bo_funcs->bo_unmap(cmd_bo);
    379     return cmd_bo;
    380 }
    381 
    382 static void
    383 push_surface_cmd (surface_cache_t *cache, struct qxl_bo *cmd_bo)
    384 {
    385     qxl_screen_t *qxl = cache->qxl;
    386 
    387     qxl->bo_funcs->write_command (qxl, QXL_CMD_SURFACE, cmd_bo);
    388 }
    389 
    390 
    391 static qxl_surface_t *
    392 surface_get_from_free_list (surface_cache_t *cache)
    393 {
    394     qxl_surface_t *result = NULL;
    395 
    396     if (cache->free_surfaces)
    397     {
    398 	qxl_surface_t *s;
    399 
    400 	result = cache->free_surfaces;
    401 	cache->free_surfaces = cache->free_surfaces->next;
    402 
    403 	result->next = NULL;
    404 	result->in_use = TRUE;
    405 	result->ref_count = 1;
    406 	result->pixmap = NULL;
    407 
    408 	for (s = cache->free_surfaces; s; s = s->next)
    409 	{
    410 	    if (s->id == result->id)
    411 		ErrorF ("huh: %d to be returned, but %d is in list\n",
    412 			s->id, result->id);
    413 
    414 	    assert (s->id != result->id);
    415 	}
    416     }
    417 
    418     return result;
    419 }
    420 
    421 static int
    422 align (int x)
    423 {
    424     return x;
    425 }
    426 
    427 static qxl_surface_t *
    428 surface_send_create (surface_cache_t *cache,
    429 		     int	      width,
    430 		     int	      height,
    431 		     int	      bpp)
    432 {
    433     SpiceSurfaceFmt format;
    434     pixman_format_code_t pformat;
    435     struct QXLSurfaceCmd *cmd;
    436     int stride;
    437     uint32_t *dev_addr;
    438     int n_attempts = 0;
    439     qxl_screen_t *qxl = cache->qxl;
    440     qxl_surface_t *surface;
    441     struct qxl_bo *bo, *cmd_bo;
    442     void *dev_ptr;
    443     qxl_get_formats (bpp, &format, &pformat);
    444 
    445     width = align (width);
    446     height = align (height);
    447 
    448     stride = width * PIXMAN_FORMAT_BPP (pformat) / 8;
    449     stride = (stride + 3) & ~3;
    450 
    451     /* the final + stride is to work around a bug where the device apparently
    452      * scribbles after the end of the image
    453      */
    454     qxl_garbage_collect (qxl);
    455 retry2:
    456     bo = qxl_ums_surf_mem_alloc(qxl, stride * height + stride);
    457 
    458     if (!bo)
    459     {
    460 	ErrorF ("- %dth attempt\n", n_attempts++);
    461 
    462 	if (qxl_garbage_collect (qxl))
    463 	    goto retry2;
    464 
    465 	ErrorF ("- OOM at %d %d %d (= %d bytes)\n", width, height, bpp, width * height * (bpp / 8));
    466 	print_cache_info (cache);
    467 
    468 	if (qxl_handle_oom (qxl))
    469 	{
    470 	    while (qxl_garbage_collect (qxl))
    471 		;
    472 	    goto retry2;
    473 	}
    474 
    475 	ErrorF ("Out of video memory: Could not allocate %d bytes\n",
    476 		stride * height + stride);
    477 
    478 	return NULL;
    479     }
    480 
    481 retry:
    482     surface = surface_get_from_free_list (cache);
    483     if (!surface)
    484     {
    485 	if (!qxl_handle_oom (cache->qxl))
    486 	{
    487 	    ErrorF ("  Out of surfaces\n");
    488 	    qxl->bo_funcs->bo_decref (qxl, bo);
    489 	    return NULL;
    490 	}
    491 	else
    492 	    goto retry;
    493     }
    494 
    495     surface->bo = bo;
    496 
    497     cmd_bo = make_surface_cmd (cache, surface->id, QXL_SURFACE_CMD_CREATE);
    498 
    499     cmd = qxl->bo_funcs->bo_map(cmd_bo);
    500     cmd->u.surface_create.format = format;
    501     cmd->u.surface_create.width = width;
    502     cmd->u.surface_create.height = height;
    503     cmd->u.surface_create.stride = - stride;
    504     qxl->bo_funcs->bo_unmap(cmd_bo);
    505 
    506     qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(struct QXLSurfaceCmd, u.surface_create.data), cmd_bo, surface->bo);
    507 
    508     push_surface_cmd (cache, cmd_bo);
    509 
    510     dev_ptr = qxl->bo_funcs->bo_map(surface->bo);
    511     dev_addr
    512 	= (uint32_t *)((uint8_t *)dev_ptr + stride * (height - 1));
    513 
    514     surface->dev_image = pixman_image_create_bits (
    515 	pformat, width, height, dev_addr, - stride);
    516 
    517     surface->host_image = pixman_image_create_bits (
    518 	pformat, width, height, NULL, -1);
    519 
    520     qxl->bo_funcs->bo_unmap(surface->bo);
    521     surface->bpp = bpp;
    522 
    523     n_live++;
    524 
    525     return surface;
    526 }
    527 
    528 qxl_surface_t *
    529 qxl_surface_create (qxl_screen_t *qxl,
    530 		    int			 width,
    531 		    int			 height,
    532 		    int			 bpp)
    533 {
    534     qxl_surface_t *surface;
    535     surface_cache_t *cache = qxl->surface_cache;
    536 
    537     if (!qxl->enable_surfaces)
    538 	return NULL;
    539 
    540     if ((bpp & 3) != 0)
    541     {
    542 	ErrorF ("%s: Bad bpp: %d (%d)\n", __FUNCTION__, bpp, bpp & 7);
    543 	return NULL;
    544     }
    545 
    546 #if 0
    547     if (bpp == 8)
    548       {
    549 	static int warned;
    550 	if (!warned)
    551 	{
    552 	    warned = 1;
    553 	    ErrorF ("bpp == 8 triggers bugs in spice apparently\n");
    554 	}
    555 
    556 	return NULL;
    557       }
    558 #endif
    559 
    560     if (bpp != 8 && bpp != 16 && bpp != 32 && bpp != 24)
    561     {
    562 	ErrorF ("%s: Unknown bpp\n", __FUNCTION__);
    563 	return NULL;
    564     }
    565 
    566     if (width == 0 || height == 0)
    567     {
    568 	ErrorF ("%s: Zero width or height\n", __FUNCTION__);
    569 	return NULL;
    570     }
    571 
    572     if (!(surface = surface_get_from_cache (cache, width, height, bpp)))
    573 	if (!(surface = surface_send_create (cache, width, height, bpp)))
    574 	    return NULL;
    575 
    576     surface->next = cache->live_surfaces;
    577     surface->prev = NULL;
    578     if (cache->live_surfaces)
    579 	cache->live_surfaces->prev = surface;
    580     cache->live_surfaces = surface;
    581 
    582     return surface;
    583 }
    584 
    585 void
    586 qxl_surface_set_pixmap (qxl_surface_t *surface, PixmapPtr pixmap)
    587 {
    588     surface->pixmap = pixmap;
    589 
    590     assert (get_surface (pixmap) == surface);
    591 }
    592 
    593 static void
    594 unlink_surface (qxl_surface_t *surface)
    595 {
    596     if (surface->id != 0)
    597     {
    598         if (surface->prev)
    599             surface->prev->next = surface->next;
    600         else
    601             surface->cache->live_surfaces = surface->next;
    602     }
    603 
    604     debug_surface_log(surface->cache);
    605 
    606     if (surface->next)
    607 	surface->next->prev = surface->prev;
    608 
    609     surface->pixmap = NULL;
    610 
    611     surface->prev = NULL;
    612     surface->next = NULL;
    613 }
    614 
    615 static void
    616 surface_destroy (qxl_surface_t *surface)
    617 {
    618     struct qxl_bo *cmd_bo;
    619 
    620     if (surface->dev_image)
    621 	pixman_image_unref (surface->dev_image);
    622     if (surface->host_image)
    623 	pixman_image_unref (surface->host_image);
    624 
    625 #if 0
    626     ErrorF("destroy %ld\n", (long int)surface->end - (long int)surface->address);
    627 #endif
    628     cmd_bo = make_surface_cmd (surface->cache, surface->id, QXL_SURFACE_CMD_DESTROY);
    629 
    630     push_surface_cmd (surface->cache, cmd_bo);
    631 
    632     surface->cache->qxl->bo_funcs->bo_decref(surface->cache->qxl, surface->bo);
    633 }
    634 
    635 static void
    636 surface_add_to_cache (qxl_surface_t *surface)
    637 {
    638     surface_cache_t *cache = surface->cache;
    639     int oldest = -1;
    640     int n_surfaces = 0;
    641     int i, delta;
    642     int destroy_id = -1;
    643     qxl_surface_t *destroy_surface = NULL;
    644 
    645     surface->ref_count++;
    646 
    647     for (i = 0; i < N_CACHED_SURFACES; ++i)
    648     {
    649 	if (cache->cached_surfaces[i])
    650 	{
    651 	    oldest = i;
    652 	    n_surfaces++;
    653 	}
    654     }
    655 
    656     if (n_surfaces == N_CACHED_SURFACES)
    657     {
    658 	destroy_id = cache->cached_surfaces[oldest]->id;
    659 
    660 	destroy_surface = cache->cached_surfaces[oldest];
    661 
    662 	cache->cached_surfaces[oldest] = NULL;
    663 
    664 	for (i = 0; i < N_CACHED_SURFACES; ++i)
    665 	    assert (!cache->cached_surfaces[i] ||
    666 		    cache->cached_surfaces[i]->id != destroy_id);
    667     }
    668 
    669     delta = 0;
    670     for (i = N_CACHED_SURFACES - 1; i >= 0; i--)
    671     {
    672 	if (cache->cached_surfaces[i])
    673 	{
    674 	    if (delta > 0)
    675 	    {
    676 		cache->cached_surfaces[i + delta] =
    677 		    cache->cached_surfaces[i];
    678 
    679 		assert (cache->cached_surfaces[i + delta]->id != destroy_id);
    680 
    681 		cache->cached_surfaces[i] = NULL;
    682 	    }
    683 	}
    684 	else
    685 	{
    686 	    delta++;
    687 	}
    688     }
    689 
    690     assert (delta > 0);
    691 
    692     cache->cached_surfaces[i + delta] = surface;
    693 
    694     for (i = 0; i < N_CACHED_SURFACES; ++i)
    695 	assert (!cache->cached_surfaces[i] || cache->cached_surfaces[i]->id != destroy_id);
    696 
    697     /* Note that sending a destroy command can trigger callbacks into
    698      * this function (due to memory management), so we have to
    699      * do this after updating the cache
    700      */
    701     if (destroy_surface)
    702 	qxl_surface_unref (destroy_surface->cache, destroy_surface->id);
    703 }
    704 
    705 void
    706 qxl_surface_unref (surface_cache_t *cache, uint32_t id)
    707 {
    708     if (id != 0)
    709     {
    710 	qxl_surface_t *surface = cache->all_surfaces + id;
    711 
    712 	if (--surface->ref_count == 0)
    713 	    surface_destroy (surface);
    714     }
    715 }
    716 
    717 void
    718 qxl_surface_kill (qxl_surface_t *surface)
    719 {
    720     struct evacuated_surface_t *ev = surface->evacuated;
    721 
    722     if (ev)
    723     {
    724         /* server side surface is already destroyed (via reset), don't
    725          * resend a destroy. Just mark surface as not to be recreated */
    726         ev->pixmap = NULL;
    727         if (ev->image)
    728             pixman_image_unref (ev->image);
    729         if (ev->next)
    730             ev->next->prev = ev->prev;
    731         if (ev->prev)
    732             ev->prev->next = ev->next;
    733         free(ev);
    734         surface->evacuated = NULL;
    735         return;
    736     }
    737 
    738     unlink_surface (surface);
    739 
    740     if (!surface->cache->all_surfaces) {
    741         return;
    742     }
    743 
    744     if (surface->id != 0					&&
    745         surface->host_image                                     &&
    746 	pixman_image_get_width (surface->host_image) >= 128	&&
    747 	pixman_image_get_height (surface->host_image) >= 128)
    748     {
    749 	surface_add_to_cache (surface);
    750     }
    751 
    752     qxl_surface_unref (surface->cache, surface->id);
    753 }
    754 
    755 
    756 void *
    757 qxl_surface_cache_evacuate_all (surface_cache_t *cache)
    758 {
    759     evacuated_surface_t *evacuated_surfaces = NULL;
    760     qxl_surface_t *s;
    761     int i;
    762 
    763     for (i = 0; i < N_CACHED_SURFACES; ++i)
    764     {
    765 	if (cache->cached_surfaces[i])
    766 	{
    767             surface_destroy (cache->cached_surfaces[i]);
    768 	    cache->cached_surfaces[i] = NULL;
    769 	}
    770     }
    771 
    772     s = cache->live_surfaces;
    773     while (s != NULL)
    774     {
    775 	qxl_surface_t *next = s->next;
    776 	evacuated_surface_t *evacuated = malloc (sizeof (evacuated_surface_t));
    777 	int width, height;
    778 
    779 	width = pixman_image_get_width (s->host_image);
    780 	height = pixman_image_get_height (s->host_image);
    781 
    782 	qxl_download_box (s, 0, 0, width, height);
    783 
    784 	evacuated->image = s->host_image;
    785 	evacuated->pixmap = s->pixmap;
    786 
    787 	assert (get_surface (evacuated->pixmap) == s);
    788 
    789 	evacuated->bpp = s->bpp;
    790 
    791 	s->host_image = NULL;
    792 
    793 	unlink_surface (s);
    794 
    795 	evacuated->prev = NULL;
    796 	evacuated->next = evacuated_surfaces;
    797         if (evacuated_surfaces)
    798             evacuated_surfaces->prev = evacuated;
    799 	evacuated_surfaces = evacuated;
    800         s->evacuated = evacuated;
    801 
    802 	s = next;
    803     }
    804 
    805     cache->live_surfaces = NULL;
    806     cache->free_surfaces = NULL;
    807 
    808     return evacuated_surfaces;
    809 }
    810 
    811 void
    812 qxl_surface_cache_replace_all (surface_cache_t *cache, void *data)
    813 {
    814     evacuated_surface_t *ev;
    815 
    816     if (!surface_cache_init (cache, cache->qxl))
    817     {
    818 	/* FIXME: report the error */
    819 	return;
    820     }
    821 
    822     ev = data;
    823     while (ev != NULL)
    824     {
    825 	evacuated_surface_t *next = ev->next;
    826 	int width = pixman_image_get_width (ev->image);
    827 	int height = pixman_image_get_height (ev->image);
    828 	qxl_surface_t *surface;
    829 
    830 	surface = qxl_surface_create (cache->qxl, width, height, ev->bpp);
    831 
    832 	assert (surface->host_image);
    833 	assert (surface->dev_image);
    834 
    835 	pixman_image_unref (surface->host_image);
    836 	surface->host_image = ev->image;
    837 
    838 	qxl_upload_box (surface, 0, 0, width, height);
    839 
    840 	set_surface (ev->pixmap, surface);
    841 
    842 	qxl_surface_set_pixmap (surface, ev->pixmap);
    843 
    844 	free (ev);
    845 
    846 	ev = next;
    847     }
    848 
    849     qxl_surface_cache_sanity_check (cache);
    850 
    851 }
    852