[Spice-devel] [spice-protocol PATCH 16/46] qxlhw: qxl_surface: use qxlhw_surface_alloc, qxlhw_surface_free
Alon Levy
alevy at redhat.com
Tue Apr 10 04:50:12 PDT 2012
---
src/qxl.h | 3 ++
src/qxl_surface.c | 46 ++++++------------------------
src/qxlhw.c | 21 ++++++++++++++
src/qxlhw.h | 23 ++++++++++++++-
src/qxlhw_pci.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 137 insertions(+), 38 deletions(-)
diff --git a/src/qxl.h b/src/qxl.h
index d72f64f..03aed28 100644
--- a/src/qxl.h
+++ b/src/qxl.h
@@ -282,6 +282,9 @@ qxl_surface_cache_evacuate_all (surface_cache_t *qxl);
void
qxl_surface_cache_replace_all (surface_cache_t *qxl, void *data);
+void
+qxl_surface_cache_print_info (surface_cache_t *cache);
+
void qxl_surface_set_pixmap (qxl_surface_t *surface,
PixmapPtr pixmap);
/* Call this to indicate that the server is done with the surface */
diff --git a/src/qxl_surface.c b/src/qxl_surface.c
index 96cfb5a..1ce6fe5 100644
--- a/src/qxl_surface.c
+++ b/src/qxl_surface.c
@@ -202,8 +202,8 @@ qxl_surface_cache_sanity_check (surface_cache_t *qxl)
#endif
}
-static void
-print_cache_info (surface_cache_t *cache)
+void
+qxl_surface_cache_print_info (surface_cache_t *cache)
{
int i;
int n_surfaces = 0;
@@ -288,7 +288,7 @@ qxl_surface_recycle (surface_cache_t *cache, uint32_t id)
qxl_surface_t *surface = cache->all_surfaces + id;
n_live--;
- qxl_free (cache->qxl->surf_mem, surface->address);
+ qxlhw_surface_free (cache->qxl->hw, surface->address);
surface->next = cache->free_surfaces;
cache->free_surfaces = surface;
@@ -519,7 +519,6 @@ surface_send_create (surface_cache_t *cache,
struct QXLSurfaceCmd cmd;
int stride;
uint32_t *dev_addr;
- int n_attempts = 0;
qxl_screen_t *qxl = cache->qxl;
qxl_surface_t *surface;
void *address;
@@ -532,35 +531,8 @@ surface_send_create (surface_cache_t *cache,
stride = width * PIXMAN_FORMAT_BPP (pformat) / 8;
stride = (stride + 3) & ~3;
- /* the final + stride is to work around a bug where the device apparently
- * scribbles after the end of the image
- */
qxl_garbage_collect (qxl);
-retry2:
- address = qxl_alloc (qxl->surf_mem, stride * height + stride);
-
- if (!address)
- {
- ErrorF ("- %dth attempt\n", n_attempts++);
-
- if (qxl_garbage_collect (qxl))
- goto retry2;
-
- ErrorF ("- OOM at %d %d %d\n", width, height, bpp);
- print_cache_info (cache);
-
- if (qxlhw_handle_oom (qxl->hw))
- {
- while (qxl_garbage_collect (qxl))
- ;
- goto retry2;
- }
-
- ErrorF ("Out of video memory: Could not allocate %d bytes\n",
- stride * height + stride);
-
- return NULL;
- }
+ address = qxlhw_surface_alloc (qxl->hw, width, height, bpp, stride, pformat);
retry:
surface = surface_get_from_free_list (cache);
@@ -569,16 +541,16 @@ retry:
if (!qxlhw_handle_oom (qxl->hw))
{
ErrorF (" Out of surfaces\n");
- qxl_free (qxl->surf_mem, address);
+ qxlhw_surface_free (qxl->hw, address);
return NULL;
}
else
goto retry;
}
- surface->address = address;
- surface->end = (char *)address + stride * height;
-
+ surface->address = address;
+ surface->end = (char *)surface->address + stride * height;
+
init_surface_cmd (&cmd, cache, surface->id, QXL_SURFACE_CMD_CREATE);
cmd.u.surface_create.format = format;
@@ -586,7 +558,7 @@ retry:
cmd.u.surface_create.height = height;
cmd.u.surface_create.stride = -stride;
- cmd.u.surface_create.data = (QXLPHYSICAL)surface->address;
+ cmd.u.surface_create.data = pointer_to_u64(surface->address);
push_surface_cmd (cache, &cmd);
diff --git a/src/qxlhw.c b/src/qxlhw.c
index 184cd7b..ee25dac 100644
--- a/src/qxlhw.c
+++ b/src/qxlhw.c
@@ -53,11 +53,32 @@ void *qxlhw_data_alloc(struct qxlhw *base, unsigned long size)
return base->data_alloc(base, size);
}
+void qxlhw_data_free(struct qxlhw *base, void *p)
+{
+ base->data_free(base, p);
+}
+
+void *qxlhw_surface_alloc(struct qxlhw *base, int width, int height, int bpp,
+ int stride, pixman_format_code_t pformat)
+{
+ return base->surface_alloc(base, width, height, bpp, stride, pformat);
+}
+
+void qxlhw_surface_free(struct qxlhw *base, void *mem)
+{
+ base->surface_free(base, mem);
+}
+
void qxlhw_create_primary_surface(struct qxlhw *base, QXLSurfaceCreate *create)
{
base->create_primary_surface(base, create);
}
+void qxlhw_push_surface_cmd(struct qxlhw *base, QXLSurfaceCmd* base_cmd)
+{
+ base->push_surface_cmd(base, base_cmd);
+}
+
void qxlhw_update_area(struct qxlhw *base, int surface_id, struct QXLRect rect)
{
base->update_area(base, surface_id, rect);
diff --git a/src/qxlhw.h b/src/qxlhw.h
index 730a623..3b950e4 100644
--- a/src/qxlhw.h
+++ b/src/qxlhw.h
@@ -19,7 +19,11 @@ struct qxlhw {
/* memory handling callbacks */
void *(*data_alloc)(struct qxlhw *base, unsigned long size);
void (*data_free)(struct qxlhw *base, void *p);
+ void *(*surface_alloc)(struct qxlhw *base, int width, int height, int bpp,
+ int stride, pixman_format_code_t pformat);
+ void (*surface_free)(struct qxlhw *base, void *mem);
void (*create_primary_surface)(struct qxlhw *base, QXLSurfaceCreate *create);
+ void (*push_surface_cmd)(struct qxlhw *base, QXLSurfaceCmd* base_cmd);
void (*update_area)(struct qxlhw *base, int surface_id, struct QXLRect rect);
void (*push_cursor)(struct qxlhw *base, struct QXLCursorCmd *base_cmd);
/* tried to avoid this. but qxl_surface.c wants to check when failing to
@@ -35,7 +39,6 @@ void qxlhw_init(struct qxlhw *base, qxl_screen_t *qxl);
struct qxlhw *qxlhw_create(qxl_screen_t *qxl, ScrnInfoPtr pScrn);
void qxlhw_update_area(struct qxlhw *base, int surface_id, struct QXLRect rect);
-void qxlhw_create_primary_surface(struct qxlhw *base, QXLSurfaceCreate *create);
/* reset vs device_reset - device_reset is just the io / drm call,
* reset does -- what? (definition, not contents) */
@@ -52,8 +55,26 @@ void qxlhw_unmap_memory(struct qxlhw *base, int scrnIndex);
void *qxlhw_data_alloc(struct qxlhw *base, unsigned long size);
void qxlhw_data_free(struct qxlhw *base, void *p);
+/* not sure if we want this in the future, but for now mark differently
+ * surface allocations then other "data" allocations */
+void *qxlhw_surface_alloc(struct qxlhw *base, int width, int height, int bpp,
+ int stride, pixman_format_code_t pformat);
+void qxlhw_surface_free(struct qxlhw *base, void *mem);
+
Bool qxlhw_handle_oom(struct qxlhw *base);
+/* primary surface. keep it seperate
+ *
+ * On entry:
+ * create->mem is ignored, since it's always pointing to the start
+ * of the main bar anyway. So we can hide the details in qxlhw.
+ */
+void qxlhw_create_primary_surface(struct qxlhw *base, QXLSurfaceCreate *create);
+
+/* note that allocation of these commands is completely in qxlhw_pci.c,
+ * and not visible in qxl_surface.c */
+void qxlhw_push_surface_cmd(struct qxlhw *base, QXLSurfaceCmd *base_cmd);
+
/* cursor */
void qxlhw_push_cursor(struct qxlhw *base, QXLCursorCmd *base_cmd);
diff --git a/src/qxlhw_pci.c b/src/qxlhw_pci.c
index d4b34c2..b3fae49 100644
--- a/src/qxlhw_pci.c
+++ b/src/qxlhw_pci.c
@@ -570,6 +570,52 @@ static void qxlhw_pci_data_free(struct qxlhw *base, void *p)
qxl_free (hw->mem, p);
}
+static void *qxlhw_pci_surface_alloc(struct qxlhw *base, int width, int height,
+ int bpp, int stride, pixman_format_code_t pformat)
+{
+ struct qxlhw_pci *hw = (struct qxlhw_pci *)base;
+ void *addr = NULL;
+ int n_attempts = 0;
+ /* the final + stride is to work around a bug where the device apparently
+ * scribbles after the end of the image
+ */
+ int size = stride * height + stride;
+
+ qxlhw_pci_flush_release_ring (hw);
+retry:
+ addr = qxlhw_pci_allocnf(hw, hw->surf_mem, size);
+ if (!addr)
+ {
+ ErrorF ("- %dth attempt\n", n_attempts++);
+
+ if (qxlhw_pci_flush_release_ring (hw))
+ goto retry;
+
+ ErrorF ("- OOM at %d %d %d\n", width, height, bpp);
+ qxl_surface_cache_print_info (base->qxl->surface_cache);
+
+ if (qxlhw_pci_handle_oom (hw))
+ {
+ while (qxlhw_pci_flush_release_ring (hw))
+ ;
+ goto retry;
+ }
+
+ ErrorF ("Out of video memory: Could not allocate %d bytes\n",
+ stride * height + stride);
+
+ return addr;
+ }
+ return addr;
+}
+
+static void qxlhw_pci_surface_free(struct qxlhw *base, void *mem)
+{
+ struct qxlhw_pci *hw = (struct qxlhw_pci *)base;
+
+ qxl_free (hw->surf_mem, mem);
+}
+
static void qxlhw_pci_create_primary_surface(struct qxlhw *base, QXLSurfaceCreate *create)
{
struct qxlhw_pci *hw = (struct qxlhw_pci *)base;
@@ -595,6 +641,39 @@ static void qxlhw_pci_create_primary_surface(struct qxlhw *base, QXLSurfaceCreat
#endif
}
+static struct QXLSurfaceCmd *
+make_surface_cmd (struct qxlhw_pci *hw, QXLSurfaceCmd *base)
+{
+ struct QXLSurfaceCmd *cmd;
+
+ qxlhw_pci_flush_release_ring (hw);
+
+ cmd = qxlhw_pci_allocnf (hw, hw->mem, sizeof *cmd);
+
+ memcpy(cmd, base, sizeof(*cmd));
+ cmd->release_info.id = pointer_to_u64 (cmd) | 2;
+ if (cmd->type == QXL_SURFACE_CMD_CREATE) {
+ cmd->u.surface_create.data =
+ qxlhw_physical_address (hw, (void *)cmd->u.surface_create.data,
+ hw->vram_mem_slot);
+ }
+
+ return cmd;
+}
+
+static void
+qxlhw_pci_push_surface_cmd (struct qxlhw *base, struct QXLSurfaceCmd *base_cmd)
+{
+ struct qxlhw_pci *hw = (struct qxlhw_pci *)base;
+ struct QXLSurfaceCmd *cmd = make_surface_cmd(hw, base_cmd);
+ struct QXLCommand command;
+
+ command.type = QXL_CMD_SURFACE;
+ command.data = qxlhw_physical_address (hw, cmd, hw->main_mem_slot);
+
+ qxl_ring_push (hw->command_ring, &command);
+}
+
static void qxlhw_pci_update_area(struct qxlhw *base, int surface_id, struct QXLRect rect)
{
struct qxlhw_pci *hw = (struct qxlhw_pci *)base;
@@ -664,6 +743,9 @@ struct qxlhw *create_qxlhw_pci(qxl_screen_t *qxl, ScrnInfoPtr pScrn)
base->data_alloc = qxlhw_pci_data_alloc;
base->data_free = qxlhw_pci_data_free;
base->create_primary_surface = qxlhw_pci_create_primary_surface;
+ base->surface_alloc = qxlhw_pci_surface_alloc;
+ base->surface_free = qxlhw_pci_surface_free;
+ base->push_surface_cmd = qxlhw_pci_push_surface_cmd;
base->update_area = qxlhw_pci_update_area;
base->push_cursor = qxlhw_pci_push_cursor;
return base;
--
1.7.9.3
More information about the Spice-devel
mailing list