[Spice-devel] [PATCH 9/9] qxl: abstract object allocation away from surface/image/cursor code
Alon Levy
alevy at redhat.com
Tue Feb 26 09:07:05 PST 2013
On Tue, Feb 26, 2013 at 02:32:12PM +1000, Dave Airlie wrote:
ACK all the patches above, ACK this one too with small nit picks.
Did not break xspice :)
Regarding application of patches - I had to manually merge but the
merges were the trivial ones so probably some whitespace? so if you
manage to push then it is fine.
> This abstracts the object bo/surface allocation away from the user code.
>
> The idea is we can then plug in a KMS backend for this abstraction and mostly
> keep the surrounding code intact.
>
> This is probably the biggest change to the driver in terms of impact of KMS
> code on UMS code. At the moment I'm storing linked list of bos for release
> handling, and that might be better done with a different data structure,
> since we are looking them up by phy_addr, either a hash table or some sort
> of rb tree perhaps, rather than a linear search.
>
> This commit also starts usign the xorg list macros, which may require
> some compat code to work in history.
>
> Signed-off-by: Dave Airlie <airlied at redhat.com>
> ---
> src/qxl.h | 52 +++++++--
> src/qxl_cursor.c | 52 +++++----
> src/qxl_driver.c | 8 +-
> src/qxl_image.c | 69 +++++++----
> src/qxl_mem.c | 343 +++++++++++++++++++++++++++++++++++++++++++++++++-----
> src/qxl_surface.c | 302 +++++++++++++++++++++++++----------------------
> src/qxl_surface.h | 4 +-
> src/qxl_uxa.c | 6 +-
> 8 files changed, 605 insertions(+), 231 deletions(-)
>
> diff --git a/src/qxl.h b/src/qxl.h
> index 2d1840a..9eb249c 100644
> --- a/src/qxl.h
> +++ b/src/qxl.h
> @@ -45,6 +45,7 @@
> #include "micmap.h"
> #include "uxa/uxa.h"
>
> +#include "list.h"
> #ifndef XSPICE
> #ifdef XSERVER_PCIACCESS
> #include "pciaccess.h"
> @@ -139,6 +140,42 @@ enum {
> QXL_DEVICE_PRIMARY_CREATED,
> };
>
> +struct qxl_bo;
> +/*
> + * for relocations
> + * dst_bo + dst_offset are the bo and offset into it the reloc is being written,
s/it/which/
> + * src_bo is the bo who's offset is being relocated.
> + */
> +struct qxl_bo_funcs {
> + struct qxl_bo *(*bo_alloc)(qxl_screen_t *qxl, unsigned long size, const char *name);
> + struct qxl_bo *(*cmd_alloc)(qxl_screen_t *qxl, unsigned long size, const char *name);
> + void *(*bo_map)(struct qxl_bo *bo);
> + void (*bo_unmap)(struct qxl_bo *bo);
> + void (*bo_decref)(qxl_screen_t *qxl, struct qxl_bo *bo);
> + void (*bo_incref)(qxl_screen_t *qxl, struct qxl_bo *bo);
> + void (*bo_output_bo_reloc)(qxl_screen_t *qxl, uint32_t dst_offset,
> + struct qxl_bo *dst_bo, struct qxl_bo *src_bo);
> + void (*write_command)(qxl_screen_t *qxl, uint32_t type, struct qxl_bo *bo);
> + void (*update_area)(qxl_surface_t *surf, int x1, int y1, int x2, int y2);
> + struct qxl_bo *(*create_primary)(qxl_screen_t *qxl, uint32_t width, uint32_t height, int32_t stride, uint32_t format);
> + void (*destroy_primary)(qxl_screen_t *qxl, struct qxl_bo *primary_bo);
> +
> + qxl_surface_t *(*create_surface)(qxl_screen_t *qxl, int width,
> + int height, int bpp);
> + void (*destroy_surface)(qxl_surface_t *surf);
> +
> + void (*bo_output_surf_reloc)(qxl_screen_t *qxl, uint32_t dst_offset,
> + struct qxl_bo *dst_bo,
> + qxl_surface_t *surf);
> + /* surface create / destroy */
> +};
> +
> +void qxl_ums_setup_funcs(qxl_screen_t *qxl);
> +
> +/* ums specific functions */
> +struct qxl_bo *qxl_ums_surf_mem_alloc(qxl_screen_t *qxl, uint32_t size);
> +struct qxl_bo *qxl_ums_lookup_phy_addr(qxl_screen_t *qxl, uint64_t phy_addr);
> +
> struct _qxl_screen_t
> {
> /* These are the names QXL uses */
> @@ -153,7 +190,7 @@ struct _qxl_screen_t
> struct qxl_ring * release_ring;
>
> int device_primary;
> -
> + struct qxl_bo * primary_bo;
> int num_modes;
> struct QXLMode * modes;
> int io_base;
> @@ -268,6 +305,9 @@ struct _qxl_screen_t
>
> uint32_t deferred_fps;
> #endif /* XSPICE */
> +
> + struct xorg_list ums_bos;
> + struct qxl_bo_funcs *bo_funcs;
> };
>
> typedef struct qxl_output_private {
> @@ -461,7 +501,7 @@ void qxl_allocate_monitors_config (qxl_screen_t *qxl);
> /*
> * Images
> */
> -struct QXLImage *qxl_image_create (qxl_screen_t *qxl,
> +struct qxl_bo *qxl_image_create (qxl_screen_t *qxl,
> const uint8_t *data,
> int x,
> int y,
> @@ -471,7 +511,7 @@ struct QXLImage *qxl_image_create (qxl_screen_t *qxl,
> int Bpp,
> Bool fallback);
> void qxl_image_destroy (qxl_screen_t *qxl,
> - struct QXLImage *image);
> + struct qxl_bo *bo);
> void qxl_drop_image_cache (qxl_screen_t *qxl);
>
>
> @@ -484,12 +524,6 @@ struct qxl_mem * qxl_mem_create (void *base,
> unsigned long n_bytes);
> void qxl_mem_dump_stats (struct qxl_mem *mem,
> const char *header);
> -void * qxl_alloc (struct qxl_mem *mem,
> - unsigned long n_bytes,
> - const char * name);
> -void qxl_free (struct qxl_mem *mem,
> - void *d,
> - const char * name);
> void qxl_mem_free_all (struct qxl_mem *mem);
> void * qxl_allocnf (qxl_screen_t *qxl,
> unsigned long size,
> diff --git a/src/qxl_cursor.c b/src/qxl_cursor.c
> index 459cbd7..d246594 100644
> --- a/src/qxl_cursor.c
> +++ b/src/qxl_cursor.c
> @@ -32,36 +32,29 @@
> #include <cursorstr.h>
>
> static void
> -push_cursor (qxl_screen_t *qxl, struct QXLCursorCmd *cursor)
> +push_cursor (qxl_screen_t *qxl, struct qxl_bo *cursor_bo)
> {
> - struct QXLCommand cmd;
> -
> - /* See comment on push_command() in qxl_driver.c */
> - if (qxl->pScrn->vtSema)
> - {
> - cmd.type = QXL_CMD_CURSOR;
> - cmd.data = physical_address (qxl, cursor, qxl->main_mem_slot);
> -
> - qxl_ring_push (qxl->cursor_ring, &cmd);
> - }
> + qxl->bo_funcs->write_command (qxl, QXL_CMD_CURSOR, cursor_bo);
> }
>
> -static struct QXLCursorCmd *
> +static struct qxl_bo *
> qxl_alloc_cursor_cmd(qxl_screen_t *qxl)
> {
> - struct QXLCursorCmd *cmd =
> - qxl_allocnf (qxl, sizeof(struct QXLCursorCmd), "cursor command");
> + struct qxl_bo *bo = qxl->bo_funcs->cmd_alloc (qxl, sizeof(struct QXLCursorCmd), "cursor command");
> + struct QXLCursorCmd *cmd = qxl->bo_funcs->bo_map(bo);
>
> - cmd->release_info.id = pointer_to_u64 (cmd) | 1;
> + cmd->release_info.id = pointer_to_u64 (bo) | 1;
>
> - return cmd;
> + qxl->bo_funcs->bo_unmap(bo);
> + return bo;
> }
>
> static void
> qxl_set_cursor_position(ScrnInfoPtr pScrn, int x, int y)
> {
> qxl_screen_t *qxl = pScrn->driverPrivate;
> - struct QXLCursorCmd *cmd = qxl_alloc_cursor_cmd(qxl);
> + struct qxl_bo *cmd_bo = qxl_alloc_cursor_cmd(qxl);
> + struct QXLCursorCmd *cmd = qxl->bo_funcs->bo_map(cmd_bo);
>
> qxl->cur_x = x;
> qxl->cur_y = y;
> @@ -70,7 +63,8 @@ qxl_set_cursor_position(ScrnInfoPtr pScrn, int x, int y)
> cmd->u.position.x = qxl->cur_x + qxl->hot_x;
> cmd->u.position.y = qxl->cur_y + qxl->hot_y;
>
> - push_cursor(qxl, cmd);
> + qxl->bo_funcs->bo_unmap(cmd_bo);
> + push_cursor(qxl, cmd_bo);
> }
>
> static void
> @@ -92,9 +86,10 @@ qxl_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs)
> int h = pCurs->bits->height;
> int size = w * h * sizeof (CARD32);
>
> - struct QXLCursorCmd *cmd = qxl_alloc_cursor_cmd (qxl);
> - struct QXLCursor *cursor =
> - qxl_allocnf(qxl, sizeof(struct QXLCursor) + size, "cursor data");
> + struct qxl_bo *cmd_bo = qxl_alloc_cursor_cmd(qxl);
> + struct QXLCursorCmd *cmd;
> + struct qxl_bo *cursor_bo = qxl->bo_funcs->bo_alloc(qxl, sizeof(struct QXLCursor) + size, "cursor data");
> + struct QXLCursor *cursor = qxl->bo_funcs->bo_map(cursor_bo);
>
> cursor->header.unique = 0;
> cursor->header.type = SPICE_CURSOR_TYPE_ALPHA;
> @@ -128,16 +123,21 @@ qxl_load_cursor_argb (ScrnInfoPtr pScrn, CursorPtr pCurs)
> }
> #endif
>
> + qxl->bo_funcs->bo_unmap(cursor_bo);
> +
> qxl->hot_x = pCurs->bits->xhot;
> qxl->hot_y = pCurs->bits->yhot;
>
> + cmd = qxl->bo_funcs->bo_map(cmd_bo);
> cmd->type = QXL_CURSOR_SET;
> cmd->u.set.position.x = qxl->cur_x + qxl->hot_x;
> cmd->u.set.position.y = qxl->cur_y + qxl->hot_y;
> - cmd->u.set.shape = physical_address (qxl, cursor, qxl->main_mem_slot);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(struct QXLCursorCmd, u.set.shape), cmd_bo, cursor_bo);
> +
> cmd->u.set.visible = TRUE;
> + qxl->bo_funcs->bo_unmap(cmd_bo);
>
> - push_cursor(qxl, cmd);
> + push_cursor(qxl, cmd_bo);
> }
>
> static Bool
> @@ -159,11 +159,13 @@ static void
> qxl_hide_cursor(ScrnInfoPtr pScrn)
> {
> qxl_screen_t *qxl = pScrn->driverPrivate;
> - struct QXLCursorCmd *cursor = qxl_alloc_cursor_cmd(qxl);
> + struct qxl_bo *cmd_bo = qxl_alloc_cursor_cmd(qxl);
> + struct QXLCursorCmd *cursor = qxl->bo_funcs->bo_map(cmd_bo);
>
> cursor->type = QXL_CURSOR_HIDE;
>
> - push_cursor(qxl, cursor);
> + qxl->bo_funcs->bo_unmap(cmd_bo);
> + push_cursor(qxl, cmd_bo);
> }
>
> static void
> diff --git a/src/qxl_driver.c b/src/qxl_driver.c
> index 21bac83..b2f803b 100644
> --- a/src/qxl_driver.c
> +++ b/src/qxl_driver.c
> @@ -523,7 +523,7 @@ qxl_resize_primary_to_virtual (qxl_screen_t *qxl)
> {
> qxl_surface_kill (qxl->primary);
> qxl_surface_cache_sanity_check (qxl->surface_cache);
> - qxl_io_destroy_primary (qxl);
> + qxl->bo_funcs->destroy_primary(qxl, qxl->primary_bo);
> }
>
> qxl->primary = qxl_create_primary(qxl);
> @@ -1034,7 +1034,9 @@ qxl_pre_init (ScrnInfoPtr pScrn, int flags)
> qxl->pScrn = pScrn;
> qxl->x_modes = NULL;
> qxl->entity = xf86GetEntityInfo (pScrn->entityList[0]);
> -
> +
> + xorg_list_init(&qxl->ums_bos);
> +
> #ifndef XSPICE
> qxl->pci = xf86GetPciInfoForEntity (qxl->entity->index);
> #ifndef XSERVER_LIBPCIACCESS
> @@ -1047,6 +1049,8 @@ qxl_pre_init (ScrnInfoPtr pScrn, int flags)
> #endif /* XSPICE */
> pScrn->monitor = pScrn->confScreen->monitor;
>
> + qxl_ums_setup_funcs(qxl);
> +
> if (!qxl_pre_init_common(pScrn))
> goto out;
>
> diff --git a/src/qxl_image.c b/src/qxl_image.c
> index fcecf8a..85e2455 100644
> --- a/src/qxl_image.c
> +++ b/src/qxl_image.c
> @@ -128,7 +128,7 @@ remove_image_info (image_info_t *info)
> #define MAX(a,b) (((a) > (b))? (a) : (b))
> #define MIN(a,b) (((a) < (b))? (a) : (b))
>
> -struct QXLImage *
> +struct qxl_bo *
> qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
> int x, int y, int width, int height,
> int stride, int Bpp, Bool fallback)
> @@ -136,8 +136,9 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
> uint32_t hash;
> image_info_t *info;
> struct QXLImage *image;
> - struct QXLDataChunk *head;
> + struct qxl_bo *head_bo, *tail_bo;
> struct QXLDataChunk *tail;
> + struct qxl_bo *image_bo;
> int dest_stride = (width * Bpp + 3) & (~3);
> int h;
>
> @@ -151,7 +152,7 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
>
> /* FIXME: Check integer overflow */
>
> - head = tail = NULL;
> + head_bo = tail_bo = NULL;
>
> hash = 0;
> h = height;
> @@ -159,35 +160,42 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
> {
> int chunk_size = MAX (512 * 512, dest_stride);
> int n_lines = MIN ((chunk_size / dest_stride), h);
> - QXLDataChunk *chunk =
> - qxl_allocnf (qxl, sizeof *chunk + n_lines * dest_stride, "image data");
> + struct qxl_bo *bo = qxl->bo_funcs->bo_alloc (qxl, sizeof (QXLDataChunk) + n_lines * dest_stride, "image data");
>
> + QXLDataChunk *chunk = qxl->bo_funcs->bo_map(bo);
> chunk->data_size = n_lines * dest_stride;
> hash = hash_and_copy (data, stride,
> chunk->data, dest_stride,
> Bpp, width, n_lines, hash);
>
> - if (tail)
> + if (tail_bo)
> {
> - tail->next_chunk = physical_address (qxl, chunk, qxl->main_mem_slot);
> - chunk->prev_chunk = physical_address (qxl, tail, qxl->main_mem_slot);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDataChunk, next_chunk),
> + tail_bo, bo);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDataChunk, prev_chunk),
> + bo, tail_bo);
> +
> chunk->next_chunk = 0;
>
> - tail = chunk;
> + tail_bo = bo;
> }
> else
> {
> - head = tail = chunk;
> + head_bo = tail_bo = bo;
> chunk->next_chunk = 0;
> chunk->prev_chunk = 0;
> }
>
> + qxl->bo_funcs->bo_unmap(bo);
> + if (bo != head_bo)
> + qxl->bo_funcs->bo_decref(qxl, bo);
> data += n_lines * stride;
> h -= n_lines;
> }
>
> /* Image */
> - image = qxl_allocnf (qxl, sizeof *image, "image struct");
> + image_bo = qxl->bo_funcs->bo_alloc (qxl, sizeof *image, "image struct");
> + image = qxl->bo_funcs->bo_map(image_bo);
>
> image->descriptor.id = 0;
> image->descriptor.type = SPICE_IMAGE_TYPE_BITMAP;
> @@ -218,8 +226,10 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
> image->bitmap.y = height;
> image->bitmap.stride = dest_stride;
> image->bitmap.palette = 0;
> - image->bitmap.data = physical_address (qxl, head, qxl->main_mem_slot);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLImage, bitmap.data),
> + image_bo, head_bo);
>
> + qxl->bo_funcs->bo_decref(qxl, head_bo);
> /* Add to hash table if caching is enabled */
> if ((fallback && qxl->enable_fallback_cache) ||
> (!fallback && qxl->enable_image_cache))
> @@ -238,20 +248,24 @@ qxl_image_create (qxl_screen_t *qxl, const uint8_t *data,
> }
> }
>
> - return image;
> + qxl->bo_funcs->bo_unmap(image_bo);
> + return image_bo;
> }
>
> void
> qxl_image_destroy (qxl_screen_t *qxl,
> - struct QXLImage *image)
> + struct qxl_bo *image_bo)
> {
> + struct QXLImage *image;
> +
> image_info_t *info;
> - uint64_t chunk;
> + uint64_t chunk, prev_chunk;
>
> + image = qxl->bo_funcs->bo_map(image_bo);
> info = lookup_image_info (image->descriptor.id,
> image->descriptor.width,
> image->descriptor.height);
> -
> + qxl->bo_funcs->bo_unmap(image_bo);
> if (info && info->image == image)
> {
> --info->ref_count;
> @@ -266,20 +280,29 @@ qxl_image_destroy (qxl_screen_t *qxl,
> remove_image_info (info);
> }
>
> -
> + image = qxl->bo_funcs->bo_map(image_bo);
> chunk = image->bitmap.data;
> while (chunk)
> {
> + struct qxl_bo *bo;
> struct QXLDataChunk *virtual;
>
> - virtual = virtual_address (qxl, u64_to_pointer (chunk), qxl->main_mem_slot);
> -
> + bo = qxl_ums_lookup_phy_addr(qxl, chunk);
> + assert(bo);
> + virtual = qxl->bo_funcs->bo_map(bo);
> chunk = virtual->next_chunk;
> -
> - qxl_free (qxl->mem, virtual, "image data");
> + prev_chunk = virtual->prev_chunk;
> +
> + qxl->bo_funcs->bo_unmap(bo);
> + qxl->bo_funcs->bo_decref (qxl, bo);
> + if (prev_chunk) {
> + bo = qxl_ums_lookup_phy_addr(qxl, prev_chunk);
> + assert(bo);
> + qxl->bo_funcs->bo_decref (qxl, bo);
> + }
> }
> -
> - qxl_free (qxl->mem, image, "image struct");
> + qxl->bo_funcs->bo_unmap(image_bo);
> + qxl->bo_funcs->bo_decref (qxl, image_bo);
> }
>
> void
> diff --git a/src/qxl_mem.c b/src/qxl_mem.c
> index 0f80581..a2d4132 100644
> --- a/src/qxl_mem.c
> +++ b/src/qxl_mem.c
> @@ -32,10 +32,19 @@
> #include "qxl.h"
> #include "mspace.h"
>
> +#include "qxl_surface.h"
> #ifdef DEBUG_QXL_MEM
> #include <valgrind/memcheck.h>
> #endif
>
> +#define QXL_BO_DATA 1
> +#define QXL_BO_SURF 2
> +#define QXL_BO_CMD 4
> +#define QXL_BO_SURF_PRIMARY 8
> +
> +#define QXL_BO_FLAG_FAIL 1
> +
> +
> struct qxl_mem
> {
> mspace space;
> @@ -124,7 +133,7 @@ qxl_mem_dump_stats (struct qxl_mem *mem,
> mspace_malloc_stats (mem->space);
> }
>
> -void *
> +static void *
> qxl_alloc (struct qxl_mem *mem,
> unsigned long n_bytes,
> const char *name)
> @@ -140,7 +149,7 @@ qxl_alloc (struct qxl_mem *mem,
> return addr;
> }
>
> -void
> +static void
> qxl_free (struct qxl_mem *mem,
> void *d,
> const char * name)
> @@ -174,7 +183,6 @@ qxl_mem_free_all (struct qxl_mem *mem)
> mem->space = create_mspace_with_base (mem->base, mem->n_bytes, 0, NULL);
> }
>
> -
> static uint8_t
> setup_slot (qxl_screen_t *qxl, uint8_t slot_index_offset,
> unsigned long start_phys_addr, unsigned long end_phys_addr,
> @@ -265,13 +273,15 @@ qxl_garbage_collect_internal (qxl_screen_t *qxl, uint64_t id)
> */
> #define POINTER_MASK ((1 << 2) - 1)
>
> - union QXLReleaseInfo *info = u64_to_pointer (id & ~POINTER_MASK);
> + struct qxl_bo *info_bo = (struct qxl_bo *)(id & ~POINTER_MASK);
> + union QXLReleaseInfo *info = qxl->bo_funcs->bo_map(info_bo);
> struct QXLCursorCmd *cmd = (struct QXLCursorCmd *)info;
> struct QXLDrawable *drawable = (struct QXLDrawable *)info;
> struct QXLSurfaceCmd *surface_cmd = (struct QXLSurfaceCmd *)info;
> int is_cursor = FALSE;
> int is_surface = FALSE;
> int is_drawable = FALSE;
> + struct qxl_bo *to_free;
>
> if ((id & POINTER_MASK) == 1)
> is_cursor = TRUE;
> @@ -282,43 +292,42 @@ qxl_garbage_collect_internal (qxl_screen_t *qxl, uint64_t id)
>
> if (is_cursor && cmd->type == QXL_CURSOR_SET)
> {
> - struct QXLCursor *cursor = (void *)virtual_address (
> - qxl, u64_to_pointer (cmd->u.set.shape), qxl->main_mem_slot);
> -
> - qxl_free (qxl->mem, cursor, "cursor image");
> + to_free = qxl_ums_lookup_phy_addr(qxl, cmd->u.set.shape);
> + qxl->bo_funcs->bo_decref (qxl, to_free);
> }
> else if (is_drawable && drawable->type == QXL_DRAW_COPY)
> {
> - struct QXLImage *image = virtual_address (
> - qxl, u64_to_pointer (drawable->u.copy.src_bitmap), qxl->main_mem_slot);
> + struct QXLImage *image;
> +
> + to_free = qxl_ums_lookup_phy_addr(qxl, drawable->u.copy.src_bitmap);
> + image = qxl->bo_funcs->bo_map(to_free);
>
> if (image->descriptor.type == SPICE_IMAGE_TYPE_SURFACE)
> {
> qxl_surface_unref (qxl->surface_cache, image->surface_image.surface_id);
> qxl_surface_cache_sanity_check (qxl->surface_cache);
> - qxl_free (qxl->mem, image, "surface image");
> + qxl->bo_funcs->bo_unmap(to_free);
> + qxl->bo_funcs->bo_decref (qxl, to_free);
> }
> else
> {
> - qxl_image_destroy (qxl, image);
> + qxl->bo_funcs->bo_unmap(to_free);
> + qxl_image_destroy (qxl, to_free);
> }
> }
> else if (is_drawable && drawable->type == QXL_DRAW_COMPOSITE)
> {
> - struct QXLTransform *src_trans, *mask_trans;
> - struct QXLImage *src_img, *mask_img;
> + struct qxl_bo *bo;
> struct QXLComposite *composite = &drawable->u.composite;
>
> /* Source */
> - src_img = virtual_address (
> - qxl, u64_to_pointer (drawable->u.composite.src), qxl->main_mem_slot);
> - qxl_free (qxl->mem, src_img, "image struct");
> + bo = qxl_ums_lookup_phy_addr(qxl, drawable->u.composite.src);
> + qxl->bo_funcs->bo_decref (qxl, bo);
>
> if (composite->src_transform)
> {
> - src_trans = virtual_address (
> - qxl, u64_to_pointer (composite->src_transform), qxl->main_mem_slot);
> - qxl_free (qxl->mem, src_trans, "transform");
> + bo = qxl_ums_lookup_phy_addr(qxl, composite->src_transform);
> + qxl->bo_funcs->bo_decref (qxl, bo);
> }
>
> /* Mask */
> @@ -326,15 +335,11 @@ qxl_garbage_collect_internal (qxl_screen_t *qxl, uint64_t id)
> {
> if (drawable->u.composite.mask_transform)
> {
> - mask_trans = virtual_address (
> - qxl, u64_to_pointer (drawable->u.composite.mask_transform), qxl->main_mem_slot);
> -
> - qxl_free (qxl->mem, mask_trans, "transform");
> + bo = qxl_ums_lookup_phy_addr(qxl, drawable->u.composite.mask_transform);
> + qxl->bo_funcs->bo_decref (qxl, bo);
> }
> -
> - mask_img = virtual_address (
> - qxl, u64_to_pointer (drawable->u.composite.mask), qxl->main_mem_slot);
> - qxl_free (qxl->mem, mask_img, "image struct");
> + bo = qxl_ums_lookup_phy_addr(qxl, drawable->u.composite.mask);
> + qxl->bo_funcs->bo_decref (qxl, bo);
> }
> }
> else if (is_surface && surface_cmd->type == QXL_SURFACE_CMD_DESTROY)
> @@ -345,7 +350,8 @@ qxl_garbage_collect_internal (qxl_screen_t *qxl, uint64_t id)
>
> id = info->next;
>
> - qxl_free (qxl->mem, info, "command");
> + qxl->bo_funcs->bo_unmap(info_bo);
> + qxl->bo_funcs->bo_decref(qxl, info_bo);
>
> return id;
> }
> @@ -433,3 +439,282 @@ qxl_allocnf (qxl_screen_t *qxl, unsigned long size, const char *name)
>
> return result;
> }
> +
> +struct qxl_ums_bo {
> + void *virt_addr;
> + const char *name;
> + int type;
> + uint32_t size;
> + void *internal_virt_addr;
> + int refcnt;
> + qxl_screen_t *qxl;
> + struct xorg_list bos;
> +};
> +
> +static struct qxl_bo *qxl_bo_alloc_internal(qxl_screen_t *qxl, int type, int flags, unsigned long size, const char *name)
> +{
> + struct qxl_ums_bo *bo;
> + struct qxl_mem *mptr;
> +
> + bo = calloc(1, sizeof(struct qxl_ums_bo));
> + if (!bo)
> + return NULL;
> +
> + bo->size = size;
> + bo->name = name;
> + bo->type = type;
> + bo->qxl = qxl;
> + bo->refcnt = 1;
> + if (type == QXL_BO_SURF)
> + mptr = qxl->surf_mem;
> + else
> + mptr = qxl->mem;
> +
> + if (flags & QXL_BO_FLAG_FAIL) {
> + bo->internal_virt_addr = qxl_alloc(mptr, size, name);
> + if (!bo->internal_virt_addr) {
> + free(bo);
> + return NULL;
> + }
> + } else
> + bo->internal_virt_addr = qxl_allocnf(qxl, size, name);
> +
> + if (type != QXL_BO_SURF) {
> + xorg_list_add(&bo->bos, &qxl->ums_bos);
> + }
> + return (struct qxl_bo *)bo;
> +}
> +
> +static struct qxl_bo *qxl_bo_alloc(qxl_screen_t *qxl, unsigned long size, const char *name)
> +{
> + return qxl_bo_alloc_internal(qxl, QXL_BO_DATA, 0, size, name);
> +}
> +
> +static struct qxl_bo *qxl_cmd_alloc(qxl_screen_t *qxl, unsigned long size, const char *name)
> +{
> + return qxl_bo_alloc_internal(qxl, QXL_BO_CMD, 0, size, name);
> +}
> +
> +static void *qxl_bo_map(struct qxl_bo *_bo)
> +{
> + struct qxl_ums_bo *bo = (struct qxl_ums_bo *)_bo;
> + if (bo->virt_addr)
> + ErrorF("recursive map %p\n", bo);
> + bo->virt_addr = bo->internal_virt_addr;
> + return bo->virt_addr;
> +}
> +
> +static void qxl_bo_unmap(struct qxl_bo *_bo)
> +{
> + struct qxl_ums_bo *bo = (struct qxl_ums_bo *)_bo;
> + if (!bo->virt_addr)
> + ErrorF("unbalanced unmap %p\n", bo);
> + bo->virt_addr = NULL;
> +}
> +
> +static void qxl_bo_output_bo_reloc(qxl_screen_t *qxl, uint32_t dst_offset,
> + struct qxl_bo *_dst_bo,
> + struct qxl_bo *_src_bo)
> +{
> + struct qxl_ums_bo *src_bo = (struct qxl_ums_bo *)_src_bo;
> + struct qxl_ums_bo *dst_bo = (struct qxl_ums_bo *)_dst_bo;
> + uint8_t slot_id;
> + uint64_t value;
> +
> + /* take a refernce on the bo */
> + src_bo->refcnt++;
> +
> + slot_id = src_bo->type == QXL_BO_SURF ? qxl->vram_mem_slot : qxl->main_mem_slot;
> + value = physical_address(qxl, src_bo->internal_virt_addr, slot_id);
> +
> + *(uint64_t *)((char *)dst_bo->internal_virt_addr + dst_offset) = value;
> +}
> +
> +static void qxl_bo_output_cmd_reloc(qxl_screen_t *qxl, QXLCommand *command,
> + struct qxl_bo *_src_bo)
> +{
> + struct qxl_ums_bo *src_bo = (struct qxl_ums_bo *)_src_bo;
> + uint64_t value;
> + uint8_t slot_id;
> +
> + src_bo->refcnt++;
> +
> + slot_id = src_bo->type == QXL_BO_SURF ? qxl->vram_mem_slot : qxl->main_mem_slot;
> + value = physical_address(qxl, src_bo->internal_virt_addr, slot_id);
> +
> + command->data = value;
> +}
> +
> +struct qxl_bo *qxl_ums_lookup_phy_addr(qxl_screen_t *qxl, uint64_t phy_addr)
> +{
> + struct qxl_ums_bo *bo, *found = NULL;
> + uint8_t slot_id;
> + void *virt_addr;
> +
> + slot_id = qxl->main_mem_slot;
> + virt_addr = (void *)virtual_address(qxl, u64_to_pointer(phy_addr), slot_id);
> +
> + xorg_list_for_each_entry(bo, &qxl->ums_bos, bos) {
> + if (bo->internal_virt_addr == virt_addr && bo->type == QXL_BO_DATA) {
> + found = bo;
> + break;
> + }
> + }
> + return (struct qxl_bo *)found;
> +}
> +
> +static void qxl_bo_incref(qxl_screen_t *qxl, struct qxl_bo *_bo)
> +{
> + struct qxl_ums_bo *bo = (struct qxl_ums_bo *)_bo;
> + bo->refcnt++;
> +}
> +
> +static void qxl_bo_decref(qxl_screen_t *qxl, struct qxl_bo *_bo)
> +{
> + struct qxl_ums_bo *bo = (struct qxl_ums_bo *)_bo;
> + struct qxl_mem *mptr;
> +
> + bo->refcnt--;
> +
> + if (bo->refcnt > 0)
> + return;
> +
> + if (bo->type == QXL_BO_SURF_PRIMARY)
> + goto out_free;
> +
> + if (bo->type == QXL_BO_SURF)
> + mptr = qxl->surf_mem;
> + else
> + mptr = qxl->mem;
> +
> + qxl_free(mptr, bo->internal_virt_addr, bo->name);
> + if (bo->type != QXL_BO_SURF)
> + xorg_list_del(&bo->bos);
> +out_free:
> + free(bo);
> +}
> +
> +static void qxl_bo_write_command(qxl_screen_t *qxl, uint32_t cmd_type, struct qxl_bo *bo)
> +{
> + struct QXLCommand cmd;
> +
> + /* When someone runs "init 3", the device will be
> + * switched into VGA mode and there is nothing we
> + * can do about it. We get no notification.
> + *
> + * However, if commands are submitted when the device
> + * is in VGA mode, they will be queued up, and then
> + * the next time a mode set set, an assertion in the
> + * device will take down the entire virtual machine.
> + *
> + * For surface commands this is not relevant, we send
> + * them regardless.
> + */
> +
> + if (!qxl->pScrn->vtSema && cmd_type != QXL_CMD_SURFACE)
> + return;
> +
> + cmd.type = cmd_type;
> + qxl_bo_output_cmd_reloc(qxl, &cmd, bo);
> +
> + if (cmd_type == QXL_CMD_CURSOR)
> + qxl_ring_push (qxl->cursor_ring, &cmd);
> + else
> + qxl_ring_push (qxl->command_ring, &cmd);
> +
> + qxl_bo_decref(qxl, bo);
> +}
> +
> +static void qxl_bo_update_area(qxl_surface_t *surf, int x1, int y1, int x2, int y2)
> +{
> + struct QXLRam *ram_header = get_ram_header(surf->qxl);
> +
> + ram_header->update_area.top = y1;
> + ram_header->update_area.bottom = y2;
> + ram_header->update_area.left = x1;
> + ram_header->update_area.right = x2;
> +
> + ram_header->update_surface = surf->id;
> +
> + qxl_update_area(surf->qxl);
> +}
> +
> +/* create a fake bo for the primary */
> +static struct qxl_bo *qxl_bo_create_primary(qxl_screen_t *qxl, uint32_t width, uint32_t height, int32_t stride, uint32_t format)
> +{
> + struct qxl_ums_bo *bo;
> + struct QXLRam *ram_header =
> + (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset);
> +
> + struct QXLSurfaceCreate *create = &(ram_header->create_surface);
> +
> + create->width = width;
> + create->height = height;
> + create->stride = - stride;
> + create->format = format;
> + 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);
> +
> + qxl_io_create_primary(qxl);
> +
> + bo = calloc(1, sizeof(struct qxl_ums_bo));
> + if (!bo)
> + return NULL;
> +
> + bo->size = stride * height;
> + bo->name = "primary";
> + bo->type = QXL_BO_SURF_PRIMARY;
> + bo->qxl = qxl;
> + bo->refcnt = 1;
> + bo->internal_virt_addr = (uint8_t *)qxl->ram + stride * (height - 1);
> +
> + qxl->primary_bo = (struct qxl_bo *)bo;
> + return (struct qxl_bo *)bo;
> +}
> +
> +static void qxl_bo_destroy_primary(qxl_screen_t *qxl, struct qxl_bo *bo)
> +{
> + free(bo);
> + qxl->primary_bo = NULL;
> +
> + qxl_io_destroy_primary (qxl);
> +}
> +
> +static void qxl_bo_output_surf_reloc(qxl_screen_t *qxl, uint32_t dst_offset,
> + struct qxl_bo *_dst_bo, qxl_surface_t *surf)
> +{
> + struct qxl_ums_bo *dst_bo = (struct qxl_ums_bo *)_dst_bo;
> +
> + *(uint32_t *)((char *)dst_bo->internal_virt_addr + dst_offset) = surf->id;
> +}
> +
> +struct qxl_bo_funcs qxl_ums_bo_funcs = {
> + qxl_bo_alloc,
> + qxl_cmd_alloc,
> + qxl_bo_map,
> + qxl_bo_unmap,
> + qxl_bo_decref,
> + qxl_bo_incref,
> + qxl_bo_output_bo_reloc,
> + qxl_bo_write_command,
> + qxl_bo_update_area,
> + qxl_bo_create_primary,
> + qxl_bo_destroy_primary,
> + qxl_surface_create,
> + qxl_surface_kill,
> + qxl_bo_output_surf_reloc,
> +};
> +
> +void qxl_ums_setup_funcs(qxl_screen_t *qxl)
> +{
> + qxl->bo_funcs = &qxl_ums_bo_funcs;
> +}
> +
> +struct qxl_bo *qxl_ums_surf_mem_alloc(qxl_screen_t *qxl, uint32_t size)
> +{
> + struct qxl_bo *bo;
> + bo = qxl_bo_alloc_internal (qxl, QXL_BO_SURF, QXL_BO_FLAG_FAIL, size, "surface memory");
> + return bo;
> +}
> diff --git a/src/qxl_surface.c b/src/qxl_surface.c
> index eaf1761..e175697 100644
> --- a/src/qxl_surface.c
> +++ b/src/qxl_surface.c
> @@ -303,8 +303,9 @@ 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, "surface memory");
> -
> + if (surface->bo)
> + cache->qxl->bo_funcs->bo_decref (cache->qxl, surface->bo);
> + surface->bo = NULL;
> surface->next = cache->free_surfaces;
> cache->free_surfaces = surface;
> }
> @@ -319,14 +320,12 @@ qxl_surface_t *
> qxl_surface_cache_create_primary (qxl_screen_t *qxl,
> struct QXLMode *mode)
> {
> - struct QXLRam *ram_header =
> - (void *)((unsigned long)qxl->ram + qxl->rom->ram_header_offset);
> - struct QXLSurfaceCreate *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;
> - surface_cache_t *cache = qxl->surface_cache;
> + surface_cache_t *cache = qxl->surface_cache;
> + struct qxl_bo *bo;
>
> if (mode->bits == 16)
> {
> @@ -338,24 +337,14 @@ qxl_surface_cache_create_primary (qxl_screen_t *qxl,
> }
> else
> {
> - xf86DrvMsg (cache->qxl->pScrn->scrnIndex, X_ERROR,
> + xf86DrvMsg (qxl->pScrn->scrnIndex, X_ERROR,
> "Unknown bit depth %d\n", mode->bits);
> return NULL;
> }
> -
> - create->width = mode->x_res;
> - create->height = mode->y_res;
> - create->stride = - mode->stride;
> - create->format = mode->bits;
> - 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 (cache->qxl, cache->qxl->ram, cache->qxl->main_mem_slot);
>
> - qxl_io_create_primary(qxl);
> -
> - dev_addr = (uint8_t *)qxl->ram + mode->stride * (mode->y_res - 1);
> + bo = qxl->bo_funcs->create_primary(qxl, mode->x_res, mode->y_res, mode->stride, mode->bits);
>
> + dev_addr = qxl->bo_funcs->bo_map(bo);
> dev_image = pixman_image_create_bits (format, mode->x_res, mode->y_res,
> (uint32_t *)dev_addr, -mode->stride);
>
> @@ -382,6 +371,7 @@ qxl_surface_cache_create_primary (qxl_screen_t *qxl,
> surface->next = NULL;
> surface->prev = NULL;
> surface->evacuated = NULL;
> + surface->bo = bo;
>
> REGION_INIT (NULL, &(surface->access_region), (BoxPtr)NULL, 0);
> surface->access_type = UXA_ACCESS_RO;
> @@ -392,35 +382,36 @@ qxl_surface_cache_create_primary (qxl_screen_t *qxl,
> void *
> qxl_surface_get_host_bits(qxl_surface_t *surface)
> {
> + if (!surface)
> + return NULL;
Looks like a separate fix, could use a separate patch. Up to you.
> return (void *) pixman_image_get_data(surface->host_image);
> }
>
> -static struct QXLSurfaceCmd *
> +static struct qxl_bo *
> make_surface_cmd (surface_cache_t *cache, uint32_t id, QXLSurfaceCmdType type)
> {
> + struct qxl_bo *cmd_bo;
> struct QXLSurfaceCmd *cmd;
> qxl_screen_t *qxl = cache->qxl;
>
> - cmd = qxl_allocnf (qxl, sizeof *cmd, "surface command");
> + cmd_bo = qxl->bo_funcs->cmd_alloc (qxl, sizeof *cmd, "surface command");
> + cmd = qxl->bo_funcs->bo_map(cmd_bo);
>
> - cmd->release_info.id = pointer_to_u64 (cmd) | 2;
> + cmd->release_info.id = pointer_to_u64 (cmd_bo) | 2;
> cmd->type = type;
> cmd->flags = 0;
> cmd->surface_id = id;
>
> - return cmd;
> + qxl->bo_funcs->bo_unmap(cmd_bo);
> + return cmd_bo;
> }
>
> static void
> -push_surface_cmd (surface_cache_t *cache, struct QXLSurfaceCmd *cmd)
> +push_surface_cmd (surface_cache_t *cache, struct qxl_bo *cmd_bo)
> {
> - struct QXLCommand command;
> qxl_screen_t *qxl = cache->qxl;
> -
> - command.type = QXL_CMD_SURFACE;
> - command.data = physical_address (qxl, cmd, qxl->main_mem_slot);
>
> - qxl_ring_push (qxl->command_ring, &command);
> + qxl->bo_funcs->write_command (qxl, QXL_CMD_SURFACE, cmd_bo);
I think you are actually fixing another possible bug here, because
write_command will check vtSema. But I think no reason to make a
separate patch here at all.
> }
>
> enum ROPDescriptor
> @@ -438,25 +429,25 @@ enum ROPDescriptor
> ROPD_INVERS_RES = (1 <<10),
> };
>
> -static struct QXLDrawable *
> +static struct qxl_bo *
> make_drawable (qxl_screen_t *qxl, qxl_surface_t *surf, uint8_t type,
> const struct QXLRect *rect
> /* , pRegion clip */)
> {
> struct QXLDrawable *drawable;
> + struct qxl_bo *draw_bo;
> int i;
> -
> - drawable = qxl_allocnf (qxl, sizeof *drawable, "drawable command");
> +
> + draw_bo = qxl->bo_funcs->cmd_alloc (qxl, sizeof *drawable, "drawable command");
> + assert(draw_bo);
> + drawable = qxl->bo_funcs->bo_map(draw_bo);
> assert(drawable);
>
> - drawable->release_info.id = pointer_to_u64 (drawable);
> + drawable->release_info.id = pointer_to_u64 (draw_bo);
>
> drawable->type = type;
>
> - if (surf)
> - drawable->surface_id = surf->id; /* Only primary for now */
> - else
> - drawable->surface_id = 0;
> + qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surface_id), draw_bo, surf);
>
> drawable->effect = QXL_EFFECT_OPAQUE;
> drawable->self_bitmap = 0;
> @@ -480,41 +471,27 @@ make_drawable (qxl_screen_t *qxl, qxl_surface_t *surf, uint8_t type,
> drawable->bbox = *rect;
>
> drawable->mm_time = qxl->rom->mm_clock;
> -
> - return drawable;
> +
> + qxl->bo_funcs->bo_unmap(draw_bo);
> + return draw_bo;
> }
>
> static void
> -push_drawable (qxl_screen_t *qxl, struct QXLDrawable *drawable)
> +push_drawable (qxl_screen_t *qxl, struct qxl_bo *drawable_bo)
> {
> - struct QXLCommand cmd;
> -
> - /* When someone runs "init 3", the device will be
> - * switched into VGA mode and there is nothing we
> - * can do about it. We get no notification.
> - *
> - * However, if commands are submitted when the device
> - * is in VGA mode, they will be queued up, and then
> - * the next time a mode set set, an assertion in the
> - * device will take down the entire virtual machine.
> - */
> - if (qxl->pScrn->vtSema)
> - {
> - cmd.type = QXL_CMD_DRAW;
> - cmd.data = physical_address (qxl, drawable, qxl->main_mem_slot);
> -
> - qxl_ring_push (qxl->command_ring, &cmd);
> - }
> + qxl->bo_funcs->write_command (qxl, QXL_CMD_DRAW, drawable_bo);
> }
>
> static void
> submit_fill (qxl_screen_t *qxl, qxl_surface_t *surf,
> const struct QXLRect *rect, uint32_t color)
> {
> + struct qxl_bo *drawable_bo;
> struct QXLDrawable *drawable;
>
> - drawable = make_drawable (qxl, surf, QXL_DRAW_FILL, rect);
> + drawable_bo = make_drawable (qxl, surf, QXL_DRAW_FILL, rect);
>
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
> drawable->u.fill.brush.type = SPICE_BRUSH_TYPE_SOLID;
> drawable->u.fill.brush.u.color = color;
> drawable->u.fill.rop_descriptor = ROPD_OP_PUT;
> @@ -523,7 +500,9 @@ submit_fill (qxl_screen_t *qxl, qxl_surface_t *surf,
> drawable->u.fill.mask.pos.y = 0;
> drawable->u.fill.mask.bitmap = 0;
>
> - push_drawable (qxl, drawable);
> + qxl->bo_funcs->bo_unmap(drawable_bo);
> +
> + push_drawable (qxl, drawable_bo);
> }
>
> static qxl_surface_t *
> @@ -576,8 +555,8 @@ surface_send_create (surface_cache_t *cache,
> int n_attempts = 0;
> qxl_screen_t *qxl = cache->qxl;
> qxl_surface_t *surface;
> - void *address;
> -
> + struct qxl_bo *bo, *cmd_bo;
> + void *dev_ptr;
> get_formats (bpp, &format, &pformat);
>
> width = align (width);
> @@ -591,9 +570,9 @@ surface_send_create (surface_cache_t *cache,
> */
> qxl_garbage_collect (qxl);
> retry2:
> - address = qxl_alloc (qxl->surf_mem, stride * height + stride, "surface memory");
> + bo = qxl_ums_surf_mem_alloc(qxl, stride * height + stride);
>
> - if (!address)
> + if (!bo)
> {
> ErrorF ("- %dth attempt\n", n_attempts++);
>
> @@ -623,30 +602,31 @@ retry:
> if (!qxl_handle_oom (cache->qxl))
> {
> ErrorF (" Out of surfaces\n");
> - qxl_free (qxl->surf_mem, address, "surface memory");
> + qxl->bo_funcs->bo_decref (qxl, bo);
> return NULL;
> }
> else
> goto retry;
> }
>
> - surface->address = address;
> - surface->end = (char *)address + stride * height;
> + surface->bo = bo;
>
> - cmd = make_surface_cmd (cache, surface->id, QXL_SURFACE_CMD_CREATE);
> + cmd_bo = make_surface_cmd (cache, surface->id, QXL_SURFACE_CMD_CREATE);
>
> + cmd = qxl->bo_funcs->bo_map(cmd_bo);
> cmd->u.surface_create.format = format;
> cmd->u.surface_create.width = width;
> cmd->u.surface_create.height = height;
> cmd->u.surface_create.stride = - stride;
> + qxl->bo_funcs->bo_unmap(cmd_bo);
>
> - cmd->u.surface_create.data =
> - physical_address (qxl, surface->address, qxl->vram_mem_slot);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(struct QXLSurfaceCmd, u.surface_create.data), cmd_bo, surface->bo);
>
> - push_surface_cmd (cache, cmd);
> + push_surface_cmd (cache, cmd_bo);
>
> + dev_ptr = qxl->bo_funcs->bo_map(surface->bo);
> dev_addr
> - = (uint32_t *)((uint8_t *)surface->address + stride * (height - 1));
> + = (uint32_t *)((uint8_t *)dev_ptr + stride * (height - 1));
>
> surface->dev_image = pixman_image_create_bits (
> pformat, width, height, dev_addr, - stride);
> @@ -654,6 +634,7 @@ retry:
> surface->host_image = pixman_image_create_bits (
> pformat, width, height, NULL, -1);
>
> + qxl->bo_funcs->bo_unmap(surface->bo);
> surface->bpp = bpp;
>
> n_live++;
> @@ -751,7 +732,7 @@ unlink_surface (qxl_surface_t *surface)
> static void
> surface_destroy (qxl_surface_t *surface)
> {
> - struct QXLSurfaceCmd *cmd;
> + struct qxl_bo *cmd_bo;
>
> if (surface->dev_image)
> pixman_image_unref (surface->dev_image);
> @@ -761,9 +742,11 @@ surface_destroy (qxl_surface_t *surface)
> #if 0
> ErrorF("destroy %ld\n", (long int)surface->end - (long int)surface->address);
> #endif
> - cmd = make_surface_cmd (surface->cache, surface->id, QXL_SURFACE_CMD_DESTROY);
> + cmd_bo = make_surface_cmd (surface->cache, surface->id, QXL_SURFACE_CMD_DESTROY);
> +
> + push_surface_cmd (surface->cache, cmd_bo);
>
> - push_surface_cmd (surface->cache, cmd);
> + surface->cache->qxl->bo_funcs->bo_decref(surface->cache->qxl, surface->bo);
> }
>
> static void
> @@ -907,16 +890,7 @@ download_box_no_update (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
> static void
> download_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
> {
> - struct QXLRam *ram_header = get_ram_header (surface->cache->qxl);
> -
> - ram_header->update_area.top = y1;
> - ram_header->update_area.bottom = y2;
> - ram_header->update_area.left = x1;
> - ram_header->update_area.right = x2;
> -
> - ram_header->update_surface = surface->id;
> -
> - qxl_update_area(surface->cache->qxl);
> + surface->qxl->bo_funcs->update_area(surface, x1, y1, x2, y2);
>
> download_box_no_update(surface, x1, y1, x2, y2);
> }
> @@ -995,7 +969,7 @@ real_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
> {
> struct QXLRect rect;
> struct QXLDrawable *drawable;
> - struct QXLImage *image;
> + struct qxl_bo *image_bo, *drawable_bo;
> qxl_screen_t *qxl = surface->qxl;
> uint32_t *data;
> int stride;
> @@ -1005,7 +979,8 @@ real_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
> rect.top = y1;
> rect.bottom = y2;
>
> - drawable = make_drawable (qxl, surface, QXL_DRAW_COPY, &rect);
> + drawable_bo = make_drawable (qxl, surface, QXL_DRAW_COPY, &rect);
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
> drawable->u.copy.src_area = rect;
> translate_rect (&drawable->u.copy.src_area);
> drawable->u.copy.rop_descriptor = ROPD_OP_PUT;
> @@ -1015,16 +990,19 @@ real_upload_box (qxl_surface_t *surface, int x1, int y1, int x2, int y2)
> drawable->u.copy.mask.pos.y = 0;
> drawable->u.copy.mask.bitmap = 0;
>
> + qxl->bo_funcs->bo_unmap(drawable_bo);
> +
> data = pixman_image_get_data (surface->host_image);
> stride = pixman_image_get_stride (surface->host_image);
>
> - image = qxl_image_create (
> + image_bo = qxl_image_create (
> qxl, (const uint8_t *)data, x1, y1, x2 - x1, y2 - y1, stride,
> surface->bpp == 24 ? 4 : surface->bpp / 8, TRUE);
> - drawable->u.copy.src_bitmap =
> - physical_address (qxl, image, qxl->main_mem_slot);
> -
> - push_drawable (qxl, drawable);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap),
> + drawable_bo, image_bo);
> + push_drawable (qxl, drawable_bo);
> +
> + qxl->bo_funcs->bo_decref(qxl, image_bo);
> }
>
> #define TILE_WIDTH 512
> @@ -1056,8 +1034,8 @@ static void
> upload_one_primary_region(qxl_screen_t *qxl, PixmapPtr pixmap, BoxPtr b)
> {
> struct QXLRect rect;
> + struct qxl_bo *drawable_bo, *image_bo;
> struct QXLDrawable *drawable;
> - struct QXLImage *image;
> FbBits *data;
> int stride;
> int bpp;
> @@ -1067,7 +1045,8 @@ upload_one_primary_region(qxl_screen_t *qxl, PixmapPtr pixmap, BoxPtr b)
> rect.top = b->y1;
> rect.bottom = b->y2;
>
> - drawable = make_drawable (qxl, NULL, QXL_DRAW_COPY, &rect);
> + drawable_bo = make_drawable (qxl, NULL, QXL_DRAW_COPY, &rect);
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
> drawable->u.copy.src_area = rect;
> translate_rect (&drawable->u.copy.src_area);
> drawable->u.copy.rop_descriptor = ROPD_OP_PUT;
> @@ -1076,15 +1055,17 @@ upload_one_primary_region(qxl_screen_t *qxl, PixmapPtr pixmap, BoxPtr b)
> drawable->u.copy.mask.pos.x = 0;
> drawable->u.copy.mask.pos.y = 0;
> drawable->u.copy.mask.bitmap = 0;
> + qxl->bo_funcs->bo_unmap(drawable_bo);
>
> fbGetPixmapBitsData(pixmap, data, stride, bpp);
> - image = qxl_image_create (
> + image_bo = qxl_image_create (
> qxl, (const uint8_t *)data, b->x1, b->y1, b->x2 - b->x1, b->y2 - b->y1, stride * sizeof(*data),
> bpp == 24 ? 4 : bpp / 8, TRUE);
> - drawable->u.copy.src_bitmap =
> - physical_address (qxl, image, qxl->main_mem_slot);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap),
> + drawable_bo, image_bo);
>
> - push_drawable (qxl, drawable);
> + push_drawable (qxl, drawable_bo);
> + qxl->bo_funcs->bo_decref(qxl, image_bo);
> }
>
> void
> @@ -1326,6 +1307,7 @@ qxl_surface_copy (qxl_surface_t *dest,
> int width, int height)
> {
> qxl_screen_t *qxl = dest->qxl;
> + struct qxl_bo *drawable_bo;
> struct QXLDrawable *drawable;
> struct QXLRect qrect;
>
> @@ -1341,26 +1323,36 @@ qxl_surface_copy (qxl_surface_t *dest,
>
> if (dest->id == dest->u.copy_src->id)
> {
> - drawable = make_drawable (qxl, dest, QXL_COPY_BITS, &qrect);
> + drawable_bo = make_drawable (qxl, dest, QXL_COPY_BITS, &qrect);
>
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
> drawable->u.copy_bits.src_pos.x = src_x1;
> drawable->u.copy_bits.src_pos.y = src_y1;
> + qxl->bo_funcs->bo_unmap(drawable_bo);
> +
> + push_drawable (qxl, drawable_bo);
> +
> }
> else
> {
> - struct QXLImage *image = qxl_allocnf (qxl, sizeof *image, "surface image struct");
> + struct qxl_bo *image_bo;
> + struct QXLImage *image;
>
> dest->u.copy_src->ref_count++;
> -
> + image_bo = qxl->bo_funcs->bo_alloc (qxl, sizeof(struct QXLImage), "image struct for surface");
> + image = qxl->bo_funcs->bo_map(image_bo);
> image->descriptor.id = 0;
> image->descriptor.type = SPICE_IMAGE_TYPE_SURFACE;
> image->descriptor.width = 0;
> image->descriptor.height = 0;
> image->surface_image.surface_id = dest->u.copy_src->id;
> + qxl->bo_funcs->bo_unmap(image_bo);
>
> - drawable = make_drawable (qxl, dest, QXL_DRAW_COPY, &qrect);
> + drawable_bo = make_drawable (qxl, dest, QXL_DRAW_COPY, &qrect);
>
> - drawable->u.copy.src_bitmap = physical_address (qxl, image, qxl->main_mem_slot);
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap),
> + drawable_bo, image_bo);
> drawable->u.copy.src_area.left = src_x1;
> drawable->u.copy.src_area.top = src_y1;
> drawable->u.copy.src_area.right = src_x1 + width;
> @@ -1372,7 +1364,7 @@ qxl_surface_copy (qxl_surface_t *dest,
> drawable->u.copy.mask.pos.y = 0;
> drawable->u.copy.mask.bitmap = 0;
>
> - drawable->surfaces_dest[0] = dest->u.copy_src->id;
> + qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[0]), drawable_bo, dest->u.copy_src);
> drawable->surfaces_rects[0] = drawable->u.copy.src_area;
>
> assert (src_x1 >= 0);
> @@ -1386,9 +1378,13 @@ qxl_surface_copy (qxl_surface_t *dest,
>
> assert (width <= pixman_image_get_width (dest->u.copy_src->host_image));
> assert (height <= pixman_image_get_height (dest->u.copy_src->host_image));
> +
> + qxl->bo_funcs->bo_unmap(drawable_bo);
> + push_drawable (qxl, drawable_bo);
> + qxl->bo_funcs->bo_decref(qxl, image_bo);
> }
>
> - push_drawable (qxl, drawable);
> +
stray whitespace.
> }
>
> /* composite */
> @@ -1412,13 +1408,14 @@ qxl_surface_prepare_composite (int op,
> return TRUE;
> }
>
> -static QXLImage *
> +static struct qxl_bo *
> image_from_picture (qxl_screen_t *qxl,
> PicturePtr picture,
> qxl_surface_t *surface,
> int *force_opaque)
> {
> - struct QXLImage *image = qxl_allocnf (qxl, sizeof *image, "image struct for picture");
> + struct qxl_bo *image_bo = qxl->bo_funcs->bo_alloc (qxl, sizeof(struct QXLImage), "image struct for surface");
> + struct QXLImage *image = qxl->bo_funcs->bo_map(image_bo);
>
> image->descriptor.id = 0;
> image->descriptor.type = SPICE_IMAGE_TYPE_SURFACE;
> @@ -1426,20 +1423,22 @@ image_from_picture (qxl_screen_t *qxl,
> image->descriptor.height = 0;
> image->surface_image.surface_id = surface->id;
>
> + qxl->bo_funcs->bo_unmap(image_bo);
> if (picture->format == PICT_x8r8g8b8)
> *force_opaque = TRUE;
> else
> *force_opaque = FALSE;
>
> - return image;
> + return image_bo;
> }
>
> -static QXLTransform *
> +static struct qxl_bo *
> get_transform (qxl_screen_t *qxl, PictTransform *transform)
> {
> if (transform)
> {
> - QXLTransform *qxform = qxl_allocnf (qxl, sizeof (QXLTransform), "transform");
> + struct qxl_bo *qxform_bo = qxl->bo_funcs->bo_alloc (qxl, sizeof (QXLTransform), "transform");
> + QXLTransform *qxform = qxl->bo_funcs->bo_map(qxform_bo);
>
> qxform->t00 = transform->matrix[0][0];
> qxform->t01 = transform->matrix[0][1];
> @@ -1448,7 +1447,8 @@ get_transform (qxl_screen_t *qxl, PictTransform *transform)
> qxform->t11 = transform->matrix[1][1];
> qxform->t12 = transform->matrix[1][2];
>
> - return qxform;
> + qxl->bo_funcs->bo_unmap(qxform_bo);
> + return qxform_bo;
> }
> else
> {
> @@ -1484,13 +1484,14 @@ qxl_surface_composite (qxl_surface_t *dest,
> qxl_surface_t *qmask = dest->u.composite.mask;
> int op = dest->u.composite.op;
> struct QXLDrawable *drawable;
> + struct qxl_bo *drawable_bo;
> QXLComposite *composite;
> QXLRect rect;
> - QXLImage *img;
> - QXLTransform *trans;
> + struct qxl_bo *trans_bo, *img_bo;
> int n_deps = 0;
> int force_opaque;
> -
> + struct qxl_bo *derefs[4];
> + int n_derefs = 0, i;
> #if 0
> ErrorF ("QXL Composite: src: %x (%d %d) id: %d; \n"
> " mask: id: %d\n"
> @@ -1511,7 +1512,9 @@ qxl_surface_composite (qxl_surface_t *dest,
> rect.top = dest_y;
> rect.bottom = dest_y + height;
>
> - drawable = make_drawable (qxl, dest, QXL_DRAW_COMPOSITE, &rect);
> + drawable_bo = make_drawable (qxl, dest, QXL_DRAW_COMPOSITE, &rect);
> +
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
>
> composite = &drawable->u.composite;
>
> @@ -1522,38 +1525,53 @@ qxl_surface_composite (qxl_surface_t *dest,
>
> composite->flags |= (op & 0xff);
>
> - img = image_from_picture (qxl, src, qsrc, &force_opaque);
> + img_bo = image_from_picture (qxl, src, qsrc, &force_opaque);
> if (force_opaque)
> composite->flags |= SPICE_COMPOSITE_SOURCE_OPAQUE;
> - composite->src = physical_address (qxl, img, qxl->main_mem_slot);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.src),
> + drawable_bo, img_bo);
> + derefs[n_derefs++] = img_bo;
> +
> composite->flags |= (src->filter << 8);
> composite->flags |= (src->repeat << 14);
> - trans = get_transform (qxl, src->transform);
> - composite->src_transform = trans?
> - physical_address (qxl, trans, qxl->main_mem_slot) : 0x00000000;
> -
> - drawable->surfaces_dest[n_deps] = qsrc->id;
> + trans_bo = get_transform (qxl, src->transform);
> + if (trans_bo) {
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.src_transform),
> + drawable_bo, trans_bo);
> + derefs[n_derefs++] = trans_bo;
> + } else
> + composite->src_transform = 0;
> +
> + qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[n_deps]), drawable_bo, qsrc);
> drawable->surfaces_rects[n_deps] = full_rect (qsrc);
>
> n_deps++;
>
> if (mask)
> {
> - img = image_from_picture (qxl, mask, qmask, &force_opaque);
> + img_bo = image_from_picture (qxl, mask, qmask, &force_opaque);
> if (force_opaque)
> composite->flags |= SPICE_COMPOSITE_MASK_OPAQUE;
> - composite->mask = physical_address (qxl, img, qxl->main_mem_slot);
> +
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.mask),
> + drawable_bo, img_bo);
> + derefs[n_derefs++] = img_bo;
> composite->flags |= (mask->filter << 11);
> composite->flags |= (mask->repeat << 16);
> composite->flags |= (mask->componentAlpha << 18);
>
> - drawable->surfaces_dest[n_deps] = qmask->id;
> + qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[n_deps]), drawable_bo, qmask);
> drawable->surfaces_rects[n_deps] = full_rect (qmask);
> n_deps++;
>
> - trans = get_transform (qxl, src->transform);
> - composite->mask_transform = trans?
> - physical_address (qxl, trans, qxl->main_mem_slot) : 0x00000000;
> + trans_bo = get_transform (qxl, src->transform);
> + if (trans_bo) {
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.composite.mask_transform),
> + drawable_bo, trans_bo);
> + derefs[n_derefs++] = trans_bo;
> + }
> + else
> + composite->mask_transform = 0;
> }
> else
> {
> @@ -1561,7 +1579,7 @@ qxl_surface_composite (qxl_surface_t *dest,
> composite->mask_transform = 0x00000000;
> }
>
> - drawable->surfaces_dest[n_deps] = dest->id;
> + qxl->bo_funcs->bo_output_surf_reloc(qxl, offsetof(struct QXLDrawable, surfaces_dest[n_deps]), drawable_bo, dest);
> drawable->surfaces_rects[n_deps] = full_rect (dest);
>
> composite->src_origin.x = src_x;
> @@ -1571,7 +1589,11 @@ qxl_surface_composite (qxl_surface_t *dest,
>
> drawable->effect = QXL_EFFECT_BLEND;
>
> - push_drawable (qxl, drawable);
> + qxl->bo_funcs->bo_unmap(drawable_bo);
> + push_drawable (qxl, drawable_bo);
> +
> + for (i = 0; i < n_derefs; i++)
> + qxl->bo_funcs->bo_decref(qxl, derefs[i]);
> }
>
> Bool
> @@ -1579,18 +1601,20 @@ qxl_surface_put_image (qxl_surface_t *dest,
> int x, int y, int width, int height,
> const char *src, int src_pitch)
> {
> + struct qxl_bo *drawable_bo;
> struct QXLDrawable *drawable;
> qxl_screen_t *qxl = dest->qxl;
> struct QXLRect rect;
> - struct QXLImage *image;
> -
> + struct qxl_bo *image_bo;
> +
> rect.left = x;
> rect.right = x + width;
> rect.top = y;
> rect.bottom = y + height;
>
> - drawable = make_drawable (qxl, dest, QXL_DRAW_COPY, &rect);
> + drawable_bo = make_drawable (qxl, dest, QXL_DRAW_COPY, &rect);
>
> + drawable = qxl->bo_funcs->bo_map(drawable_bo);
> drawable->u.copy.src_area.top = 0;
> drawable->u.copy.src_area.bottom = height;
> drawable->u.copy.src_area.left = 0;
> @@ -1603,13 +1627,15 @@ qxl_surface_put_image (qxl_surface_t *dest,
> drawable->u.copy.mask.pos.y = 0;
> drawable->u.copy.mask.bitmap = 0;
>
> - image = qxl_image_create (
> + image_bo = qxl_image_create (
> qxl, (const uint8_t *)src, 0, 0, width, height, src_pitch,
> dest->bpp == 24 ? 4 : dest->bpp / 8, FALSE);
> - drawable->u.copy.src_bitmap =
> - physical_address (qxl, image, qxl->main_mem_slot);
> -
> - push_drawable (qxl, drawable);
> + qxl->bo_funcs->bo_output_bo_reloc(qxl, offsetof(QXLDrawable, u.copy.src_bitmap),
> + drawable_bo, image_bo);
>
> + qxl->bo_funcs->bo_unmap(drawable_bo);
> +
> + push_drawable (qxl, drawable_bo);
> + qxl->bo_funcs->bo_decref(qxl, image_bo);
> return TRUE;
> }
> diff --git a/src/qxl_surface.h b/src/qxl_surface.h
> index 0f05d9d..89e08fd 100644
> --- a/src/qxl_surface.h
> +++ b/src/qxl_surface.h
> @@ -16,9 +16,7 @@ struct qxl_surface_t
> uxa_access_t access_type;
> RegionRec access_region;
>
> - void * address;
> - void * end;
> -
> + struct qxl_bo *bo;
> struct qxl_surface_t * next;
> struct qxl_surface_t * prev; /* Only used in the 'live'
> * chain in the surface cache
> diff --git a/src/qxl_uxa.c b/src/qxl_uxa.c
> index fd70488..d1740b2 100644
> --- a/src/qxl_uxa.c
> +++ b/src/qxl_uxa.c
> @@ -358,8 +358,10 @@ qxl_create_pixmap (ScreenPtr screen, int w, int h, int depth, unsigned usage)
> goto fallback;
> }
>
> - surface = qxl_surface_create (qxl, w, h, depth);
> + if (!w || !h)
> + goto fallback;
>
> + surface = qxl->bo_funcs->create_surface (qxl, w, h, depth);
> if (surface)
> {
> /* ErrorF (" Successfully created surface in video memory\n"); */
> @@ -415,7 +417,7 @@ qxl_destroy_pixmap (PixmapPtr pixmap)
>
> if (surface)
> {
> - qxl_surface_kill (surface);
> + qxl->bo_funcs->destroy_surface(surface);
> set_surface (pixmap, NULL);
>
> qxl_surface_cache_sanity_check (qxl->surface_cache);
> --
> 1.8.1.2
>
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/spice-devel
More information about the Spice-devel
mailing list