summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2010-11-13 16:30:36 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2010-11-15 19:44:32 -0500
commit4d12a0fc13b6357d7758362189dd1a59f5feccf4 (patch)
tree9f50259b311b59ff029e109eda4d5c17ed9ac943
parent6768b98ddb393eee9a43467ae0db1dcf17af57fe (diff)
Add a surface cache
-rw-r--r--src/qxl.h30
-rw-r--r--src/qxl_driver.c22
-rw-r--r--src/qxl_surface.c429
3 files changed, 345 insertions, 136 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 9f7e516..5f932ff 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -604,6 +604,7 @@ struct qxl_ram_header {
};
#pragma pack(pop)
+typedef struct surface_cache_t surface_cache_t;
typedef struct _qxl_screen_t qxl_screen_t;
@@ -691,17 +692,7 @@ struct _qxl_screen_t
uint8_t vram_mem_slot;
- /* 'All' surfaces is an array of all surfaces, indexed by
- * surface id.
- *
- * 'Live' is a double linked list of all
- * surfaces that correspond to a pixmap
- *
- * 'Free' is a single linked list of all free surfaces
- */
- qxl_surface_t * all_surfaces;
- qxl_surface_t * live_surfaces;
- qxl_surface_t * free_surfaces;
+ surface_cache_t * surface_cache;
};
static inline uint64_t
@@ -762,19 +753,20 @@ void qxl_ring_wait_idle (struct qxl_ring *ring);
/*
* Surface
*/
-void qxl_surface_init (qxl_screen_t *qxl);
-qxl_surface_t * qxl_surface_create_primary (qxl_screen_t *qxl,
+surface_cache_t * qxl_surface_cache_create (qxl_screen_t *qxl);
+qxl_surface_t * qxl_surface_cache_create_primary (surface_cache_t *qxl,
struct qxl_mode *mode);
-qxl_surface_t * qxl_surface_create (qxl_screen_t *qxl,
+qxl_surface_t * qxl_surface_create (surface_cache_t *qxl,
int width,
int height,
int bpp);
void
-qxl_surface_sanity_check (qxl_screen_t *qxl);
+qxl_surface_cache_sanity_check (surface_cache_t *qxl);
void *
-qxl_surface_evacuate_all (qxl_screen_t *qxl);
+qxl_surface_cache_evacuate_all (surface_cache_t *qxl);
void
-qxl_surface_replace_all (qxl_screen_t *qxl, void *data);
+qxl_surface_cache_replace_all (surface_cache_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 */
@@ -782,7 +774,7 @@ void qxl_surface_destroy (qxl_surface_t *surface);
/* Call this when the notification comes back from the device
* that the surface has been destroyed
*/
-void qxl_surface_recycle (qxl_screen_t *qxl, uint32_t id);
+void qxl_surface_recycle (surface_cache_t *cache, uint32_t id);
/* send anything pending to the other side */
void qxl_surface_flush (qxl_surface_t *surface);
@@ -814,7 +806,7 @@ void qxl_surface_copy (qxl_surface_t *dest,
Bool qxl_surface_put_image (qxl_surface_t *dest,
int x, int y, int width, int height,
const char *src, int src_pitch);
-void qxl_surface_unref (qxl_screen_t *qxl,
+void qxl_surface_unref (surface_cache_t *cache,
uint32_t surface_id);
diff --git a/src/qxl_driver.c b/src/qxl_driver.c
index 226c331..8d076fb 100644
--- a/src/qxl_driver.c
+++ b/src/qxl_driver.c
@@ -86,7 +86,7 @@ qxl_garbage_collect (qxl_screen_t *qxl)
if (image->descriptor.type == QXL_IMAGE_TYPE_SURFACE)
{
- qxl_surface_unref (qxl, image->u.surface_id);
+ qxl_surface_unref (qxl->surface_cache, image->u.surface_id);
qxl_free (qxl->mem, image);
}
else
@@ -96,7 +96,7 @@ qxl_garbage_collect (qxl_screen_t *qxl)
}
else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY)
{
- qxl_surface_recycle (qxl, surface_cmd->surface_id);
+ qxl_surface_recycle (qxl->surface_cache, surface_cmd->surface_id);
}
id = info->next;
@@ -338,13 +338,11 @@ qxl_reset (qxl_screen_t *qxl)
qxl_memslot_t *slot;
uint64_t high_bits;
struct qxl_ram_header *ram_header;
-
+
outb(qxl->io_base + QXL_IO_RESET, 0);
ram_header = (void *)((unsigned long)qxl->ram + (unsigned long)qxl->rom->ram_header_offset);
- qxl_surface_init (qxl);
-
/* Mem slots */
ErrorF ("slots start: %d, slots end: %d\n",
qxl->rom->slots_start,
@@ -432,7 +430,7 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
ScreenPtr pScreen;
void *evacuated;
- evacuated = qxl_surface_evacuate_all (qxl);
+ evacuated = qxl_surface_cache_evacuate_all (qxl->surface_cache);
if (qxl->primary)
qxl_surface_destroy (qxl->primary);
@@ -441,7 +439,7 @@ qxl_switch_mode(int scrnIndex, DisplayModePtr p, int flags)
ErrorF ("done reset\n");
- qxl->primary = qxl_surface_create_primary (qxl, m);
+ qxl->primary = qxl_surface_cache_create_primary (qxl->surface_cache, m);
qxl->current_mode = m;
qxl->bytes_per_pixel = (qxl->pScrn->bitsPerPixel + 7) / 8;
@@ -463,7 +461,7 @@ 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);
+ qxl_surface_cache_replace_all (qxl->surface_cache, evacuated);
return TRUE;
}
@@ -657,13 +655,13 @@ 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);
+ qxl_surface_cache_sanity_check (qxl->surface_cache);
#if 0
ErrorF ("Create pixmap: %d %d @ %d (usage: %d)\n", w, h, depth, usage);
#endif
- surface = qxl_surface_create (qxl, w, h, depth);
+ surface = qxl_surface_create (qxl->surface_cache, w, h, depth);
if (surface)
{
@@ -707,7 +705,7 @@ qxl_destroy_pixmap (PixmapPtr pixmap)
qxl_screen_t *qxl = scrn->driverPrivate;
qxl_surface_t *surface = NULL;
- qxl_surface_sanity_check (qxl);
+ qxl_surface_cache_sanity_check (qxl->surface_cache);
if (pixmap->refcnt == 1)
{
@@ -892,7 +890,7 @@ qxl_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv)
sizeof (uint64_t),
8, 0);
- qxl_surface_init (qxl);
+ qxl->surface_cache = qxl_surface_cache_create (qxl);
/* xf86DPMSInit(pScreen, xf86DPMSSet, 0); */
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 372637c..9dc005e 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -4,7 +4,7 @@ typedef struct evacuated_surface_t evacuated_surface_t;
struct qxl_surface_t
{
- qxl_screen_t * qxl;
+ surface_cache_t *cache;
uint32_t id;
@@ -17,7 +17,9 @@ struct qxl_surface_t
void * end;
qxl_surface_t * next;
- qxl_surface_t * prev; /* Only used in the 'live' chain in qxl_screen */
+ qxl_surface_t * prev; /* Only used in the 'live'
+ * chain in the surface cache
+ */
int in_use;
int Bpp;
@@ -41,8 +43,89 @@ struct evacuated_surface_t
evacuated_surface_t *next;
};
+#define N_CACHED_SURFACES 16
+
+/*
+ * Surface cache
+ */
+struct surface_cache_t
+{
+ qxl_screen_t *qxl;
+
+ /* Array of surfaces (not a linked list).
+ * All surfaces, excluding the primary one, indexed by surface id.
+ */
+ qxl_surface_t *all_surfaces;
+
+ /* All surfaces that the driver is currently using (linked through next/prev) */
+ qxl_surface_t *live_surfaces;
+
+ /* All surfaces that need to be allocated (linked through next, but not prev) */
+ qxl_surface_t *free_surfaces;
+
+ /* Surfaces that are already allocated, but not in used by the driver,
+ * linked through next
+ */
+ qxl_surface_t *cached_surfaces[N_CACHED_SURFACES];
+};
+
+static Bool
+surface_cache_init (surface_cache_t *cache, qxl_screen_t *qxl)
+{
+ int n_surfaces = qxl->rom->n_surfaces;
+ int i;
+
+ cache->all_surfaces = calloc (n_surfaces, sizeof (qxl_surface_t));
+ if (!cache->all_surfaces)
+ return FALSE;
+
+ memset (cache->all_surfaces, 0, n_surfaces * sizeof (qxl_surface_t));
+ memset (cache->cached_surfaces, 0, N_CACHED_SURFACES * sizeof (qxl_surface_t *));
+
+ cache->free_surfaces = NULL;
+ cache->live_surfaces = NULL;
+
+ for (i = 0; i < n_surfaces; ++i)
+ {
+ cache->all_surfaces[i].id = i;
+ cache->all_surfaces[i].cache = cache;
+ cache->all_surfaces[i].dev_image = NULL;
+ cache->all_surfaces[i].host_image = NULL;
+
+ REGION_INIT (
+ NULL, &(cache->all_surfaces[i].access_region), (BoxPtr)NULL, 0);
+
+ if (i) /* surface 0 is the primary surface */
+ {
+ cache->all_surfaces[i].next = cache->free_surfaces;
+ cache->free_surfaces = &(cache->all_surfaces[i]);
+ cache->all_surfaces[i].in_use = FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+surface_cache_t *
+qxl_surface_cache_create (qxl_screen_t *qxl)
+{
+ surface_cache_t *cache = malloc (sizeof *cache);
+
+ if (!cache)
+ return NULL;
+
+ cache->qxl = qxl;
+ if (!surface_cache_init (cache, qxl))
+ {
+ free (cache);
+ return NULL;
+ }
+
+ return cache;
+}
+
void
-qxl_surface_sanity_check (qxl_screen_t *qxl)
+qxl_surface_cache_sanity_check (surface_cache_t *qxl)
{
qxl_surface_t *s;
@@ -75,61 +158,85 @@ qxl_surface_free_all (qxl_screen_t *qxl)
}
#endif
-void
-qxl_surface_init (qxl_screen_t *qxl)
+static void
+print_cache_info (surface_cache_t *cache)
{
- int n_surfaces;
+#if 0
int i;
+ int n_surfaces = 0;
- n_surfaces = qxl->rom->n_surfaces;
-
- if (!qxl->all_surfaces)
- qxl->all_surfaces = calloc (n_surfaces, sizeof (qxl_surface_t));
- else
- memset (qxl->all_surfaces, 0, n_surfaces * sizeof (qxl_surface_t));
+ ErrorF ("Cache contents: ");
+ for (i = 0; i < N_CACHED_SURFACES; ++i)
+ {
+ if (cache->cached_surfaces[i])
+ {
+ ErrorF ("%4d ", cache->cached_surfaces[i]->id);
+ n_surfaces++;
+ }
+ else
+ ErrorF ("null ");
+ }
+
+ ErrorF (" total: %d\n", n_surfaces);
+#endif
+}
+
+static qxl_surface_t *
+surface_get_cached (surface_cache_t *cache, int width, int height, int bpp)
+{
+ int i;
- qxl->free_surfaces = NULL;
-
#if 0
- ErrorF ("surface init\n");
+ ErrorF ("Before getting from cache\n");
#endif
-
- for (i = 0; i < n_surfaces; ++i)
+ print_cache_info (cache);
+
+ for (i = 0; i < N_CACHED_SURFACES; ++i)
{
- qxl->all_surfaces[i].id = i;
- qxl->all_surfaces[i].qxl = qxl;
- qxl->all_surfaces[i].dev_image = NULL;
- qxl->all_surfaces[i].host_image = NULL;
-
- REGION_INIT (NULL, &(qxl->all_surfaces[i].access_region), (BoxPtr)NULL, 0);
+ qxl_surface_t *s = cache->cached_surfaces[i];
- if (i) /* surface 0 is the primary surface */
+ if (s && bpp / 8 == s->Bpp)
{
- qxl->all_surfaces[i].next = qxl->free_surfaces;
- qxl->free_surfaces = &(qxl->all_surfaces[i]);
- qxl->all_surfaces[i].in_use = FALSE;
+ int w;
+ int h;
+
+ w = pixman_image_get_width (s->host_image);
+ h = pixman_image_get_height (s->host_image);
+
+ if (width <= w && width * 2 > w && height <= h && height * 2 > h)
+ {
+ cache->cached_surfaces[i] = NULL;
+
+#if 0
+ ErrorF ("Got %d from cache\n", s->id);
+#endif
+ print_cache_info (cache);
+ return s;
+ }
}
}
+
+ return NULL;
}
static qxl_surface_t *
-surface_new (qxl_screen_t *qxl)
+surface_new (surface_cache_t *cache)
{
qxl_surface_t *result = NULL;
- if (qxl->free_surfaces)
+ if (cache->free_surfaces)
{
qxl_surface_t *s;
- result = qxl->free_surfaces;
- qxl->free_surfaces = qxl->free_surfaces->next;
+ result = cache->free_surfaces;
+ cache->free_surfaces = cache->free_surfaces->next;
result->next = NULL;
result->in_use = TRUE;
result->ref_count = 1;
result->pixmap = NULL;
- for (s = qxl->free_surfaces; s; s = s->next)
+ for (s = cache->free_surfaces; s; s = s->next)
{
if (s->id == result->id)
ErrorF ("huh: %d to be returned, but %d is in list\n",
@@ -139,31 +246,50 @@ surface_new (qxl_screen_t *qxl)
}
}
+#if 0
+ if (result)
+ ErrorF ("returning %d from surface_new\n", result->id);
+ else
+ ErrorF ("returning nul from surface_new\n");
+#endif
+
return result;
}
-static void
-surface_free (qxl_screen_t *qxl, qxl_surface_t *surface)
+void
+qxl_surface_recycle (surface_cache_t *cache, uint32_t id)
{
+ qxl_surface_t *surface = cache->all_surfaces + id;
+
+#if 0
+ ErrorF ("recycle %d\n", id);
+#endif
+
+#if 0
+ ErrorF ("freeing %p\n", surface->address);
+#endif
+ qxl_free (cache->qxl->surf_mem, surface->address);
+
#if 0
ErrorF (" Adding %d to free list\n", surface->id);
#endif
- surface->next = qxl->free_surfaces;
- qxl->free_surfaces = surface;
+ surface->next = cache->free_surfaces;
+ cache->free_surfaces = surface;
}
qxl_surface_t *
-qxl_surface_create_primary (qxl_screen_t *qxl,
- struct qxl_mode *mode)
+qxl_surface_cache_create_primary (surface_cache_t *cache,
+ struct qxl_mode *mode)
{
struct qxl_ram_header *ram_header =
- (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset);
+ (void *)((unsigned long)cache->qxl->ram + cache->qxl->rom->ram_header_offset);
struct qxl_surface_create *create = &(ram_header->create_surface);
pixman_format_code_t format;
uint8_t *dev_addr;
pixman_image_t *dev_image, *host_image;
qxl_surface_t *surface;
+ qxl_screen_t *qxl = cache->qxl;
if (mode->bits == 16)
{
@@ -175,7 +301,7 @@ qxl_surface_create_primary (qxl_screen_t *qxl,
}
else
{
- xf86DrvMsg (qxl->pScrn->scrnIndex, X_ERROR,
+ xf86DrvMsg (cache->qxl->pScrn->scrnIndex, X_ERROR,
"Unknown bit depth %d\n", mode->bits);
return NULL;
}
@@ -187,7 +313,7 @@ qxl_surface_create_primary (qxl_screen_t *qxl,
create->position = 0; /* What is this? The Windows driver doesn't use it */
create->flags = 0;
create->type = QXL_SURF_TYPE_PRIMARY;
- create->mem = physical_address (qxl, qxl->ram, qxl->main_mem_slot);
+ create->mem = physical_address (cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot);
outb (qxl->io_base + QXL_IO_CREATE_PRIMARY, 0);
@@ -204,7 +330,7 @@ qxl_surface_create_primary (qxl_screen_t *qxl,
surface->id = 0;
surface->dev_image = dev_image;
surface->host_image = host_image;
- surface->qxl = qxl;
+ surface->cache = cache;
surface->Bpp = PIXMAN_FORMAT_BPP (format) / 8;
surface->next = NULL;
surface->prev = NULL;
@@ -219,9 +345,10 @@ qxl_surface_create_primary (qxl_screen_t *qxl,
}
static struct qxl_surface_cmd *
-make_surface_cmd (qxl_screen_t *qxl, uint32_t id, qxl_surface_cmd_type type)
+make_surface_cmd (surface_cache_t *cache, uint32_t id, qxl_surface_cmd_type type)
{
struct qxl_surface_cmd *cmd;
+ qxl_screen_t *qxl = cache->qxl;
qxl_garbage_collect (qxl);
@@ -236,9 +363,10 @@ make_surface_cmd (qxl_screen_t *qxl, uint32_t id, qxl_surface_cmd_type type)
}
static void
-push_surface_cmd (qxl_screen_t *qxl, struct qxl_surface_cmd *cmd)
+push_surface_cmd (surface_cache_t *cache, struct qxl_surface_cmd *cmd)
{
struct qxl_command command;
+ qxl_screen_t *qxl = cache->qxl;
command.type = QXL_CMD_SURFACE;
command.data = physical_address (qxl, cmd, qxl->main_mem_slot);
@@ -345,10 +473,10 @@ submit_fill (qxl_screen_t *qxl, int id,
}
qxl_surface_t *
-qxl_surface_create (qxl_screen_t *qxl,
- int width,
- int height,
- int bpp)
+qxl_surface_create (surface_cache_t * cache,
+ int width,
+ int height,
+ int bpp)
{
qxl_surface_t *surface;
struct qxl_surface_cmd *cmd;
@@ -357,6 +485,7 @@ qxl_surface_create (qxl_screen_t *qxl,
int stride;
uint32_t *dev_addr;
int n_attempts = 0;
+ qxl_screen_t *qxl = cache->qxl;
#if 0
ErrorF (" qxl_surface: attempting to allocate %d x %d @ %d\n", width, height, bpp);
@@ -386,11 +515,16 @@ qxl_surface_create (qxl_screen_t *qxl,
return NULL;
}
+ surface = surface_get_cached (cache, width, height, bpp);
+
+ if (surface)
+ return surface;
+
retry:
- surface = surface_new (qxl);
+ surface = surface_new (cache);
if (!surface)
{
- if (!qxl_handle_oom (qxl))
+ if (!qxl_handle_oom (cache->qxl))
{
ErrorF (" Out of surfaces\n");
return NULL;
@@ -442,7 +576,7 @@ retry:
/* the final + stride is to work around a bug where the device apparently
* scribbles after the end of the image
*/
- qxl_garbage_collect (qxl);
+ qxl_garbage_collect (cache->qxl);
retry2:
surface->address = qxl_alloc (qxl->surf_mem, stride * height + stride);
@@ -470,7 +604,7 @@ retry2:
surface->end = (char *)surface->address + stride * height;
- cmd = make_surface_cmd (qxl, surface->id, QXL_SURFACE_CMD_CREATE);
+ cmd = make_surface_cmd (cache, surface->id, QXL_SURFACE_CMD_CREATE);
cmd->u.surface_create.format = format;
cmd->u.surface_create.width = width;
@@ -480,7 +614,7 @@ retry2:
cmd->u.surface_create.physical =
physical_address (qxl, surface->address, qxl->vram_mem_slot);
- push_surface_cmd (qxl, cmd);
+ push_surface_cmd (cache, cmd);
#if 0
ErrorF ("Allocated %d\n", surface->id);
@@ -496,11 +630,11 @@ retry2:
surface->Bpp = PIXMAN_FORMAT_BPP (pformat) / 8;
- surface->next = qxl->live_surfaces;
+ surface->next = cache->live_surfaces;
surface->prev = NULL;
- if (qxl->live_surfaces)
- qxl->live_surfaces->prev = surface;
- qxl->live_surfaces = surface;
+ if (cache->live_surfaces)
+ cache->live_surfaces->prev = surface;
+ cache->live_surfaces = surface;
return surface;
}
@@ -516,15 +650,10 @@ qxl_surface_set_pixmap (qxl_surface_t *surface, PixmapPtr pixmap)
static void
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);
-
if (surface->prev)
surface->prev->next = surface->next;
else
- surface->qxl->live_surfaces = surface->next;
+ surface->cache->live_surfaces = surface->next;
if (surface->next)
surface->next->prev = surface->prev;
@@ -535,24 +664,109 @@ unlink_surface (qxl_surface_t *surface)
surface->next = NULL;
}
+static void
+send_destroy (qxl_surface_t *surface)
+{
+ struct qxl_surface_cmd *cmd;
+
+#if 0
+ ErrorF ("destroy %d\n", surface->id);
+#endif
+
+ if (surface->dev_image)
+ pixman_image_unref (surface->dev_image);
+ if (surface->host_image)
+ pixman_image_unref (surface->host_image);
+
+ cmd = make_surface_cmd (surface->cache, surface->id, QXL_SURFACE_CMD_DESTROY);
+
+ push_surface_cmd (surface->cache, cmd);
+}
+
void
-qxl_surface_unref (qxl_screen_t *qxl, uint32_t id)
+qxl_surface_unref (surface_cache_t *cache, uint32_t id)
{
if (id != 0)
{
- qxl_surface_t *surface = qxl->all_surfaces + id;
-
+ qxl_surface_t *surface = cache->all_surfaces + id;
+
if (--surface->ref_count == 0)
{
- struct qxl_surface_cmd *cmd;
-
- cmd = make_surface_cmd (qxl, surface->id, QXL_SURFACE_CMD_DESTROY);
+ int oldest = -1;
+ int n_surfaces = 0;
+ int i, delta;
+ int destroy_id = -1;
+ qxl_surface_t *destroy_surface = NULL;
#if 0
- ErrorF ("Destroying %d\n", id);
+ ErrorF ("Unreffing %d - before\n", id);
#endif
+
+ print_cache_info (cache);
+
+ for (i = 0; i < N_CACHED_SURFACES; ++i)
+ {
+ if (cache->cached_surfaces[i])
+ {
+ oldest = i;
+ n_surfaces++;
+ }
+ }
+
+ if (n_surfaces == N_CACHED_SURFACES)
+ {
+ int i;
+ destroy_id = cache->cached_surfaces[oldest]->id;
+
+ destroy_surface = cache->cached_surfaces[oldest];
+
+ cache->cached_surfaces[oldest] = NULL;
+
+ print_cache_info (cache);
+
+ for (i = 0; i < N_CACHED_SURFACES; ++i)
+ assert (!cache->cached_surfaces[i] ||
+ cache->cached_surfaces[i]->id != destroy_id);
+ }
+
+ delta = 0;
+ for (i = N_CACHED_SURFACES - 1; i >= 0; i--)
+ {
+ if (cache->cached_surfaces[i])
+ {
+ if (delta > 0)
+ {
+ cache->cached_surfaces[i + delta] =
+ cache->cached_surfaces[i];
+
+ assert (cache->cached_surfaces[i + delta]->id != destroy_id);
+
+ cache->cached_surfaces[i] = NULL;
+ }
+ }
+ else
+ {
+ delta++;
+ }
+ }
+
+ assert (delta > 0);
- push_surface_cmd (qxl, cmd);
+ cache->cached_surfaces[i + delta] = surface;
+
+ for (i = 0; i < N_CACHED_SURFACES; ++i)
+ assert (!cache->cached_surfaces[i] || cache->cached_surfaces[i]->id != destroy_id);
+ /* Note that sending a destroy command can trigger callbacks into
+ * this function (due to memory management), so we have to
+ * do this after updating the cache
+ */
+ if (destroy_surface)
+ send_destroy (destroy_surface);
+
+#if 0
+ ErrorF ("Done\n");
+#endif
+ print_cache_info (cache);
}
}
}
@@ -562,24 +776,7 @@ qxl_surface_destroy (qxl_surface_t *surface)
{
unlink_surface (surface);
- qxl_surface_unref (surface->qxl, surface->id);
-}
-
-void
-qxl_surface_recycle (qxl_screen_t *qxl, uint32_t id)
-{
- qxl_surface_t *surface = qxl->all_surfaces + id;
-
-#if 0
- ErrorF ("recycle %d\n", id);
-#endif
-
-#if 0
- ErrorF ("freeing %p\n", surface->address);
-#endif
- qxl_free (surface->qxl->surf_mem, surface->address);
-
- surface_free (qxl, surface);
+ qxl_surface_unref (surface->cache, surface->id);
}
/* send anything pending to the other side */
@@ -593,7 +790,7 @@ qxl_surface_flush (qxl_surface_t *surface)
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);
+ struct qxl_ram_header *ram_header = get_ram_header (surface->cache->qxl);
ram_header->update_area.top = y1;
ram_header->update_area.bottom = y2;
@@ -606,7 +803,7 @@ download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
ErrorF ("Issuing update command for %d\n", surface->id);
#endif
- outb (surface->qxl->io_base + QXL_IO_UPDATE_AREA, 0);
+ outb (surface->cache->qxl->io_base + QXL_IO_UPDATE_AREA, 0);
pixman_image_composite (PIXMAN_OP_SRC,
surface->dev_image,
@@ -712,7 +909,7 @@ upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
struct qxl_rect rect;
struct qxl_drawable *drawable;
struct qxl_image *image;
- qxl_screen_t *qxl = surface->qxl;
+ qxl_screen_t *qxl = surface->cache->qxl;
uint32_t *data;
int stride;
@@ -779,16 +976,30 @@ qxl_surface_finish_access (qxl_surface_t *surface, PixmapPtr pixmap)
}
void *
-qxl_surface_evacuate_all (qxl_screen_t *qxl)
+qxl_surface_cache_evacuate_all (surface_cache_t *cache)
{
evacuated_surface_t *evacuated_surfaces = NULL;
qxl_surface_t *s;
+ int i;
+
+#if 0
+ ErrorF ("Before evacucate\n");
+#endif
+ print_cache_info (cache);
+ for (i = 0; i < N_CACHED_SURFACES; ++i)
+ {
+ if (cache->cached_surfaces[i])
+ {
+ send_destroy (cache->cached_surfaces[i]);
+ cache->cached_surfaces[i] = NULL;
+ }
+ }
#if 0
ErrorF ("Evacuating all\n");
#endif
- s = qxl->live_surfaces;
+ s = cache->live_surfaces;
while (s != NULL)
{
qxl_surface_t *next = s->next;
@@ -821,23 +1032,31 @@ qxl_surface_evacuate_all (qxl_screen_t *qxl)
s = next;
}
- free (qxl->all_surfaces);
- qxl->all_surfaces = NULL;
- qxl->live_surfaces = NULL;
- qxl->free_surfaces = NULL;
+ free (cache->all_surfaces);
+ cache->all_surfaces = NULL;
+ cache->live_surfaces = NULL;
+ cache->free_surfaces = NULL;
return evacuated_surfaces;
}
void
-qxl_surface_replace_all (qxl_screen_t *qxl, void *data)
+qxl_surface_cache_replace_all (surface_cache_t *cache, void *data)
{
evacuated_surface_t *ev;
#if 0
+ ErrorF ("Before replace\n");
+#endif
+ print_cache_info (cache);
+#if 0
ErrorF ("Replacing all\n");
#endif
- qxl_surface_init (qxl);
+ if (!surface_cache_init (cache, cache->qxl))
+ {
+ /* FIXME: report the error */
+ return;
+ }
ev = data;
while (ev != NULL)
@@ -847,7 +1066,7 @@ qxl_surface_replace_all (qxl_screen_t *qxl, void *data)
int height = pixman_image_get_height (ev->image);
qxl_surface_t *surface;
- surface = qxl_surface_create (qxl, width, height, ev->Bpp * 8);
+ surface = qxl_surface_create (cache, width, height, ev->Bpp * 8);
#if 0
ErrorF ("recreated %d\n", surface->id);
ErrorF ("%d => %p\n", surface->id, ev->pixmap);
@@ -870,7 +1089,7 @@ qxl_surface_replace_all (qxl_screen_t *qxl, void *data)
ev = next;
}
- qxl_surface_sanity_check (qxl);
+ qxl_surface_cache_sanity_check (cache);
}
@@ -923,7 +1142,7 @@ qxl_surface_solid (qxl_surface_t *destination,
int x2,
int y2)
{
- qxl_screen_t *qxl = destination->qxl;
+ qxl_screen_t *qxl = destination->cache->qxl;
struct qxl_rect qrect;
uint32_t p;
@@ -978,7 +1197,7 @@ qxl_surface_copy (qxl_surface_t *dest,
int dest_x1, int dest_y1,
int width, int height)
{
- qxl_screen_t *qxl = dest->qxl;
+ qxl_screen_t *qxl = dest->cache->qxl;
struct qxl_drawable *drawable;
struct qxl_rect qrect;
@@ -1060,7 +1279,7 @@ qxl_surface_put_image (qxl_surface_t *dest,
const char *src, int src_pitch)
{
struct qxl_drawable *drawable;
- qxl_screen_t *qxl = dest->qxl;
+ qxl_screen_t *qxl = dest->cache->qxl;
struct qxl_rect rect;
struct qxl_image *image;