[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