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
55static FILE* surface_log;
56#endif
57
58typedef struct evacuated_surface_t evacuated_surface_t;
59
60struct 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 */
75struct 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
97static 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
109static 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
117static 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
134static Bool
135surface_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
180surface_cache_t *
181qxl_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
199void
200qxl_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
220static void
221print_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
241static qxl_surface_t *
242surface_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
267static int n_live;
268
269void
270qxl_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 */
288qxl_surface_t *
289qxl_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
352void *
353qxl_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
363static struct qxl_bo *
364make_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
382static void
383push_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
391static qxl_surface_t *
392surface_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
421static int
422align (int x)
423{
424    return x;
425}
426
427static qxl_surface_t *
428surface_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);
455retry2:
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
481retry:
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
528qxl_surface_t *
529qxl_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
585void
586qxl_surface_set_pixmap (qxl_surface_t *surface, PixmapPtr pixmap)
587{
588    surface->pixmap = pixmap;
589
590    assert (get_surface (pixmap) == surface);
591}
592
593static void
594unlink_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
615static void
616surface_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
635static void
636surface_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
705void
706qxl_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
717void
718qxl_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
756void *
757qxl_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
811void
812qxl_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