libspice: add surface 0 support

This include alot of infestracture for off screens.

Signed-off-by: Izik Eidus <ieidus@redhat.com>
This commit is contained in:
Izik Eidus 2010-01-28 04:44:43 +02:00
parent 766c74f63c
commit 2ba69f9f88
8 changed files with 1192 additions and 667 deletions

View File

@ -52,7 +52,7 @@
#define REDHAT_PCI_VENDOR_ID 0x1b36
#define QXL_DEVICE_ID 0x0100 /* 0x100-0x11f reserved for spice */
#define QXL_REVISION 0x02
#define QXL_REVISION 0x03
#define QXL_ROM_MAGIC (*(UINT32*)"QXRO")
#define QXL_RAM_MAGIC (*(UINT32*)"QXRA")
@ -73,10 +73,14 @@ enum {
QXL_IO_UPDATE_IRQ,
QXL_IO_NOTIFY_OOM,
QXL_IO_RESET,
QXL_IO_SET_MODE,
QXL_IO_LOG,
QXL_IO_MEMSLOT_ADD,
QXL_IO_MEMSLOT_DEL,
QXL_IO_DETACH_PRIMARY,
QXL_IO_ATTACH_PRIMARY,
QXL_IO_CREATE_PRIMARY,
QXL_IO_DESTROY_PRIMARY,
QXL_IO_DESTROY_SURFACE_WAIT,
QXL_IO_RANGE_SIZE
};
@ -87,12 +91,9 @@ typedef struct ATTR_PACKED QXLRom {
UINT32 update_id;
UINT32 compression_level;
UINT32 log_level;
UINT32 mode;
UINT32 modes_offset;
UINT32 num_io_pages;
UINT32 pages_offset;
UINT32 draw_area_offset;
UINT32 draw_area_size;
UINT32 num_pages;
UINT32 surface0_area_size;
UINT32 ram_header_offset;
UINT32 mm_clock;
UINT64 flags;
@ -136,12 +137,30 @@ typedef struct ATTR_PACKED QXLCommand {
UINT32 ped;
} QXLCommand;
typedef struct ATTR_PACKED QXLCommandExt {
QXLCommand cmd;
UINT32 group_id;
} QXLCommandExt;
typedef struct ATTR_PACKED QXLMemSlot {
UINT64 mem_start;
UINT64 mem_end;
} QXLMemSlot;
#define QXL_SURF_TYPE_PRIMARY 0
typedef struct ATTR_PACKED QXLSurfaceCreate {
UINT32 width;
UINT32 height;
INT32 stride;
UINT32 depth;
UINT32 position;
UINT32 mouse_mode;
UINT32 flags;
UINT32 type;
PHYSICAL mem;
} QXLSurfaceCreate;
RING_DECLARE(QXLCommandRing, QXLCommand, 32);
RING_DECLARE(QXLCursorRing, QXLCommand, 32);
@ -162,6 +181,7 @@ typedef struct ATTR_PACKED QXLRam {
QXLReleaseRing release_ring;
Rect update_area;
QXLMemSlot mem_slot;
QXLSurfaceCreate create_surface;
UINT64 flags;
} QXLRam;
@ -170,6 +190,11 @@ typedef union QXLReleaseInfo {
UINT64 next; // out
} QXLReleaseInfo;
typedef struct QXLReleaseInfoExt {
QXLReleaseInfo *info;
UINT32 group_id;
} QXLReleaseInfoExt;
typedef struct ATTR_PACKED QXLDataChunk {
UINT32 data_size;
PHYSICAL prev_chunk;
@ -262,8 +287,8 @@ typedef struct ATTR_PACKED QXLDrawable {
QXLReleaseInfo release_info;
UINT8 effect;
UINT8 type;
UINT16 bitmap_offset;
Rect bitmap_area;
UINT8 self_bitmap;
Rect self_bitmap_area;
Rect bbox;
Clip clip;
UINT32 mm_time;

View File

@ -2,7 +2,7 @@ AC_PREREQ([2.57])
m4_define([SPICE_MAJOR], 0)
m4_define([SPICE_MINOR], 5)
m4_define([SPICE_MICRO], 1)
m4_define([SPICE_MICRO], 2)
AC_INIT(spice, [SPICE_MAJOR.SPICE_MINOR.SPICE_MICRO], [], spice)

View File

@ -48,6 +48,11 @@
abort(); \
}
#define PANIC_ON(x) if ((x)) { \
printf("%s: panic %s\n", __FUNCTION__, #x); \
abort(); \
}
#define TRUE 1
#define FALSE 0

View File

@ -44,7 +44,7 @@ struct RedDispatcher {
int channel;
pthread_t worker_thread;
uint32_t pending;
int active;
int primary_active;
int x_res;
int y_res;
int use_hardware_cursor;
@ -179,7 +179,7 @@ static void update_client_mouse_allowed()
allow_now = TRUE;
RedDispatcher *now = dispatchers;
while (now && allow_now) {
if (now->active) {
if (now->primary_active) {
allow_now = now->use_hardware_cursor;
if (num_active_workers == 1) {
if (allow_now) {
@ -199,44 +199,6 @@ static void update_client_mouse_allowed()
}
}
static void qxl_worker_attach(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_ATTACH;
QXLDevInfo info;
dispatcher->qxl_interface->get_info(dispatcher->qxl_interface, &info);
dispatcher->x_res = info.x_res;
dispatcher->y_res = info.y_res;
dispatcher->use_hardware_cursor = info.use_hardware_cursor;
dispatcher->active = TRUE;
write_message(dispatcher->channel, &message);
send_data(dispatcher->channel, &info, sizeof(QXLDevInfo));
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
num_active_workers++;
update_client_mouse_allowed();
}
static void qxl_worker_detach(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_DETACH;
write_message(dispatcher->channel, &message);
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
dispatcher->x_res = 0;
dispatcher->y_res = 0;
dispatcher->use_hardware_cursor = FALSE;
dispatcher->active = FALSE;
num_active_workers--;
update_client_mouse_allowed();
}
static void qxl_worker_update_area(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
@ -258,15 +220,95 @@ static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slo
ASSERT(message == RED_WORKER_MESSAGE_READY);
}
static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t slot_id)
static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t slot_group_id, uint32_t slot_id)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_DEL_MEMSLOT;
write_message(dispatcher->channel, &message);
send_data(dispatcher->channel, &slot_group_id, sizeof(uint32_t));
send_data(dispatcher->channel, &slot_id, sizeof(uint32_t));
}
static void qxl_worker_destroy_surfaces(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES;
write_message(dispatcher->channel, &message);
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
}
static void qxl_worker_destroy_primary(QXLWorker *qxl_worker, uint32_t surface_id)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE;
write_message(dispatcher->channel, &message);
send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
dispatcher->x_res = 0;
dispatcher->y_res = 0;
dispatcher->use_hardware_cursor = FALSE;
dispatcher->primary_active = FALSE;
update_client_mouse_allowed();
}
static void qxl_worker_create_primary(QXLWorker *qxl_worker, uint32_t surface_id,
QXLDevSurfaceCreate *surface)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE;
dispatcher->x_res = surface->width;
dispatcher->y_res = surface->height;
dispatcher->use_hardware_cursor = surface->mouse_mode;
dispatcher->primary_active = TRUE;
write_message(dispatcher->channel, &message);
send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
send_data(dispatcher->channel, surface, sizeof(QXLDevSurfaceCreate));
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
update_client_mouse_allowed();
}
static void qxl_worker_reset_image_cache(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_RESET_IMAGE_CACHE;
write_message(dispatcher->channel, &message);
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
}
static void qxl_worker_reset_cursor(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_RESET_CURSOR;
write_message(dispatcher->channel, &message);
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
}
static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t surface_id)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
RedWorkeMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT;
write_message(dispatcher->channel, &message);
send_data(dispatcher->channel, &surface_id, sizeof(uint32_t));
read_message(dispatcher->channel, &message);
ASSERT(message == RED_WORKER_MESSAGE_READY);
}
static void qxl_worker_reset_memslots(QXLWorker *qxl_worker)
{
RedDispatcher *dispatcher = (RedDispatcher *)qxl_worker;
@ -404,12 +446,12 @@ int red_dispatcher_count()
uint32_t red_dispatcher_qxl_ram_size()
{
QXLDevInfo qxl_info;
QXLDevInitInfo qxl_info;
if (!dispatchers) {
return 0;
}
dispatchers->qxl_interface->get_info(dispatchers->qxl_interface, &qxl_info);
return qxl_info.ram_size;
dispatchers->qxl_interface->get_init_info(dispatchers->qxl_interface, &qxl_info);
return qxl_info.qxl_ram_size;
}
RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
@ -457,8 +499,6 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
dispatcher->base.major_version = VD_INTERFACE_QXL_MAJOR;
dispatcher->base.major_version = VD_INTERFACE_QXL_MINOR;
dispatcher->base.attach = qxl_worker_attach;
dispatcher->base.detach = qxl_worker_detach;
dispatcher->base.wakeup = qxl_worker_wakeup;
dispatcher->base.oom = qxl_worker_oom;
dispatcher->base.save = qxl_worker_save;
@ -469,12 +509,23 @@ RedDispatcher *red_dispatcher_init(QXLInterface *qxl_interface)
dispatcher->base.add_memslot = qxl_worker_add_memslot;
dispatcher->base.del_memslot = qxl_worker_del_memslot;
dispatcher->base.reset_memslots = qxl_worker_reset_memslots;
dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces;
dispatcher->base.create_primary_surface = qxl_worker_create_primary;
dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary;
dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache;
dispatcher->base.reset_cursor = qxl_worker_reset_cursor;
dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;
qxl_interface->get_init_info(qxl_interface, &init_info);
init_data.memslot_id_bits = init_info.memslot_id_bits;
init_data.memslot_gen_bits = init_info.memslot_gen_bits;
init_data.num_memslots = init_info.num_memslots;
init_data.num_memslots_groups = init_info.num_memslots_groups;
init_data.internal_groupslot_id = init_info.internal_groupslot_id;
num_active_workers = 1;
sigfillset(&thread_sig_mask);
sigdelset(&thread_sig_mask, SIGILL);

File diff suppressed because it is too large Load Diff

View File

@ -46,8 +46,6 @@ enum {
RED_WORKER_MESSAGE_UPDATE,
RED_WORKER_MESSAGE_WAKEUP,
RED_WORKER_MESSAGE_OOM,
RED_WORKER_MESSAGE_ATTACH,
RED_WORKER_MESSAGE_DETACH,
RED_WORKER_MESSAGE_READY,
RED_WORKER_MESSAGE_DISPLAY_CONNECT,
RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
@ -65,6 +63,12 @@ enum {
RED_WORKER_MESSAGE_ADD_MEMSLOT,
RED_WORKER_MESSAGE_DEL_MEMSLOT,
RED_WORKER_MESSAGE_RESET_MEMSLOTS,
RED_WORKER_MESSAGE_DESTROY_SURFACES,
RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
RED_WORKER_MESSAGE_RESET_CURSOR,
RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
};
typedef uint32_t RedWorkeMessage;
@ -88,8 +92,10 @@ typedef struct WorkerInitData {
image_compression_t image_compression;
int streaming_video;
uint32_t num_memslots;
uint32_t num_memslots_groups;
uint8_t memslot_gen_bits;
uint8_t memslot_id_bits;
uint8_t internal_groupslot_id;
} WorkerInitData;
void *red_worker_main(void *arg);

View File

@ -86,7 +86,7 @@ static inline void FUNC_NAME(red_rgb_to_yuv420_line)(const uint8_t* line0, const
static inline int FUNC_NAME(red_rgb_to_yuv420)(RedWorker *worker, const Rect *src,
const Bitmap *image, AVFrame *frame,
long phys_delta, int memslot_id, int id,
Stream *stream)
Stream *stream, uint32_t group_id)
{
QXLDataChunk *chunk;
uint32_t image_stride;
@ -108,16 +108,17 @@ static inline int FUNC_NAME(red_rgb_to_yuv420)(RedWorker *worker, const Rect *sr
const int skip_lines = stream->top_down ? src->top : image->y - (src->bottom - 0);
for (i = 0; i < skip_lines; i++) {
red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, memslot_id);
red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta, memslot_id,
group_id);
}
const int image_hight = src->bottom - src->top;
const int image_width = src->right - src->left;
for (i = 0; i < image_hight / 2; i++) {
uint8_t* line0 = red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta,
memslot_id);
memslot_id, group_id);
uint8_t* line1 = red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta,
memslot_id);
memslot_id, group_id);
if (!line0 || !line1) {
return FALSE;
@ -135,7 +136,7 @@ static inline int FUNC_NAME(red_rgb_to_yuv420)(RedWorker *worker, const Rect *sr
if ((image_hight & 1)) {
uint8_t* line = red_get_image_line(worker, &chunk, &offset, image_stride, phys_delta,
memslot_id);
memslot_id, group_id);
if (!line) {
return FALSE;
}

View File

@ -93,19 +93,20 @@ struct CoreInterface {
};
#define VD_INTERFACE_QXL "qxl"
#define VD_INTERFACE_QXL_MAJOR 2
#define VD_INTERFACE_QXL_MAJOR 3
#define VD_INTERFACE_QXL_MINOR 0
typedef struct QXLInterface QXLInterface;
typedef void (*qxl_mode_change_notifier_t)(void *opaque);
typedef struct QXLWorker QXLWorker;
typedef struct QXLDevMemSlot QXLDevMemSlot;
typedef struct QXLDevSurfaceCreate QXLDevSurfaceCreate;
union QXLReleaseInfo;
struct QXLReleaseInfoExt;
struct QXLCommand;
struct QXLCommandExt;
struct QXLWorker {
uint32_t minor_version;
uint32_t major_version;
void (*attach)(QXLWorker *worker);
void (*detach)(QXLWorker *worker);
void (*wakeup)(QXLWorker *worker);
void (*oom)(QXLWorker *worker);
void (*save)(QXLWorker *worker);
@ -114,8 +115,15 @@ struct QXLWorker {
void (*stop)(QXLWorker *worker);
void (*update_area)(QXLWorker *worker);
void (*add_memslot)(QXLWorker *worker, QXLDevMemSlot *slot);
void (*del_memslot)(QXLWorker *worker, uint32_t slot_id);
void (*del_memslot)(QXLWorker *worker, uint32_t slot_group_id, uint32_t slot_id);
void (*reset_memslots)(QXLWorker *worker);
void (*destroy_surfaces)(QXLWorker *worker);
void (*destroy_primary_surface)(QXLWorker *worker, uint32_t surface_id);
void (*create_primary_surface)(QXLWorker *worker, uint32_t surface_id,
QXLDevSurfaceCreate *surface);
void (*reset_image_cache)(QXLWorker *worker);
void (*reset_cursor)(QXLWorker *worker);
void (*destroy_surface_wait)(QXLWorker *worker, uint32_t surface_id);
};
typedef struct DrawArea {
@ -139,17 +147,35 @@ typedef struct QXLDevInfo {
} QXLDevInfo;
typedef struct QXLDevInitInfo {
uint32_t num_memslots_groups;
uint32_t num_memslots;
uint8_t memslot_gen_bits;
uint8_t memslot_id_bits;
uint32_t qxl_ram_size;
uint8_t internal_groupslot_id;
} QXLDevInitInfo;
struct QXLDevMemSlot {
uint32_t slot_group_id;
uint32_t slot_id;
uint32_t generation;
unsigned long virt_start;
unsigned long virt_end;
uint64_t addr_delta;
uint32_t qxl_ram_size;
};
struct QXLDevSurfaceCreate {
uint32_t width;
uint32_t height;
int32_t stride;
uint32_t depth;
uint32_t position;
uint32_t mouse_mode;
uint32_t flags;
uint32_t type;
uint64_t mem;
uint32_t group_id;
};
struct QXLInterface {
@ -162,17 +188,13 @@ struct QXLInterface {
void (*attache_worker)(QXLInterface *qxl, QXLWorker *qxl_worker);
void (*set_compression_level)(QXLInterface *qxl, int level);
void (*set_mm_time)(QXLInterface *qxl, uint32_t mm_time);
VDObjectRef (*register_mode_change)(QXLInterface *qxl, qxl_mode_change_notifier_t,
void *opaque);
void (*unregister_mode_change)(QXLInterface *qxl, VDObjectRef notifier);
void (*get_init_info)(QXLInterface *qxl, QXLDevInitInfo *info);
void (*get_info)(QXLInterface *qxl, QXLDevInfo *info);
int (*get_command)(QXLInterface *qxl, struct QXLCommand *cmd);
int (*get_command)(QXLInterface *qxl, struct QXLCommandExt *cmd);
int (*req_cmd_notification)(QXLInterface *qxl);
int (*has_command)(QXLInterface *qxl);
void (*release_resource)(QXLInterface *qxl, union QXLReleaseInfo *release_info);
int (*get_cursor_command)(QXLInterface *qxl, struct QXLCommand *cmd);
void (*release_resource)(QXLInterface *qxl, struct QXLReleaseInfoExt release_info);
int (*get_cursor_command)(QXLInterface *qxl, struct QXLCommandExt *cmd);
int (*req_cursor_notification)(QXLInterface *qxl);
const struct Rect *(*get_update_area)(QXLInterface *qxl);
void (*notify_update)(QXLInterface *qxl, uint32_t update_id);