--- 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 _______________________________________________ Spice-devel mailing list Spice-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/spice-devel