summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@gmail.com>2013-02-26 14:03:40 +1000
committerDave Airlie <airlied@gmail.com>2013-03-06 13:22:42 +1000
commit8c7fada8f42cc4a741f7f1d210b50f754ef8805e (patch)
tree6aca2cc3bdb37fced1c5f1a8cc7437ffe390caa7
parentf0e9d7bb9658a89909f97b485437a1375aa0267f (diff)
qxl: abstract object allocation away from surface/image/cursor code
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@redhat.com>
-rw-r--r--src/qxl.h52
-rw-r--r--src/qxl_cursor.c52
-rw-r--r--src/qxl_driver.c8
-rw-r--r--src/qxl_image.c69
-rw-r--r--src/qxl_mem.c343
-rw-r--r--src/qxl_surface.c302
-rw-r--r--src/qxl_surface.h4
-rw-r--r--src/qxl_uxa.c6
8 files changed, 604 insertions, 232 deletions
diff --git a/src/qxl.h b/src/qxl.h
index 2d1840a..017eab5 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 which the reloc is being written,
+ * 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..b404873 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;
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);
}
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,11 @@ 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));
- }
- push_drawable (qxl, drawable);
+ qxl->bo_funcs->bo_unmap(drawable_bo);
+ push_drawable (qxl, drawable_bo);
+ qxl->bo_funcs->bo_decref(qxl, image_bo);
+ }
}
/* composite */
@@ -1412,13 +1406,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 +1421,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 +1445,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 +1482,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 +1510,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 +1523,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 +1577,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 +1587,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 +1599,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 +1625,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);