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