[Spice-devel] [PATCH v3 2/4] rename red-dispatcher.* files to red-qxl.*
Frediano Ziglio
fziglio at redhat.com
Fri Mar 4 15:13:26 UTC 2016
Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
---
server/Makefile.am | 4 +-
server/agent-msg-filter.c | 2 +-
server/display-channel.h | 2 +-
server/red-dispatcher.c | 1032 ---------------------------------------------
server/red-dispatcher.h | 272 ------------
server/red-qxl.c | 1032 +++++++++++++++++++++++++++++++++++++++++++++
server/red-qxl.h | 272 ++++++++++++
server/red-worker.h | 2 +-
server/reds.c | 2 +-
server/sound.c | 2 +-
10 files changed, 1311 insertions(+), 1311 deletions(-)
delete mode 100644 server/red-dispatcher.c
delete mode 100644 server/red-dispatcher.h
create mode 100644 server/red-qxl.c
create mode 100644 server/red-qxl.h
diff --git a/server/Makefile.am b/server/Makefile.am
index 9eb5f44..a7a8d9f 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -93,8 +93,8 @@ libserver_la_SOURCES = \
red-common.h \
dispatcher.c \
dispatcher.h \
- red-dispatcher.c \
- red-dispatcher.h \
+ red-qxl.c \
+ red-qxl.h \
main-dispatcher.c \
main-dispatcher.h \
migration-protocol.h \
diff --git a/server/agent-msg-filter.c b/server/agent-msg-filter.c
index d72a3e4..a6aee9e 100644
--- a/server/agent-msg-filter.c
+++ b/server/agent-msg-filter.c
@@ -25,7 +25,7 @@
#include "red-common.h"
#include "agent-msg-filter.h"
#include "reds.h"
-#include "red-dispatcher.h"
+#include "red-qxl.h"
void agent_msg_filter_init(struct AgentMsgFilter *filter,
gboolean copy_paste, gboolean file_xfer,
diff --git a/server/display-channel.h b/server/display-channel.h
index cf40edd..1bccd22 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -33,7 +33,7 @@
#include "red-record-qxl.h"
#include "demarshallers.h"
#include "red-channel.h"
-#include "red-dispatcher.h"
+#include "red-qxl.h"
#include "dispatcher.h"
#include "main-channel.h"
#include "migration-protocol.h"
diff --git a/server/red-dispatcher.c b/server/red-dispatcher.c
deleted file mode 100644
index cfc113d..0000000
--- a/server/red-dispatcher.c
+++ /dev/null
@@ -1,1032 +0,0 @@
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-#include <pthread.h>
-#include <sys/socket.h>
-#include <inttypes.h>
-
-#include <spice/qxl_dev.h>
-#include "common/quic.h"
-
-#include "spice.h"
-#include "red-worker.h"
-#include "sw-canvas.h"
-#include "reds.h"
-#include "dispatcher.h"
-#include "red-parse-qxl.h"
-
-#include "red-dispatcher.h"
-
-
-struct AsyncCommand {
- RedWorkerMessage message;
- uint64_t cookie;
-};
-
-struct RedDispatcher {
- QXLWorker base;
- QXLInstance *qxl;
- Dispatcher dispatcher;
- uint32_t pending;
- int primary_active;
- int x_res;
- int y_res;
- int use_hardware_cursor;
- QXLDevSurfaceCreate surface_create;
- unsigned int max_monitors;
-};
-
-static int red_qxl_check_qxl_version(RedDispatcher *rd, int major, int minor)
-{
- int qxl_major = rd->qxl->st->qif->base.major_version;
- int qxl_minor = rd->qxl->st->qif->base.minor_version;
-
- return ((qxl_major > major) ||
- ((qxl_major == major) && (qxl_minor >= minor)));
-}
-
-static void red_qxl_set_display_peer(RedChannel *channel, RedClient *client,
- RedsStream *stream, int migration,
- int num_common_caps, uint32_t *common_caps, int num_caps,
- uint32_t *caps)
-{
- RedWorkerMessageDisplayConnect payload = {0,};
- RedDispatcher *dispatcher;
-
- spice_debug("%s", "");
- dispatcher = (RedDispatcher *)channel->data;
- payload.client = client;
- payload.stream = stream;
- payload.migration = migration;
- payload.num_common_caps = num_common_caps;
- payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
- payload.num_caps = num_caps;
- payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);
-
- memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
- memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DISPLAY_CONNECT,
- &payload);
-}
-
-static void red_qxl_disconnect_display_peer(RedChannelClient *rcc)
-{
- RedWorkerMessageDisplayDisconnect payload;
- RedDispatcher *dispatcher;
-
- if (!rcc->channel) {
- return;
- }
-
- dispatcher = (RedDispatcher *)rcc->channel->data;
-
- spice_printerr("");
- payload.rcc = rcc;
-
- // TODO: we turned it to be sync, due to client_destroy . Should we support async? - for this we will need ref count
- // for channels
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
- &payload);
-}
-
-static void red_qxl_display_migrate(RedChannelClient *rcc)
-{
- RedWorkerMessageDisplayMigrate payload;
- RedDispatcher *dispatcher;
- if (!rcc->channel) {
- return;
- }
- dispatcher = (RedDispatcher *)rcc->channel->data;
- spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id);
- payload.rcc = rcc;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
- &payload);
-}
-
-static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient *client, RedsStream *stream,
- int migration, int num_common_caps,
- uint32_t *common_caps, int num_caps,
- uint32_t *caps)
-{
- RedWorkerMessageCursorConnect payload = {0,};
- RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
- spice_printerr("");
- payload.client = client;
- payload.stream = stream;
- payload.migration = migration;
- payload.num_common_caps = num_common_caps;
- payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
- payload.num_caps = num_caps;
- payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);
-
- memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
- memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_CURSOR_CONNECT,
- &payload);
-}
-
-static void red_qxl_disconnect_cursor_peer(RedChannelClient *rcc)
-{
- RedWorkerMessageCursorDisconnect payload;
- RedDispatcher *dispatcher;
-
- if (!rcc->channel) {
- return;
- }
-
- dispatcher = (RedDispatcher *)rcc->channel->data;
- spice_printerr("");
- payload.rcc = rcc;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
- &payload);
-}
-
-static void red_qxl_cursor_migrate(RedChannelClient *rcc)
-{
- RedWorkerMessageCursorMigrate payload;
- RedDispatcher *dispatcher;
-
- if (!rcc->channel) {
- return;
- }
- dispatcher = (RedDispatcher *)rcc->channel->data;
- spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id);
- payload.rcc = rcc;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_CURSOR_MIGRATE,
- &payload);
-}
-
-static void red_qxl_update_area(RedDispatcher *dispatcher, uint32_t surface_id,
- QXLRect *qxl_area, QXLRect *qxl_dirty_rects,
- uint32_t num_dirty_rects, uint32_t clear_dirty_region)
-{
- RedWorkerMessageUpdate payload = {0,};
-
- payload.surface_id = surface_id;
- payload.qxl_area = qxl_area;
- payload.qxl_dirty_rects = qxl_dirty_rects;
- payload.num_dirty_rects = num_dirty_rects;
- payload.clear_dirty_region = clear_dirty_region;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_UPDATE,
- &payload);
-}
-
-gboolean red_qxl_use_client_monitors_config(RedDispatcher *dispatcher)
-{
- return (red_qxl_check_qxl_version(dispatcher, 3, 3) &&
- dispatcher->qxl->st->qif->client_monitors_config &&
- dispatcher->qxl->st->qif->client_monitors_config(dispatcher->qxl, NULL));
-}
-
-gboolean red_qxl_client_monitors_config(RedDispatcher *dispatcher,
- VDAgentMonitorsConfig *monitors_config)
-{
- return (dispatcher->qxl->st->qif->client_monitors_config &&
- dispatcher->qxl->st->qif->client_monitors_config(dispatcher->qxl,
- monitors_config));
-}
-
-static AsyncCommand *async_command_alloc(RedDispatcher *dispatcher,
- RedWorkerMessage message,
- uint64_t cookie)
-{
- AsyncCommand *async_command = spice_new0(AsyncCommand, 1);
-
- async_command->cookie = cookie;
- async_command->message = message;
-
- spice_debug("%p", async_command);
- return async_command;
-}
-
-static void red_qxl_update_area_async(RedDispatcher *dispatcher,
- uint32_t surface_id,
- QXLRect *qxl_area,
- uint32_t clear_dirty_region,
- uint64_t cookie)
-{
- RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE_ASYNC;
- RedWorkerMessageUpdateAsync payload;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- payload.surface_id = surface_id;
- payload.qxl_area = *qxl_area;
- payload.clear_dirty_region = clear_dirty_region;
- dispatcher_send_message(&dispatcher->dispatcher,
- message,
- &payload);
-}
-
-static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t surface_id,
- QXLRect *qxl_area, QXLRect *qxl_dirty_rects,
- uint32_t num_dirty_rects, uint32_t clear_dirty_region)
-{
- red_qxl_update_area((RedDispatcher*)qxl_worker, surface_id, qxl_area,
- qxl_dirty_rects, num_dirty_rects, clear_dirty_region);
-}
-
-static void red_qxl_add_memslot(RedDispatcher *dispatcher, QXLDevMemSlot *mem_slot)
-{
- RedWorkerMessageAddMemslot payload;
-
- payload.mem_slot = *mem_slot;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_ADD_MEMSLOT,
- &payload);
-}
-
-static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slot)
-{
- red_qxl_add_memslot((RedDispatcher*)qxl_worker, mem_slot);
-}
-
-static void red_qxl_add_memslot_async(RedDispatcher *dispatcher, QXLDevMemSlot *mem_slot, uint64_t cookie)
-{
- RedWorkerMessageAddMemslotAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- payload.mem_slot = *mem_slot;
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void red_qxl_del_memslot(RedDispatcher *dispatcher, uint32_t slot_group_id, uint32_t slot_id)
-{
- RedWorkerMessageDelMemslot payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_DEL_MEMSLOT;
-
- payload.slot_group_id = slot_group_id;
- payload.slot_id = slot_id;
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t slot_group_id, uint32_t slot_id)
-{
- red_qxl_del_memslot((RedDispatcher*)qxl_worker, slot_group_id, slot_id);
-}
-
-static void red_qxl_destroy_surfaces(RedDispatcher *dispatcher)
-{
- RedWorkerMessageDestroySurfaces payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DESTROY_SURFACES,
- &payload);
-}
-
-static void qxl_worker_destroy_surfaces(QXLWorker *qxl_worker)
-{
- red_qxl_destroy_surfaces((RedDispatcher*)qxl_worker);
-}
-
-static void red_qxl_destroy_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
-{
- RedWorkerMessageDestroySurfacesAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void red_qxl_destroy_primary_surface_complete(RedDispatcher *dispatcher)
-{
- dispatcher->x_res = 0;
- dispatcher->y_res = 0;
- dispatcher->use_hardware_cursor = FALSE;
- dispatcher->primary_active = FALSE;
-
- reds_update_client_mouse_allowed(reds);
-}
-
-static void
-red_qxl_destroy_primary_surface_sync(RedDispatcher *dispatcher,
- uint32_t surface_id)
-{
- RedWorkerMessageDestroyPrimarySurface payload;
- payload.surface_id = surface_id;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
- &payload);
- red_qxl_destroy_primary_surface_complete(dispatcher);
-}
-
-static void
-red_qxl_destroy_primary_surface_async(RedDispatcher *dispatcher,
- uint32_t surface_id, uint64_t cookie)
-{
- RedWorkerMessageDestroyPrimarySurfaceAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- payload.surface_id = surface_id;
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void
-red_qxl_destroy_primary_surface(RedDispatcher *dispatcher,
- uint32_t surface_id, int async, uint64_t cookie)
-{
- if (async) {
- red_qxl_destroy_primary_surface_async(dispatcher, surface_id, cookie);
- } else {
- red_qxl_destroy_primary_surface_sync(dispatcher, surface_id);
- }
-}
-
-static void qxl_worker_destroy_primary_surface(QXLWorker *qxl_worker, uint32_t surface_id)
-{
- red_qxl_destroy_primary_surface((RedDispatcher*)qxl_worker, surface_id, 0, 0);
-}
-
-static void red_qxl_create_primary_surface_complete(RedDispatcher *dispatcher)
-{
- QXLDevSurfaceCreate *surface = &dispatcher->surface_create;
-
- dispatcher->x_res = surface->width;
- dispatcher->y_res = surface->height;
- dispatcher->use_hardware_cursor = surface->mouse_mode;
- dispatcher->primary_active = TRUE;
-
- reds_update_client_mouse_allowed(reds);
- memset(&dispatcher->surface_create, 0, sizeof(QXLDevSurfaceCreate));
-}
-
-static void
-red_qxl_create_primary_surface_async(RedDispatcher *dispatcher, uint32_t surface_id,
- QXLDevSurfaceCreate *surface, uint64_t cookie)
-{
- RedWorkerMessageCreatePrimarySurfaceAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC;
-
- dispatcher->surface_create = *surface;
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- payload.surface_id = surface_id;
- payload.surface = *surface;
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void
-red_qxl_create_primary_surface_sync(RedDispatcher *dispatcher, uint32_t surface_id,
- QXLDevSurfaceCreate *surface)
-{
- RedWorkerMessageCreatePrimarySurface payload = {0,};
-
- dispatcher->surface_create = *surface;
- payload.surface_id = surface_id;
- payload.surface = *surface;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
- &payload);
- red_qxl_create_primary_surface_complete(dispatcher);
-}
-
-static void
-red_qxl_create_primary_surface(RedDispatcher *dispatcher, uint32_t surface_id,
- QXLDevSurfaceCreate *surface, int async, uint64_t cookie)
-{
- if (async) {
- red_qxl_create_primary_surface_async(dispatcher, surface_id, surface, cookie);
- } else {
- red_qxl_create_primary_surface_sync(dispatcher, surface_id, surface);
- }
-}
-
-static void qxl_worker_create_primary_surface(QXLWorker *qxl_worker, uint32_t surface_id,
- QXLDevSurfaceCreate *surface)
-{
- red_qxl_create_primary_surface((RedDispatcher*)qxl_worker, surface_id, surface, 0, 0);
-}
-
-static void red_qxl_reset_image_cache(RedDispatcher *dispatcher)
-{
- RedWorkerMessageResetImageCache payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
- &payload);
-}
-
-static void qxl_worker_reset_image_cache(QXLWorker *qxl_worker)
-{
- red_qxl_reset_image_cache((RedDispatcher*)qxl_worker);
-}
-
-static void red_qxl_reset_cursor(RedDispatcher *dispatcher)
-{
- RedWorkerMessageResetCursor payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_RESET_CURSOR,
- &payload);
-}
-
-static void qxl_worker_reset_cursor(QXLWorker *qxl_worker)
-{
- red_qxl_reset_cursor((RedDispatcher*)qxl_worker);
-}
-
-static void red_qxl_destroy_surface_wait_sync(RedDispatcher *dispatcher,
- uint32_t surface_id)
-{
- RedWorkerMessageDestroySurfaceWait payload;
-
- payload.surface_id = surface_id;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
- &payload);
-}
-
-static void red_qxl_destroy_surface_wait_async(RedDispatcher *dispatcher,
- uint32_t surface_id,
- uint64_t cookie)
-{
- RedWorkerMessageDestroySurfaceWaitAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- payload.surface_id = surface_id;
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void red_qxl_destroy_surface_wait(RedDispatcher *dispatcher,
- uint32_t surface_id,
- int async, uint64_t cookie)
-{
- if (async) {
- red_qxl_destroy_surface_wait_async(dispatcher, surface_id, cookie);
- } else {
- red_qxl_destroy_surface_wait_sync(dispatcher, surface_id);
- }
-}
-
-static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t surface_id)
-{
- red_qxl_destroy_surface_wait((RedDispatcher*)qxl_worker, surface_id, 0, 0);
-}
-
-static void red_qxl_reset_memslots(RedDispatcher *dispatcher)
-{
- RedWorkerMessageResetMemslots payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_RESET_MEMSLOTS,
- &payload);
-}
-
-static void qxl_worker_reset_memslots(QXLWorker *qxl_worker)
-{
- red_qxl_reset_memslots((RedDispatcher*)qxl_worker);
-}
-
-static bool red_qxl_set_pending(RedDispatcher *dispatcher, int pending)
-{
- // this is not atomic but is not an issue
- if (test_bit(pending, dispatcher->pending)) {
- return TRUE;
- }
-
- set_bit(pending, &dispatcher->pending);
- return FALSE;
-}
-
-static void red_qxl_wakeup(RedDispatcher *dispatcher)
-{
- RedWorkerMessageWakeup payload;
-
- if (red_qxl_set_pending(dispatcher, RED_DISPATCHER_PENDING_WAKEUP))
- return;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_WAKEUP,
- &payload);
-}
-
-static void qxl_worker_wakeup(QXLWorker *qxl_worker)
-{
- red_qxl_wakeup((RedDispatcher*)qxl_worker);
-}
-
-static void red_qxl_oom(RedDispatcher *dispatcher)
-{
- RedWorkerMessageOom payload;
-
- if (red_qxl_set_pending(dispatcher, RED_DISPATCHER_PENDING_OOM))
- return;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_OOM,
- &payload);
-}
-
-static void qxl_worker_oom(QXLWorker *qxl_worker)
-{
- red_qxl_oom((RedDispatcher*)qxl_worker);
-}
-
-void red_qxl_start(RedDispatcher *dispatcher)
-{
- RedWorkerMessageStart payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_START,
- &payload);
-}
-
-static void qxl_worker_start(QXLWorker *qxl_worker)
-{
- red_qxl_start((RedDispatcher*)qxl_worker);
-}
-
-static void red_qxl_flush_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
-{
- RedWorkerMessageFlushSurfacesAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void red_qxl_monitors_config_async(RedDispatcher *dispatcher,
- QXLPHYSICAL monitors_config,
- int group_id,
- uint64_t cookie)
-{
- RedWorkerMessageMonitorsConfigAsync payload;
- RedWorkerMessage message = RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC;
-
- payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
- payload.monitors_config = monitors_config;
- payload.group_id = group_id;
- payload.max_monitors = dispatcher->max_monitors;
-
- dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
-}
-
-static void red_qxl_driver_unload(RedDispatcher *dispatcher)
-{
- RedWorkerMessageDriverUnload payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_DRIVER_UNLOAD,
- &payload);
-}
-
-void red_qxl_stop(RedDispatcher *dispatcher)
-{
- RedWorkerMessageStop payload;
-
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_STOP,
- &payload);
-}
-
-static void qxl_worker_stop(QXLWorker *qxl_worker)
-{
- red_qxl_stop((RedDispatcher*)qxl_worker);
-}
-
-static void red_qxl_loadvm_commands(RedDispatcher *dispatcher,
- struct QXLCommandExt *ext,
- uint32_t count)
-{
- RedWorkerMessageLoadvmCommands payload;
-
- spice_printerr("");
- payload.count = count;
- payload.ext = ext;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_LOADVM_COMMANDS,
- &payload);
-}
-
-static void qxl_worker_loadvm_commands(QXLWorker *qxl_worker,
- struct QXLCommandExt *ext,
- uint32_t count)
-{
- red_qxl_loadvm_commands((RedDispatcher*)qxl_worker, ext, count);
-}
-
-void red_qxl_set_mm_time(RedDispatcher *dispatcher, uint32_t mm_time)
-{
- dispatcher->qxl->st->qif->set_mm_time(dispatcher->qxl, mm_time);
-}
-
-void red_qxl_attach_worker(RedDispatcher *dispatcher)
-{
- QXLInstance *qxl = dispatcher->qxl;
- qxl->st->qif->attache_worker(qxl, &dispatcher->base);
-}
-
-void red_qxl_set_compression_level(RedDispatcher *dispatcher, int level)
-{
- dispatcher->qxl->st->qif->set_compression_level(dispatcher->qxl, level);
-}
-
-uint32_t red_qxl_get_ram_size(RedDispatcher *dispatcher)
-{
- QXLDevInitInfo qxl_info;
- dispatcher->qxl->st->qif->get_init_info(dispatcher->qxl, &qxl_info);
- return qxl_info.qxl_ram_size;
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_wakeup(QXLInstance *instance)
-{
- red_qxl_wakeup(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_oom(QXLInstance *instance)
-{
- red_qxl_oom(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_start(QXLInstance *instance)
-{
- red_qxl_start(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_stop(QXLInstance *instance)
-{
- red_qxl_stop(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_update_area(QXLInstance *instance, uint32_t surface_id,
- struct QXLRect *area, struct QXLRect *dirty_rects,
- uint32_t num_dirty_rects, uint32_t clear_dirty_region)
-{
- red_qxl_update_area(instance->st->dispatcher, surface_id, area, dirty_rects,
- num_dirty_rects, clear_dirty_region);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_add_memslot(QXLInstance *instance, QXLDevMemSlot *slot)
-{
- red_qxl_add_memslot(instance->st->dispatcher, slot);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_del_memslot(QXLInstance *instance, uint32_t slot_group_id, uint32_t slot_id)
-{
- red_qxl_del_memslot(instance->st->dispatcher, slot_group_id, slot_id);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_reset_memslots(QXLInstance *instance)
-{
- red_qxl_reset_memslots(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_destroy_surfaces(QXLInstance *instance)
-{
- red_qxl_destroy_surfaces(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_destroy_primary_surface(QXLInstance *instance, uint32_t surface_id)
-{
- red_qxl_destroy_primary_surface(instance->st->dispatcher, surface_id, 0, 0);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_create_primary_surface(QXLInstance *instance, uint32_t surface_id,
- QXLDevSurfaceCreate *surface)
-{
- red_qxl_create_primary_surface(instance->st->dispatcher, surface_id, surface, 0, 0);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_reset_image_cache(QXLInstance *instance)
-{
- red_qxl_reset_image_cache(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_reset_cursor(QXLInstance *instance)
-{
- red_qxl_reset_cursor(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_destroy_surface_wait(QXLInstance *instance, uint32_t surface_id)
-{
- red_qxl_destroy_surface_wait(instance->st->dispatcher, surface_id, 0, 0);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_loadvm_commands(QXLInstance *instance, struct QXLCommandExt *ext, uint32_t count)
-{
- red_qxl_loadvm_commands(instance->st->dispatcher, ext, count);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_update_area_async(QXLInstance *instance, uint32_t surface_id, QXLRect *qxl_area,
- uint32_t clear_dirty_region, uint64_t cookie)
-{
- red_qxl_update_area_async(instance->st->dispatcher, surface_id, qxl_area,
- clear_dirty_region, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_add_memslot_async(QXLInstance *instance, QXLDevMemSlot *slot, uint64_t cookie)
-{
- red_qxl_add_memslot_async(instance->st->dispatcher, slot, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_destroy_surfaces_async(QXLInstance *instance, uint64_t cookie)
-{
- red_qxl_destroy_surfaces_async(instance->st->dispatcher, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_destroy_primary_surface_async(QXLInstance *instance, uint32_t surface_id, uint64_t cookie)
-{
- red_qxl_destroy_primary_surface(instance->st->dispatcher, surface_id, 1, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_create_primary_surface_async(QXLInstance *instance, uint32_t surface_id,
- QXLDevSurfaceCreate *surface, uint64_t cookie)
-{
- red_qxl_create_primary_surface(instance->st->dispatcher, surface_id, surface, 1, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_destroy_surface_async(QXLInstance *instance, uint32_t surface_id, uint64_t cookie)
-{
- red_qxl_destroy_surface_wait(instance->st->dispatcher, surface_id, 1, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie)
-{
- red_qxl_flush_surfaces_async(instance->st->dispatcher, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_monitors_config_async(QXLInstance *instance, QXLPHYSICAL monitors_config,
- int group_id, uint64_t cookie)
-{
- red_qxl_monitors_config_async(instance->st->dispatcher, monitors_config, group_id, cookie);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_set_max_monitors(QXLInstance *instance, unsigned int max_monitors)
-{
- instance->st->dispatcher->max_monitors = MAX(1u, max_monitors);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_driver_unload(QXLInstance *instance)
-{
- red_qxl_driver_unload(instance->st->dispatcher);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_gl_scanout(QXLInstance *qxl,
- int fd,
- uint32_t width, uint32_t height,
- uint32_t stride, uint32_t format,
- int y_0_top)
-{
- spice_return_if_fail(qxl != NULL);
- spice_return_if_fail(qxl->st->gl_draw_async == NULL);
-
- pthread_mutex_lock(&qxl->st->scanout_mutex);
-
- if (qxl->st->scanout.drm_dma_buf_fd != -1) {
- close(qxl->st->scanout.drm_dma_buf_fd);
- }
-
- qxl->st->scanout = (SpiceMsgDisplayGlScanoutUnix) {
- .flags = y_0_top ? SPICE_GL_SCANOUT_FLAGS_Y0TOP : 0,
- .drm_dma_buf_fd = fd,
- .width = width,
- .height = height,
- .stride = stride,
- .drm_fourcc_format = format
- };
-
- pthread_mutex_unlock(&qxl->st->scanout_mutex);
-
- /* FIXME: find a way to coallesce all pending SCANOUTs */
- dispatcher_send_message(&qxl->st->dispatcher->dispatcher,
- RED_WORKER_MESSAGE_GL_SCANOUT, NULL);
-}
-
-SPICE_GNUC_VISIBLE
-void spice_qxl_gl_draw_async(QXLInstance *qxl,
- uint32_t x, uint32_t y,
- uint32_t w, uint32_t h,
- uint64_t cookie)
-{
- RedDispatcher *dispatcher;
- RedWorkerMessage message = RED_WORKER_MESSAGE_GL_DRAW_ASYNC;
- SpiceMsgDisplayGlDraw draw = {
- .x = x,
- .y = y,
- .w = w,
- .h = h
- };
-
- spice_return_if_fail(qxl != NULL);
- spice_return_if_fail(qxl->st->scanout.drm_dma_buf_fd != -1);
- spice_return_if_fail(qxl->st->gl_draw_async == NULL);
-
- dispatcher = qxl->st->dispatcher;
- qxl->st->gl_draw_async = async_command_alloc(dispatcher, message, cookie);
- dispatcher_send_message(&dispatcher->dispatcher, message, &draw);
-}
-
-void red_qxl_async_complete(struct RedDispatcher *dispatcher,
- AsyncCommand *async_command)
-{
- spice_debug("%p: cookie %" PRId64, async_command, async_command->cookie);
- switch (async_command->message) {
- case RED_WORKER_MESSAGE_UPDATE_ASYNC:
- case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC:
- case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC:
- case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
- case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
- case RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC:
- case RED_WORKER_MESSAGE_GL_DRAW_ASYNC:
- break;
- case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC:
- red_qxl_create_primary_surface_complete(dispatcher);
- break;
- case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC:
- red_qxl_destroy_primary_surface_complete(dispatcher);
- break;
- default:
- spice_warning("unexpected message %d", async_command->message);
- }
- dispatcher->qxl->st->qif->async_complete(dispatcher->qxl,
- async_command->cookie);
- free(async_command);
-}
-
-void red_qxl_init(QXLInstance *qxl)
-{
- RedDispatcher *red_dispatcher;
- RedChannel *channel;
- ClientCbs client_cbs = { NULL, };
-
- spice_return_if_fail(qxl != NULL);
- spice_return_if_fail(qxl->st->dispatcher == NULL);
-
- static gsize initialized = FALSE;
- if (g_once_init_enter(&initialized)) {
- quic_init();
- sw_canvas_init();
- g_once_init_leave(&initialized, TRUE);
- }
-
- red_dispatcher = spice_new0(RedDispatcher, 1);
- red_dispatcher->qxl = qxl;
- dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL);
- red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR;
- red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
- red_dispatcher->base.wakeup = qxl_worker_wakeup;
- red_dispatcher->base.oom = qxl_worker_oom;
- red_dispatcher->base.start = qxl_worker_start;
- red_dispatcher->base.stop = qxl_worker_stop;
- red_dispatcher->base.update_area = qxl_worker_update_area;
- red_dispatcher->base.add_memslot = qxl_worker_add_memslot;
- red_dispatcher->base.del_memslot = qxl_worker_del_memslot;
- red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots;
- red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces;
- red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface;
- red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface;
-
- red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache;
- red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor;
- red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;
- red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands;
-
- red_dispatcher->max_monitors = UINT_MAX;
-
- // TODO: reference and free
- RedWorker *worker = red_worker_new(qxl, red_dispatcher);
-
- // TODO: move to their respective channel files
- channel = red_worker_get_cursor_channel(worker);
- client_cbs.connect = red_qxl_set_cursor_peer;
- client_cbs.disconnect = red_qxl_disconnect_cursor_peer;
- client_cbs.migrate = red_qxl_cursor_migrate;
- red_channel_register_client_cbs(channel, &client_cbs);
- red_channel_set_data(channel, red_dispatcher);
- reds_register_channel(reds, channel);
-
- channel = red_worker_get_display_channel(worker);
- client_cbs.connect = red_qxl_set_display_peer;
- client_cbs.disconnect = red_qxl_disconnect_display_peer;
- client_cbs.migrate = red_qxl_display_migrate;
- red_channel_register_client_cbs(channel, &client_cbs);
- red_channel_set_data(channel, red_dispatcher);
- red_channel_set_cap(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
- red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
- red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
- reds_register_channel(reds, channel);
-
- red_worker_run(worker);
-
- qxl->st->dispatcher = red_dispatcher;
-}
-
-struct Dispatcher *red_qxl_get_dispatcher(RedDispatcher *red_dispatcher)
-{
- return &red_dispatcher->dispatcher;
-}
-
-void red_qxl_set_dispatcher_opaque(RedDispatcher *red_dispatcher,
- void *opaque)
-{
- dispatcher_set_opaque(&red_dispatcher->dispatcher, opaque);
-}
-
-void red_qxl_clear_pending(RedDispatcher *red_dispatcher, int pending)
-{
- spice_return_if_fail(red_dispatcher != NULL);
-
- clear_bit(pending, &red_dispatcher->pending);
-}
-
-gboolean red_qxl_get_primary_active(RedDispatcher *dispatcher)
-{
- return dispatcher->primary_active;
-}
-
-gboolean red_qxl_get_allow_client_mouse(RedDispatcher *dispatcher, gint *x_res, gint *y_res)
-{
- if (dispatcher->use_hardware_cursor) {
- if (x_res)
- *x_res = dispatcher->x_res;
- if (y_res)
- *y_res = dispatcher->y_res;
- }
- return dispatcher->use_hardware_cursor;
-}
-
-void red_qxl_on_ic_change(RedDispatcher *dispatcher, SpiceImageCompression ic)
-{
- RedWorkerMessageSetCompression payload;
- payload.image_compression = ic;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_SET_COMPRESSION,
- &payload);
-}
-
-void red_qxl_on_sv_change(RedDispatcher *dispatcher, int sv)
-{
- RedWorkerMessageSetStreamingVideo payload;
- payload.streaming_video = sv;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
- &payload);
-}
-
-void red_qxl_set_mouse_mode(RedDispatcher *dispatcher, uint32_t mode)
-{
- RedWorkerMessageSetMouseMode payload;
- payload.mode = mode;
- dispatcher_send_message(&dispatcher->dispatcher,
- RED_WORKER_MESSAGE_SET_MOUSE_MODE,
- &payload);
-}
diff --git a/server/red-dispatcher.h b/server/red-dispatcher.h
deleted file mode 100644
index 1348e6c..0000000
--- a/server/red-dispatcher.h
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- Copyright (C) 2009 Red Hat, Inc.
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef _H_RED_DISPATCHER
-#define _H_RED_DISPATCHER
-
-#include "red-channel.h"
-
-typedef struct RedDispatcher RedDispatcher;
-
-typedef struct AsyncCommand AsyncCommand;
-
-void red_qxl_init(QXLInstance *qxl);
-
-void red_qxl_set_mm_time(RedDispatcher *dispatcher, uint32_t);
-void red_qxl_on_ic_change(RedDispatcher *dispatcher, SpiceImageCompression ic);
-void red_qxl_on_sv_change(RedDispatcher *dispatcher, int sv);
-void red_qxl_set_mouse_mode(RedDispatcher *dispatcher, uint32_t mode);
-void red_qxl_attach_worker(RedDispatcher *dispatcher);
-void red_qxl_set_compression_level(RedDispatcher *dispatcher, int level);
-void red_qxl_stop(RedDispatcher *dispatcher);
-void red_qxl_start(RedDispatcher *dispatcher);
-uint32_t red_qxl_get_ram_size(RedDispatcher *dispatcher);
-void red_qxl_async_complete(struct RedDispatcher *, AsyncCommand *);
-struct Dispatcher *red_qxl_get_dispatcher(struct RedDispatcher *);
-gboolean red_qxl_use_client_monitors_config(RedDispatcher *dispatcher);
-gboolean red_qxl_client_monitors_config(RedDispatcher *dispatcher, VDAgentMonitorsConfig *monitors_config);
-gboolean red_qxl_get_primary_active(RedDispatcher *dispatcher);
-gboolean red_qxl_get_allow_client_mouse(RedDispatcher *dispatcher, gint *x_res, gint *y_res);
-
-typedef uint32_t RedWorkerMessage;
-
-/* Keep message order, only append new messages!
- * Replay code store enum values into save files.
- */
-enum {
- RED_WORKER_MESSAGE_NOP,
-
- RED_WORKER_MESSAGE_UPDATE,
- RED_WORKER_MESSAGE_WAKEUP,
- RED_WORKER_MESSAGE_OOM,
- RED_WORKER_MESSAGE_READY, /* unused */
-
- RED_WORKER_MESSAGE_DISPLAY_CONNECT,
- RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
- RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
- RED_WORKER_MESSAGE_START,
- RED_WORKER_MESSAGE_STOP,
- RED_WORKER_MESSAGE_CURSOR_CONNECT,
- RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
- RED_WORKER_MESSAGE_CURSOR_MIGRATE,
- RED_WORKER_MESSAGE_SET_COMPRESSION,
- RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
- RED_WORKER_MESSAGE_SET_MOUSE_MODE,
- 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,
- RED_WORKER_MESSAGE_LOADVM_COMMANDS,
- /* async commands */
- RED_WORKER_MESSAGE_UPDATE_ASYNC,
- RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC,
- RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC,
- RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC,
- RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
- RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
- /* suspend/windows resolution change command */
- RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
-
- RED_WORKER_MESSAGE_DISPLAY_CHANNEL_CREATE, /* unused */
- RED_WORKER_MESSAGE_CURSOR_CHANNEL_CREATE, /* unused */
-
- RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
- RED_WORKER_MESSAGE_DRIVER_UNLOAD,
- RED_WORKER_MESSAGE_GL_SCANOUT,
- RED_WORKER_MESSAGE_GL_DRAW_ASYNC,
-
- RED_WORKER_MESSAGE_COUNT // LAST
-};
-
-typedef struct RedWorkerMessageDisplayConnect {
- RedClient * client;
- RedsStream * stream;
- uint32_t *common_caps; // red_worker should free
- uint32_t *caps; // red_worker should free
- int migration;
- int num_common_caps;
- int num_caps;
-} RedWorkerMessageDisplayConnect;
-
-typedef struct RedWorkerMessageDisplayDisconnect {
- RedChannelClient *rcc;
-} RedWorkerMessageDisplayDisconnect;
-
-typedef struct RedWorkerMessageDisplayMigrate {
- RedChannelClient *rcc;
-} RedWorkerMessageDisplayMigrate;
-
-typedef struct RedWorkerMessageCursorConnect {
- RedClient *client;
- RedsStream *stream;
- int migration;
- uint32_t *common_caps; // red_worker should free
- int num_common_caps;
- uint32_t *caps; // red_worker should free
- int num_caps;
-} RedWorkerMessageCursorConnect;
-
-typedef struct RedWorkerMessageCursorDisconnect {
- RedChannelClient *rcc;
-} RedWorkerMessageCursorDisconnect;
-
-typedef struct RedWorkerMessageCursorMigrate {
- RedChannelClient *rcc;
-} RedWorkerMessageCursorMigrate;
-
-typedef struct RedWorkerMessageUpdate {
- uint32_t surface_id;
- QXLRect * qxl_area;
- QXLRect * qxl_dirty_rects;
- uint32_t num_dirty_rects;
- uint32_t clear_dirty_region;
-} RedWorkerMessageUpdate;
-
-typedef struct RedWorkerMessageAsync {
- AsyncCommand *cmd;
-} RedWorkerMessageAsync;
-
-typedef struct RedWorkerMessageUpdateAsync {
- RedWorkerMessageAsync base;
- uint32_t surface_id;
- QXLRect qxl_area;
- uint32_t clear_dirty_region;
-} RedWorkerMessageUpdateAsync;
-
-typedef struct RedWorkerMessageAddMemslot {
- QXLDevMemSlot mem_slot;
-} RedWorkerMessageAddMemslot;
-
-typedef struct RedWorkerMessageAddMemslotAsync {
- RedWorkerMessageAsync base;
- QXLDevMemSlot mem_slot;
-} RedWorkerMessageAddMemslotAsync;
-
-typedef struct RedWorkerMessageDelMemslot {
- uint32_t slot_group_id;
- uint32_t slot_id;
-} RedWorkerMessageDelMemslot;
-
-typedef struct RedWorkerMessageDestroySurfaces {
-} RedWorkerMessageDestroySurfaces;
-
-typedef struct RedWorkerMessageDestroySurfacesAsync {
- RedWorkerMessageAsync base;
-} RedWorkerMessageDestroySurfacesAsync;
-
-
-typedef struct RedWorkerMessageDestroyPrimarySurface {
- uint32_t surface_id;
-} RedWorkerMessageDestroyPrimarySurface;
-
-typedef struct RedWorkerMessageDestroyPrimarySurfaceAsync {
- RedWorkerMessageAsync base;
- uint32_t surface_id;
-} RedWorkerMessageDestroyPrimarySurfaceAsync;
-
-typedef struct RedWorkerMessageCreatePrimarySurfaceAsync {
- RedWorkerMessageAsync base;
- uint32_t surface_id;
- QXLDevSurfaceCreate surface;
-} RedWorkerMessageCreatePrimarySurfaceAsync;
-
-typedef struct RedWorkerMessageCreatePrimarySurface {
- uint32_t surface_id;
- QXLDevSurfaceCreate surface;
-} RedWorkerMessageCreatePrimarySurface;
-
-typedef struct RedWorkerMessageResetImageCache {
-} RedWorkerMessageResetImageCache;
-
-typedef struct RedWorkerMessageResetCursor {
-} RedWorkerMessageResetCursor;
-
-typedef struct RedWorkerMessageWakeup {
-} RedWorkerMessageWakeup;
-
-typedef struct RedWorkerMessageOom {
-} RedWorkerMessageOom;
-
-typedef struct RedWorkerMessageStart {
-} RedWorkerMessageStart;
-
-typedef struct RedWorkerMessageFlushSurfacesAsync {
- RedWorkerMessageAsync base;
-} RedWorkerMessageFlushSurfacesAsync;
-
-typedef struct RedWorkerMessageStop {
-} RedWorkerMessageStop;
-
-/* this command is sync, so it's ok to pass a pointer */
-typedef struct RedWorkerMessageLoadvmCommands {
- uint32_t count;
- QXLCommandExt *ext;
-} RedWorkerMessageLoadvmCommands;
-
-typedef struct RedWorkerMessageSetCompression {
- SpiceImageCompression image_compression;
-} RedWorkerMessageSetCompression;
-
-typedef struct RedWorkerMessageSetStreamingVideo {
- uint32_t streaming_video;
-} RedWorkerMessageSetStreamingVideo;
-
-typedef struct RedWorkerMessageSetMouseMode {
- uint32_t mode;
-} RedWorkerMessageSetMouseMode;
-
-typedef struct RedWorkerMessageDisplayChannelCreate {
-} RedWorkerMessageDisplayChannelCreate;
-
-typedef struct RedWorkerMessageCursorChannelCreate {
-} RedWorkerMessageCursorChannelCreate;
-
-typedef struct RedWorkerMessageDestroySurfaceWait {
- uint32_t surface_id;
-} RedWorkerMessageDestroySurfaceWait;
-
-typedef struct RedWorkerMessageDestroySurfaceWaitAsync {
- RedWorkerMessageAsync base;
- uint32_t surface_id;
-} RedWorkerMessageDestroySurfaceWaitAsync;
-
-typedef struct RedWorkerMessageResetMemslots {
-} RedWorkerMessageResetMemslots;
-
-typedef struct RedWorkerMessageMonitorsConfigAsync {
- RedWorkerMessageAsync base;
- QXLPHYSICAL monitors_config;
- int group_id;
- unsigned int max_monitors;
-} RedWorkerMessageMonitorsConfigAsync;
-
-typedef struct RedWorkerMessageDriverUnload {
-} RedWorkerMessageDriverUnload;
-
-enum {
- RED_DISPATCHER_PENDING_WAKEUP,
- RED_DISPATCHER_PENDING_OOM,
-};
-
-void red_qxl_clear_pending(RedDispatcher *red_dispatcher, int pending);
-
-#endif
diff --git a/server/red-qxl.c b/server/red-qxl.c
new file mode 100644
index 0000000..3dfeae6
--- /dev/null
+++ b/server/red-qxl.c
@@ -0,0 +1,1032 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <inttypes.h>
+
+#include <spice/qxl_dev.h>
+#include "common/quic.h"
+
+#include "spice.h"
+#include "red-worker.h"
+#include "sw-canvas.h"
+#include "reds.h"
+#include "dispatcher.h"
+#include "red-parse-qxl.h"
+
+#include "red-qxl.h"
+
+
+struct AsyncCommand {
+ RedWorkerMessage message;
+ uint64_t cookie;
+};
+
+struct RedDispatcher {
+ QXLWorker base;
+ QXLInstance *qxl;
+ Dispatcher dispatcher;
+ uint32_t pending;
+ int primary_active;
+ int x_res;
+ int y_res;
+ int use_hardware_cursor;
+ QXLDevSurfaceCreate surface_create;
+ unsigned int max_monitors;
+};
+
+static int red_qxl_check_qxl_version(RedDispatcher *rd, int major, int minor)
+{
+ int qxl_major = rd->qxl->st->qif->base.major_version;
+ int qxl_minor = rd->qxl->st->qif->base.minor_version;
+
+ return ((qxl_major > major) ||
+ ((qxl_major == major) && (qxl_minor >= minor)));
+}
+
+static void red_qxl_set_display_peer(RedChannel *channel, RedClient *client,
+ RedsStream *stream, int migration,
+ int num_common_caps, uint32_t *common_caps, int num_caps,
+ uint32_t *caps)
+{
+ RedWorkerMessageDisplayConnect payload = {0,};
+ RedDispatcher *dispatcher;
+
+ spice_debug("%s", "");
+ dispatcher = (RedDispatcher *)channel->data;
+ payload.client = client;
+ payload.stream = stream;
+ payload.migration = migration;
+ payload.num_common_caps = num_common_caps;
+ payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
+ payload.num_caps = num_caps;
+ payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);
+
+ memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
+ memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_CONNECT,
+ &payload);
+}
+
+static void red_qxl_disconnect_display_peer(RedChannelClient *rcc)
+{
+ RedWorkerMessageDisplayDisconnect payload;
+ RedDispatcher *dispatcher;
+
+ if (!rcc->channel) {
+ return;
+ }
+
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+
+ spice_printerr("");
+ payload.rcc = rcc;
+
+ // TODO: we turned it to be sync, due to client_destroy . Should we support async? - for this we will need ref count
+ // for channels
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
+ &payload);
+}
+
+static void red_qxl_display_migrate(RedChannelClient *rcc)
+{
+ RedWorkerMessageDisplayMigrate payload;
+ RedDispatcher *dispatcher;
+ if (!rcc->channel) {
+ return;
+ }
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+ spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id);
+ payload.rcc = rcc;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
+ &payload);
+}
+
+static void red_qxl_set_cursor_peer(RedChannel *channel, RedClient *client, RedsStream *stream,
+ int migration, int num_common_caps,
+ uint32_t *common_caps, int num_caps,
+ uint32_t *caps)
+{
+ RedWorkerMessageCursorConnect payload = {0,};
+ RedDispatcher *dispatcher = (RedDispatcher *)channel->data;
+ spice_printerr("");
+ payload.client = client;
+ payload.stream = stream;
+ payload.migration = migration;
+ payload.num_common_caps = num_common_caps;
+ payload.common_caps = spice_malloc(sizeof(uint32_t)*num_common_caps);
+ payload.num_caps = num_caps;
+ payload.caps = spice_malloc(sizeof(uint32_t)*num_caps);
+
+ memcpy(payload.common_caps, common_caps, sizeof(uint32_t)*num_common_caps);
+ memcpy(payload.caps, caps, sizeof(uint32_t)*num_caps);
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_CURSOR_CONNECT,
+ &payload);
+}
+
+static void red_qxl_disconnect_cursor_peer(RedChannelClient *rcc)
+{
+ RedWorkerMessageCursorDisconnect payload;
+ RedDispatcher *dispatcher;
+
+ if (!rcc->channel) {
+ return;
+ }
+
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+ spice_printerr("");
+ payload.rcc = rcc;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
+ &payload);
+}
+
+static void red_qxl_cursor_migrate(RedChannelClient *rcc)
+{
+ RedWorkerMessageCursorMigrate payload;
+ RedDispatcher *dispatcher;
+
+ if (!rcc->channel) {
+ return;
+ }
+ dispatcher = (RedDispatcher *)rcc->channel->data;
+ spice_printerr("channel type %u id %u", rcc->channel->type, rcc->channel->id);
+ payload.rcc = rcc;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_CURSOR_MIGRATE,
+ &payload);
+}
+
+static void red_qxl_update_area(RedDispatcher *dispatcher, uint32_t surface_id,
+ QXLRect *qxl_area, QXLRect *qxl_dirty_rects,
+ uint32_t num_dirty_rects, uint32_t clear_dirty_region)
+{
+ RedWorkerMessageUpdate payload = {0,};
+
+ payload.surface_id = surface_id;
+ payload.qxl_area = qxl_area;
+ payload.qxl_dirty_rects = qxl_dirty_rects;
+ payload.num_dirty_rects = num_dirty_rects;
+ payload.clear_dirty_region = clear_dirty_region;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_UPDATE,
+ &payload);
+}
+
+gboolean red_qxl_use_client_monitors_config(RedDispatcher *dispatcher)
+{
+ return (red_qxl_check_qxl_version(dispatcher, 3, 3) &&
+ dispatcher->qxl->st->qif->client_monitors_config &&
+ dispatcher->qxl->st->qif->client_monitors_config(dispatcher->qxl, NULL));
+}
+
+gboolean red_qxl_client_monitors_config(RedDispatcher *dispatcher,
+ VDAgentMonitorsConfig *monitors_config)
+{
+ return (dispatcher->qxl->st->qif->client_monitors_config &&
+ dispatcher->qxl->st->qif->client_monitors_config(dispatcher->qxl,
+ monitors_config));
+}
+
+static AsyncCommand *async_command_alloc(RedDispatcher *dispatcher,
+ RedWorkerMessage message,
+ uint64_t cookie)
+{
+ AsyncCommand *async_command = spice_new0(AsyncCommand, 1);
+
+ async_command->cookie = cookie;
+ async_command->message = message;
+
+ spice_debug("%p", async_command);
+ return async_command;
+}
+
+static void red_qxl_update_area_async(RedDispatcher *dispatcher,
+ uint32_t surface_id,
+ QXLRect *qxl_area,
+ uint32_t clear_dirty_region,
+ uint64_t cookie)
+{
+ RedWorkerMessage message = RED_WORKER_MESSAGE_UPDATE_ASYNC;
+ RedWorkerMessageUpdateAsync payload;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ payload.surface_id = surface_id;
+ payload.qxl_area = *qxl_area;
+ payload.clear_dirty_region = clear_dirty_region;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ message,
+ &payload);
+}
+
+static void qxl_worker_update_area(QXLWorker *qxl_worker, uint32_t surface_id,
+ QXLRect *qxl_area, QXLRect *qxl_dirty_rects,
+ uint32_t num_dirty_rects, uint32_t clear_dirty_region)
+{
+ red_qxl_update_area((RedDispatcher*)qxl_worker, surface_id, qxl_area,
+ qxl_dirty_rects, num_dirty_rects, clear_dirty_region);
+}
+
+static void red_qxl_add_memslot(RedDispatcher *dispatcher, QXLDevMemSlot *mem_slot)
+{
+ RedWorkerMessageAddMemslot payload;
+
+ payload.mem_slot = *mem_slot;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_ADD_MEMSLOT,
+ &payload);
+}
+
+static void qxl_worker_add_memslot(QXLWorker *qxl_worker, QXLDevMemSlot *mem_slot)
+{
+ red_qxl_add_memslot((RedDispatcher*)qxl_worker, mem_slot);
+}
+
+static void red_qxl_add_memslot_async(RedDispatcher *dispatcher, QXLDevMemSlot *mem_slot, uint64_t cookie)
+{
+ RedWorkerMessageAddMemslotAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ payload.mem_slot = *mem_slot;
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void red_qxl_del_memslot(RedDispatcher *dispatcher, uint32_t slot_group_id, uint32_t slot_id)
+{
+ RedWorkerMessageDelMemslot payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_DEL_MEMSLOT;
+
+ payload.slot_group_id = slot_group_id;
+ payload.slot_id = slot_id;
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void qxl_worker_del_memslot(QXLWorker *qxl_worker, uint32_t slot_group_id, uint32_t slot_id)
+{
+ red_qxl_del_memslot((RedDispatcher*)qxl_worker, slot_group_id, slot_id);
+}
+
+static void red_qxl_destroy_surfaces(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageDestroySurfaces payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DESTROY_SURFACES,
+ &payload);
+}
+
+static void qxl_worker_destroy_surfaces(QXLWorker *qxl_worker)
+{
+ red_qxl_destroy_surfaces((RedDispatcher*)qxl_worker);
+}
+
+static void red_qxl_destroy_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
+{
+ RedWorkerMessageDestroySurfacesAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void red_qxl_destroy_primary_surface_complete(RedDispatcher *dispatcher)
+{
+ dispatcher->x_res = 0;
+ dispatcher->y_res = 0;
+ dispatcher->use_hardware_cursor = FALSE;
+ dispatcher->primary_active = FALSE;
+
+ reds_update_client_mouse_allowed(reds);
+}
+
+static void
+red_qxl_destroy_primary_surface_sync(RedDispatcher *dispatcher,
+ uint32_t surface_id)
+{
+ RedWorkerMessageDestroyPrimarySurface payload;
+ payload.surface_id = surface_id;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE,
+ &payload);
+ red_qxl_destroy_primary_surface_complete(dispatcher);
+}
+
+static void
+red_qxl_destroy_primary_surface_async(RedDispatcher *dispatcher,
+ uint32_t surface_id, uint64_t cookie)
+{
+ RedWorkerMessageDestroyPrimarySurfaceAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ payload.surface_id = surface_id;
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void
+red_qxl_destroy_primary_surface(RedDispatcher *dispatcher,
+ uint32_t surface_id, int async, uint64_t cookie)
+{
+ if (async) {
+ red_qxl_destroy_primary_surface_async(dispatcher, surface_id, cookie);
+ } else {
+ red_qxl_destroy_primary_surface_sync(dispatcher, surface_id);
+ }
+}
+
+static void qxl_worker_destroy_primary_surface(QXLWorker *qxl_worker, uint32_t surface_id)
+{
+ red_qxl_destroy_primary_surface((RedDispatcher*)qxl_worker, surface_id, 0, 0);
+}
+
+static void red_qxl_create_primary_surface_complete(RedDispatcher *dispatcher)
+{
+ QXLDevSurfaceCreate *surface = &dispatcher->surface_create;
+
+ dispatcher->x_res = surface->width;
+ dispatcher->y_res = surface->height;
+ dispatcher->use_hardware_cursor = surface->mouse_mode;
+ dispatcher->primary_active = TRUE;
+
+ reds_update_client_mouse_allowed(reds);
+ memset(&dispatcher->surface_create, 0, sizeof(QXLDevSurfaceCreate));
+}
+
+static void
+red_qxl_create_primary_surface_async(RedDispatcher *dispatcher, uint32_t surface_id,
+ QXLDevSurfaceCreate *surface, uint64_t cookie)
+{
+ RedWorkerMessageCreatePrimarySurfaceAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC;
+
+ dispatcher->surface_create = *surface;
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ payload.surface_id = surface_id;
+ payload.surface = *surface;
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void
+red_qxl_create_primary_surface_sync(RedDispatcher *dispatcher, uint32_t surface_id,
+ QXLDevSurfaceCreate *surface)
+{
+ RedWorkerMessageCreatePrimarySurface payload = {0,};
+
+ dispatcher->surface_create = *surface;
+ payload.surface_id = surface_id;
+ payload.surface = *surface;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE,
+ &payload);
+ red_qxl_create_primary_surface_complete(dispatcher);
+}
+
+static void
+red_qxl_create_primary_surface(RedDispatcher *dispatcher, uint32_t surface_id,
+ QXLDevSurfaceCreate *surface, int async, uint64_t cookie)
+{
+ if (async) {
+ red_qxl_create_primary_surface_async(dispatcher, surface_id, surface, cookie);
+ } else {
+ red_qxl_create_primary_surface_sync(dispatcher, surface_id, surface);
+ }
+}
+
+static void qxl_worker_create_primary_surface(QXLWorker *qxl_worker, uint32_t surface_id,
+ QXLDevSurfaceCreate *surface)
+{
+ red_qxl_create_primary_surface((RedDispatcher*)qxl_worker, surface_id, surface, 0, 0);
+}
+
+static void red_qxl_reset_image_cache(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageResetImageCache payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_RESET_IMAGE_CACHE,
+ &payload);
+}
+
+static void qxl_worker_reset_image_cache(QXLWorker *qxl_worker)
+{
+ red_qxl_reset_image_cache((RedDispatcher*)qxl_worker);
+}
+
+static void red_qxl_reset_cursor(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageResetCursor payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_RESET_CURSOR,
+ &payload);
+}
+
+static void qxl_worker_reset_cursor(QXLWorker *qxl_worker)
+{
+ red_qxl_reset_cursor((RedDispatcher*)qxl_worker);
+}
+
+static void red_qxl_destroy_surface_wait_sync(RedDispatcher *dispatcher,
+ uint32_t surface_id)
+{
+ RedWorkerMessageDestroySurfaceWait payload;
+
+ payload.surface_id = surface_id;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT,
+ &payload);
+}
+
+static void red_qxl_destroy_surface_wait_async(RedDispatcher *dispatcher,
+ uint32_t surface_id,
+ uint64_t cookie)
+{
+ RedWorkerMessageDestroySurfaceWaitAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ payload.surface_id = surface_id;
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void red_qxl_destroy_surface_wait(RedDispatcher *dispatcher,
+ uint32_t surface_id,
+ int async, uint64_t cookie)
+{
+ if (async) {
+ red_qxl_destroy_surface_wait_async(dispatcher, surface_id, cookie);
+ } else {
+ red_qxl_destroy_surface_wait_sync(dispatcher, surface_id);
+ }
+}
+
+static void qxl_worker_destroy_surface_wait(QXLWorker *qxl_worker, uint32_t surface_id)
+{
+ red_qxl_destroy_surface_wait((RedDispatcher*)qxl_worker, surface_id, 0, 0);
+}
+
+static void red_qxl_reset_memslots(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageResetMemslots payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_RESET_MEMSLOTS,
+ &payload);
+}
+
+static void qxl_worker_reset_memslots(QXLWorker *qxl_worker)
+{
+ red_qxl_reset_memslots((RedDispatcher*)qxl_worker);
+}
+
+static bool red_qxl_set_pending(RedDispatcher *dispatcher, int pending)
+{
+ // this is not atomic but is not an issue
+ if (test_bit(pending, dispatcher->pending)) {
+ return TRUE;
+ }
+
+ set_bit(pending, &dispatcher->pending);
+ return FALSE;
+}
+
+static void red_qxl_wakeup(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageWakeup payload;
+
+ if (red_qxl_set_pending(dispatcher, RED_DISPATCHER_PENDING_WAKEUP))
+ return;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_WAKEUP,
+ &payload);
+}
+
+static void qxl_worker_wakeup(QXLWorker *qxl_worker)
+{
+ red_qxl_wakeup((RedDispatcher*)qxl_worker);
+}
+
+static void red_qxl_oom(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageOom payload;
+
+ if (red_qxl_set_pending(dispatcher, RED_DISPATCHER_PENDING_OOM))
+ return;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_OOM,
+ &payload);
+}
+
+static void qxl_worker_oom(QXLWorker *qxl_worker)
+{
+ red_qxl_oom((RedDispatcher*)qxl_worker);
+}
+
+void red_qxl_start(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageStart payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_START,
+ &payload);
+}
+
+static void qxl_worker_start(QXLWorker *qxl_worker)
+{
+ red_qxl_start((RedDispatcher*)qxl_worker);
+}
+
+static void red_qxl_flush_surfaces_async(RedDispatcher *dispatcher, uint64_t cookie)
+{
+ RedWorkerMessageFlushSurfacesAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void red_qxl_monitors_config_async(RedDispatcher *dispatcher,
+ QXLPHYSICAL monitors_config,
+ int group_id,
+ uint64_t cookie)
+{
+ RedWorkerMessageMonitorsConfigAsync payload;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC;
+
+ payload.base.cmd = async_command_alloc(dispatcher, message, cookie);
+ payload.monitors_config = monitors_config;
+ payload.group_id = group_id;
+ payload.max_monitors = dispatcher->max_monitors;
+
+ dispatcher_send_message(&dispatcher->dispatcher, message, &payload);
+}
+
+static void red_qxl_driver_unload(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageDriverUnload payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_DRIVER_UNLOAD,
+ &payload);
+}
+
+void red_qxl_stop(RedDispatcher *dispatcher)
+{
+ RedWorkerMessageStop payload;
+
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_STOP,
+ &payload);
+}
+
+static void qxl_worker_stop(QXLWorker *qxl_worker)
+{
+ red_qxl_stop((RedDispatcher*)qxl_worker);
+}
+
+static void red_qxl_loadvm_commands(RedDispatcher *dispatcher,
+ struct QXLCommandExt *ext,
+ uint32_t count)
+{
+ RedWorkerMessageLoadvmCommands payload;
+
+ spice_printerr("");
+ payload.count = count;
+ payload.ext = ext;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_LOADVM_COMMANDS,
+ &payload);
+}
+
+static void qxl_worker_loadvm_commands(QXLWorker *qxl_worker,
+ struct QXLCommandExt *ext,
+ uint32_t count)
+{
+ red_qxl_loadvm_commands((RedDispatcher*)qxl_worker, ext, count);
+}
+
+void red_qxl_set_mm_time(RedDispatcher *dispatcher, uint32_t mm_time)
+{
+ dispatcher->qxl->st->qif->set_mm_time(dispatcher->qxl, mm_time);
+}
+
+void red_qxl_attach_worker(RedDispatcher *dispatcher)
+{
+ QXLInstance *qxl = dispatcher->qxl;
+ qxl->st->qif->attache_worker(qxl, &dispatcher->base);
+}
+
+void red_qxl_set_compression_level(RedDispatcher *dispatcher, int level)
+{
+ dispatcher->qxl->st->qif->set_compression_level(dispatcher->qxl, level);
+}
+
+uint32_t red_qxl_get_ram_size(RedDispatcher *dispatcher)
+{
+ QXLDevInitInfo qxl_info;
+ dispatcher->qxl->st->qif->get_init_info(dispatcher->qxl, &qxl_info);
+ return qxl_info.qxl_ram_size;
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_wakeup(QXLInstance *instance)
+{
+ red_qxl_wakeup(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_oom(QXLInstance *instance)
+{
+ red_qxl_oom(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_start(QXLInstance *instance)
+{
+ red_qxl_start(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_stop(QXLInstance *instance)
+{
+ red_qxl_stop(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_update_area(QXLInstance *instance, uint32_t surface_id,
+ struct QXLRect *area, struct QXLRect *dirty_rects,
+ uint32_t num_dirty_rects, uint32_t clear_dirty_region)
+{
+ red_qxl_update_area(instance->st->dispatcher, surface_id, area, dirty_rects,
+ num_dirty_rects, clear_dirty_region);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_add_memslot(QXLInstance *instance, QXLDevMemSlot *slot)
+{
+ red_qxl_add_memslot(instance->st->dispatcher, slot);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_del_memslot(QXLInstance *instance, uint32_t slot_group_id, uint32_t slot_id)
+{
+ red_qxl_del_memslot(instance->st->dispatcher, slot_group_id, slot_id);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_reset_memslots(QXLInstance *instance)
+{
+ red_qxl_reset_memslots(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_destroy_surfaces(QXLInstance *instance)
+{
+ red_qxl_destroy_surfaces(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_destroy_primary_surface(QXLInstance *instance, uint32_t surface_id)
+{
+ red_qxl_destroy_primary_surface(instance->st->dispatcher, surface_id, 0, 0);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_create_primary_surface(QXLInstance *instance, uint32_t surface_id,
+ QXLDevSurfaceCreate *surface)
+{
+ red_qxl_create_primary_surface(instance->st->dispatcher, surface_id, surface, 0, 0);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_reset_image_cache(QXLInstance *instance)
+{
+ red_qxl_reset_image_cache(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_reset_cursor(QXLInstance *instance)
+{
+ red_qxl_reset_cursor(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_destroy_surface_wait(QXLInstance *instance, uint32_t surface_id)
+{
+ red_qxl_destroy_surface_wait(instance->st->dispatcher, surface_id, 0, 0);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_loadvm_commands(QXLInstance *instance, struct QXLCommandExt *ext, uint32_t count)
+{
+ red_qxl_loadvm_commands(instance->st->dispatcher, ext, count);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_update_area_async(QXLInstance *instance, uint32_t surface_id, QXLRect *qxl_area,
+ uint32_t clear_dirty_region, uint64_t cookie)
+{
+ red_qxl_update_area_async(instance->st->dispatcher, surface_id, qxl_area,
+ clear_dirty_region, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_add_memslot_async(QXLInstance *instance, QXLDevMemSlot *slot, uint64_t cookie)
+{
+ red_qxl_add_memslot_async(instance->st->dispatcher, slot, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_destroy_surfaces_async(QXLInstance *instance, uint64_t cookie)
+{
+ red_qxl_destroy_surfaces_async(instance->st->dispatcher, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_destroy_primary_surface_async(QXLInstance *instance, uint32_t surface_id, uint64_t cookie)
+{
+ red_qxl_destroy_primary_surface(instance->st->dispatcher, surface_id, 1, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_create_primary_surface_async(QXLInstance *instance, uint32_t surface_id,
+ QXLDevSurfaceCreate *surface, uint64_t cookie)
+{
+ red_qxl_create_primary_surface(instance->st->dispatcher, surface_id, surface, 1, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_destroy_surface_async(QXLInstance *instance, uint32_t surface_id, uint64_t cookie)
+{
+ red_qxl_destroy_surface_wait(instance->st->dispatcher, surface_id, 1, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_flush_surfaces_async(QXLInstance *instance, uint64_t cookie)
+{
+ red_qxl_flush_surfaces_async(instance->st->dispatcher, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_monitors_config_async(QXLInstance *instance, QXLPHYSICAL monitors_config,
+ int group_id, uint64_t cookie)
+{
+ red_qxl_monitors_config_async(instance->st->dispatcher, monitors_config, group_id, cookie);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_set_max_monitors(QXLInstance *instance, unsigned int max_monitors)
+{
+ instance->st->dispatcher->max_monitors = MAX(1u, max_monitors);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_driver_unload(QXLInstance *instance)
+{
+ red_qxl_driver_unload(instance->st->dispatcher);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_gl_scanout(QXLInstance *qxl,
+ int fd,
+ uint32_t width, uint32_t height,
+ uint32_t stride, uint32_t format,
+ int y_0_top)
+{
+ spice_return_if_fail(qxl != NULL);
+ spice_return_if_fail(qxl->st->gl_draw_async == NULL);
+
+ pthread_mutex_lock(&qxl->st->scanout_mutex);
+
+ if (qxl->st->scanout.drm_dma_buf_fd != -1) {
+ close(qxl->st->scanout.drm_dma_buf_fd);
+ }
+
+ qxl->st->scanout = (SpiceMsgDisplayGlScanoutUnix) {
+ .flags = y_0_top ? SPICE_GL_SCANOUT_FLAGS_Y0TOP : 0,
+ .drm_dma_buf_fd = fd,
+ .width = width,
+ .height = height,
+ .stride = stride,
+ .drm_fourcc_format = format
+ };
+
+ pthread_mutex_unlock(&qxl->st->scanout_mutex);
+
+ /* FIXME: find a way to coallesce all pending SCANOUTs */
+ dispatcher_send_message(&qxl->st->dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_GL_SCANOUT, NULL);
+}
+
+SPICE_GNUC_VISIBLE
+void spice_qxl_gl_draw_async(QXLInstance *qxl,
+ uint32_t x, uint32_t y,
+ uint32_t w, uint32_t h,
+ uint64_t cookie)
+{
+ RedDispatcher *dispatcher;
+ RedWorkerMessage message = RED_WORKER_MESSAGE_GL_DRAW_ASYNC;
+ SpiceMsgDisplayGlDraw draw = {
+ .x = x,
+ .y = y,
+ .w = w,
+ .h = h
+ };
+
+ spice_return_if_fail(qxl != NULL);
+ spice_return_if_fail(qxl->st->scanout.drm_dma_buf_fd != -1);
+ spice_return_if_fail(qxl->st->gl_draw_async == NULL);
+
+ dispatcher = qxl->st->dispatcher;
+ qxl->st->gl_draw_async = async_command_alloc(dispatcher, message, cookie);
+ dispatcher_send_message(&dispatcher->dispatcher, message, &draw);
+}
+
+void red_qxl_async_complete(struct RedDispatcher *dispatcher,
+ AsyncCommand *async_command)
+{
+ spice_debug("%p: cookie %" PRId64, async_command, async_command->cookie);
+ switch (async_command->message) {
+ case RED_WORKER_MESSAGE_UPDATE_ASYNC:
+ case RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC:
+ case RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC:
+ case RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC:
+ case RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC:
+ case RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC:
+ case RED_WORKER_MESSAGE_GL_DRAW_ASYNC:
+ break;
+ case RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC:
+ red_qxl_create_primary_surface_complete(dispatcher);
+ break;
+ case RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC:
+ red_qxl_destroy_primary_surface_complete(dispatcher);
+ break;
+ default:
+ spice_warning("unexpected message %d", async_command->message);
+ }
+ dispatcher->qxl->st->qif->async_complete(dispatcher->qxl,
+ async_command->cookie);
+ free(async_command);
+}
+
+void red_qxl_init(QXLInstance *qxl)
+{
+ RedDispatcher *red_dispatcher;
+ RedChannel *channel;
+ ClientCbs client_cbs = { NULL, };
+
+ spice_return_if_fail(qxl != NULL);
+ spice_return_if_fail(qxl->st->dispatcher == NULL);
+
+ static gsize initialized = FALSE;
+ if (g_once_init_enter(&initialized)) {
+ quic_init();
+ sw_canvas_init();
+ g_once_init_leave(&initialized, TRUE);
+ }
+
+ red_dispatcher = spice_new0(RedDispatcher, 1);
+ red_dispatcher->qxl = qxl;
+ dispatcher_init(&red_dispatcher->dispatcher, RED_WORKER_MESSAGE_COUNT, NULL);
+ red_dispatcher->base.major_version = SPICE_INTERFACE_QXL_MAJOR;
+ red_dispatcher->base.minor_version = SPICE_INTERFACE_QXL_MINOR;
+ red_dispatcher->base.wakeup = qxl_worker_wakeup;
+ red_dispatcher->base.oom = qxl_worker_oom;
+ red_dispatcher->base.start = qxl_worker_start;
+ red_dispatcher->base.stop = qxl_worker_stop;
+ red_dispatcher->base.update_area = qxl_worker_update_area;
+ red_dispatcher->base.add_memslot = qxl_worker_add_memslot;
+ red_dispatcher->base.del_memslot = qxl_worker_del_memslot;
+ red_dispatcher->base.reset_memslots = qxl_worker_reset_memslots;
+ red_dispatcher->base.destroy_surfaces = qxl_worker_destroy_surfaces;
+ red_dispatcher->base.create_primary_surface = qxl_worker_create_primary_surface;
+ red_dispatcher->base.destroy_primary_surface = qxl_worker_destroy_primary_surface;
+
+ red_dispatcher->base.reset_image_cache = qxl_worker_reset_image_cache;
+ red_dispatcher->base.reset_cursor = qxl_worker_reset_cursor;
+ red_dispatcher->base.destroy_surface_wait = qxl_worker_destroy_surface_wait;
+ red_dispatcher->base.loadvm_commands = qxl_worker_loadvm_commands;
+
+ red_dispatcher->max_monitors = UINT_MAX;
+
+ // TODO: reference and free
+ RedWorker *worker = red_worker_new(qxl, red_dispatcher);
+
+ // TODO: move to their respective channel files
+ channel = red_worker_get_cursor_channel(worker);
+ client_cbs.connect = red_qxl_set_cursor_peer;
+ client_cbs.disconnect = red_qxl_disconnect_cursor_peer;
+ client_cbs.migrate = red_qxl_cursor_migrate;
+ red_channel_register_client_cbs(channel, &client_cbs);
+ red_channel_set_data(channel, red_dispatcher);
+ reds_register_channel(reds, channel);
+
+ channel = red_worker_get_display_channel(worker);
+ client_cbs.connect = red_qxl_set_display_peer;
+ client_cbs.disconnect = red_qxl_disconnect_display_peer;
+ client_cbs.migrate = red_qxl_display_migrate;
+ red_channel_register_client_cbs(channel, &client_cbs);
+ red_channel_set_data(channel, red_dispatcher);
+ red_channel_set_cap(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
+ red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
+ red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
+ reds_register_channel(reds, channel);
+
+ red_worker_run(worker);
+
+ qxl->st->dispatcher = red_dispatcher;
+}
+
+struct Dispatcher *red_qxl_get_dispatcher(RedDispatcher *red_dispatcher)
+{
+ return &red_dispatcher->dispatcher;
+}
+
+void red_qxl_set_dispatcher_opaque(RedDispatcher *red_dispatcher,
+ void *opaque)
+{
+ dispatcher_set_opaque(&red_dispatcher->dispatcher, opaque);
+}
+
+void red_qxl_clear_pending(RedDispatcher *red_dispatcher, int pending)
+{
+ spice_return_if_fail(red_dispatcher != NULL);
+
+ clear_bit(pending, &red_dispatcher->pending);
+}
+
+gboolean red_qxl_get_primary_active(RedDispatcher *dispatcher)
+{
+ return dispatcher->primary_active;
+}
+
+gboolean red_qxl_get_allow_client_mouse(RedDispatcher *dispatcher, gint *x_res, gint *y_res)
+{
+ if (dispatcher->use_hardware_cursor) {
+ if (x_res)
+ *x_res = dispatcher->x_res;
+ if (y_res)
+ *y_res = dispatcher->y_res;
+ }
+ return dispatcher->use_hardware_cursor;
+}
+
+void red_qxl_on_ic_change(RedDispatcher *dispatcher, SpiceImageCompression ic)
+{
+ RedWorkerMessageSetCompression payload;
+ payload.image_compression = ic;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_SET_COMPRESSION,
+ &payload);
+}
+
+void red_qxl_on_sv_change(RedDispatcher *dispatcher, int sv)
+{
+ RedWorkerMessageSetStreamingVideo payload;
+ payload.streaming_video = sv;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
+ &payload);
+}
+
+void red_qxl_set_mouse_mode(RedDispatcher *dispatcher, uint32_t mode)
+{
+ RedWorkerMessageSetMouseMode payload;
+ payload.mode = mode;
+ dispatcher_send_message(&dispatcher->dispatcher,
+ RED_WORKER_MESSAGE_SET_MOUSE_MODE,
+ &payload);
+}
diff --git a/server/red-qxl.h b/server/red-qxl.h
new file mode 100644
index 0000000..1348e6c
--- /dev/null
+++ b/server/red-qxl.h
@@ -0,0 +1,272 @@
+/*
+ Copyright (C) 2009 Red Hat, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _H_RED_DISPATCHER
+#define _H_RED_DISPATCHER
+
+#include "red-channel.h"
+
+typedef struct RedDispatcher RedDispatcher;
+
+typedef struct AsyncCommand AsyncCommand;
+
+void red_qxl_init(QXLInstance *qxl);
+
+void red_qxl_set_mm_time(RedDispatcher *dispatcher, uint32_t);
+void red_qxl_on_ic_change(RedDispatcher *dispatcher, SpiceImageCompression ic);
+void red_qxl_on_sv_change(RedDispatcher *dispatcher, int sv);
+void red_qxl_set_mouse_mode(RedDispatcher *dispatcher, uint32_t mode);
+void red_qxl_attach_worker(RedDispatcher *dispatcher);
+void red_qxl_set_compression_level(RedDispatcher *dispatcher, int level);
+void red_qxl_stop(RedDispatcher *dispatcher);
+void red_qxl_start(RedDispatcher *dispatcher);
+uint32_t red_qxl_get_ram_size(RedDispatcher *dispatcher);
+void red_qxl_async_complete(struct RedDispatcher *, AsyncCommand *);
+struct Dispatcher *red_qxl_get_dispatcher(struct RedDispatcher *);
+gboolean red_qxl_use_client_monitors_config(RedDispatcher *dispatcher);
+gboolean red_qxl_client_monitors_config(RedDispatcher *dispatcher, VDAgentMonitorsConfig *monitors_config);
+gboolean red_qxl_get_primary_active(RedDispatcher *dispatcher);
+gboolean red_qxl_get_allow_client_mouse(RedDispatcher *dispatcher, gint *x_res, gint *y_res);
+
+typedef uint32_t RedWorkerMessage;
+
+/* Keep message order, only append new messages!
+ * Replay code store enum values into save files.
+ */
+enum {
+ RED_WORKER_MESSAGE_NOP,
+
+ RED_WORKER_MESSAGE_UPDATE,
+ RED_WORKER_MESSAGE_WAKEUP,
+ RED_WORKER_MESSAGE_OOM,
+ RED_WORKER_MESSAGE_READY, /* unused */
+
+ RED_WORKER_MESSAGE_DISPLAY_CONNECT,
+ RED_WORKER_MESSAGE_DISPLAY_DISCONNECT,
+ RED_WORKER_MESSAGE_DISPLAY_MIGRATE,
+ RED_WORKER_MESSAGE_START,
+ RED_WORKER_MESSAGE_STOP,
+ RED_WORKER_MESSAGE_CURSOR_CONNECT,
+ RED_WORKER_MESSAGE_CURSOR_DISCONNECT,
+ RED_WORKER_MESSAGE_CURSOR_MIGRATE,
+ RED_WORKER_MESSAGE_SET_COMPRESSION,
+ RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
+ RED_WORKER_MESSAGE_SET_MOUSE_MODE,
+ 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,
+ RED_WORKER_MESSAGE_LOADVM_COMMANDS,
+ /* async commands */
+ RED_WORKER_MESSAGE_UPDATE_ASYNC,
+ RED_WORKER_MESSAGE_ADD_MEMSLOT_ASYNC,
+ RED_WORKER_MESSAGE_DESTROY_SURFACES_ASYNC,
+ RED_WORKER_MESSAGE_CREATE_PRIMARY_SURFACE_ASYNC,
+ RED_WORKER_MESSAGE_DESTROY_PRIMARY_SURFACE_ASYNC,
+ RED_WORKER_MESSAGE_DESTROY_SURFACE_WAIT_ASYNC,
+ /* suspend/windows resolution change command */
+ RED_WORKER_MESSAGE_FLUSH_SURFACES_ASYNC,
+
+ RED_WORKER_MESSAGE_DISPLAY_CHANNEL_CREATE, /* unused */
+ RED_WORKER_MESSAGE_CURSOR_CHANNEL_CREATE, /* unused */
+
+ RED_WORKER_MESSAGE_MONITORS_CONFIG_ASYNC,
+ RED_WORKER_MESSAGE_DRIVER_UNLOAD,
+ RED_WORKER_MESSAGE_GL_SCANOUT,
+ RED_WORKER_MESSAGE_GL_DRAW_ASYNC,
+
+ RED_WORKER_MESSAGE_COUNT // LAST
+};
+
+typedef struct RedWorkerMessageDisplayConnect {
+ RedClient * client;
+ RedsStream * stream;
+ uint32_t *common_caps; // red_worker should free
+ uint32_t *caps; // red_worker should free
+ int migration;
+ int num_common_caps;
+ int num_caps;
+} RedWorkerMessageDisplayConnect;
+
+typedef struct RedWorkerMessageDisplayDisconnect {
+ RedChannelClient *rcc;
+} RedWorkerMessageDisplayDisconnect;
+
+typedef struct RedWorkerMessageDisplayMigrate {
+ RedChannelClient *rcc;
+} RedWorkerMessageDisplayMigrate;
+
+typedef struct RedWorkerMessageCursorConnect {
+ RedClient *client;
+ RedsStream *stream;
+ int migration;
+ uint32_t *common_caps; // red_worker should free
+ int num_common_caps;
+ uint32_t *caps; // red_worker should free
+ int num_caps;
+} RedWorkerMessageCursorConnect;
+
+typedef struct RedWorkerMessageCursorDisconnect {
+ RedChannelClient *rcc;
+} RedWorkerMessageCursorDisconnect;
+
+typedef struct RedWorkerMessageCursorMigrate {
+ RedChannelClient *rcc;
+} RedWorkerMessageCursorMigrate;
+
+typedef struct RedWorkerMessageUpdate {
+ uint32_t surface_id;
+ QXLRect * qxl_area;
+ QXLRect * qxl_dirty_rects;
+ uint32_t num_dirty_rects;
+ uint32_t clear_dirty_region;
+} RedWorkerMessageUpdate;
+
+typedef struct RedWorkerMessageAsync {
+ AsyncCommand *cmd;
+} RedWorkerMessageAsync;
+
+typedef struct RedWorkerMessageUpdateAsync {
+ RedWorkerMessageAsync base;
+ uint32_t surface_id;
+ QXLRect qxl_area;
+ uint32_t clear_dirty_region;
+} RedWorkerMessageUpdateAsync;
+
+typedef struct RedWorkerMessageAddMemslot {
+ QXLDevMemSlot mem_slot;
+} RedWorkerMessageAddMemslot;
+
+typedef struct RedWorkerMessageAddMemslotAsync {
+ RedWorkerMessageAsync base;
+ QXLDevMemSlot mem_slot;
+} RedWorkerMessageAddMemslotAsync;
+
+typedef struct RedWorkerMessageDelMemslot {
+ uint32_t slot_group_id;
+ uint32_t slot_id;
+} RedWorkerMessageDelMemslot;
+
+typedef struct RedWorkerMessageDestroySurfaces {
+} RedWorkerMessageDestroySurfaces;
+
+typedef struct RedWorkerMessageDestroySurfacesAsync {
+ RedWorkerMessageAsync base;
+} RedWorkerMessageDestroySurfacesAsync;
+
+
+typedef struct RedWorkerMessageDestroyPrimarySurface {
+ uint32_t surface_id;
+} RedWorkerMessageDestroyPrimarySurface;
+
+typedef struct RedWorkerMessageDestroyPrimarySurfaceAsync {
+ RedWorkerMessageAsync base;
+ uint32_t surface_id;
+} RedWorkerMessageDestroyPrimarySurfaceAsync;
+
+typedef struct RedWorkerMessageCreatePrimarySurfaceAsync {
+ RedWorkerMessageAsync base;
+ uint32_t surface_id;
+ QXLDevSurfaceCreate surface;
+} RedWorkerMessageCreatePrimarySurfaceAsync;
+
+typedef struct RedWorkerMessageCreatePrimarySurface {
+ uint32_t surface_id;
+ QXLDevSurfaceCreate surface;
+} RedWorkerMessageCreatePrimarySurface;
+
+typedef struct RedWorkerMessageResetImageCache {
+} RedWorkerMessageResetImageCache;
+
+typedef struct RedWorkerMessageResetCursor {
+} RedWorkerMessageResetCursor;
+
+typedef struct RedWorkerMessageWakeup {
+} RedWorkerMessageWakeup;
+
+typedef struct RedWorkerMessageOom {
+} RedWorkerMessageOom;
+
+typedef struct RedWorkerMessageStart {
+} RedWorkerMessageStart;
+
+typedef struct RedWorkerMessageFlushSurfacesAsync {
+ RedWorkerMessageAsync base;
+} RedWorkerMessageFlushSurfacesAsync;
+
+typedef struct RedWorkerMessageStop {
+} RedWorkerMessageStop;
+
+/* this command is sync, so it's ok to pass a pointer */
+typedef struct RedWorkerMessageLoadvmCommands {
+ uint32_t count;
+ QXLCommandExt *ext;
+} RedWorkerMessageLoadvmCommands;
+
+typedef struct RedWorkerMessageSetCompression {
+ SpiceImageCompression image_compression;
+} RedWorkerMessageSetCompression;
+
+typedef struct RedWorkerMessageSetStreamingVideo {
+ uint32_t streaming_video;
+} RedWorkerMessageSetStreamingVideo;
+
+typedef struct RedWorkerMessageSetMouseMode {
+ uint32_t mode;
+} RedWorkerMessageSetMouseMode;
+
+typedef struct RedWorkerMessageDisplayChannelCreate {
+} RedWorkerMessageDisplayChannelCreate;
+
+typedef struct RedWorkerMessageCursorChannelCreate {
+} RedWorkerMessageCursorChannelCreate;
+
+typedef struct RedWorkerMessageDestroySurfaceWait {
+ uint32_t surface_id;
+} RedWorkerMessageDestroySurfaceWait;
+
+typedef struct RedWorkerMessageDestroySurfaceWaitAsync {
+ RedWorkerMessageAsync base;
+ uint32_t surface_id;
+} RedWorkerMessageDestroySurfaceWaitAsync;
+
+typedef struct RedWorkerMessageResetMemslots {
+} RedWorkerMessageResetMemslots;
+
+typedef struct RedWorkerMessageMonitorsConfigAsync {
+ RedWorkerMessageAsync base;
+ QXLPHYSICAL monitors_config;
+ int group_id;
+ unsigned int max_monitors;
+} RedWorkerMessageMonitorsConfigAsync;
+
+typedef struct RedWorkerMessageDriverUnload {
+} RedWorkerMessageDriverUnload;
+
+enum {
+ RED_DISPATCHER_PENDING_WAKEUP,
+ RED_DISPATCHER_PENDING_OOM,
+};
+
+void red_qxl_clear_pending(RedDispatcher *red_dispatcher, int pending);
+
+#endif
diff --git a/server/red-worker.h b/server/red-worker.h
index b22d41d..e51e261 100644
--- a/server/red-worker.h
+++ b/server/red-worker.h
@@ -19,7 +19,7 @@
#define _H_REDWORKER
#include "red-common.h"
-#include "red-dispatcher.h"
+#include "red-qxl.h"
#include "red-parse-qxl.h"
typedef struct RedWorker RedWorker;
diff --git a/server/reds.c b/server/reds.c
index b8f8cbc..ab923e9 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -57,7 +57,7 @@
#include "agent-msg-filter.h"
#include "inputs-channel.h"
#include "main-channel.h"
-#include "red-dispatcher.h"
+#include "red-qxl.h"
#include "main-dispatcher.h"
#include "sound.h"
#include "stat.h"
diff --git a/server/sound.c b/server/sound.c
index 6d64ad2..1aa3a74 100644
--- a/server/sound.c
+++ b/server/sound.c
@@ -33,7 +33,7 @@
#include "red-common.h"
#include "main-channel.h"
#include "reds.h"
-#include "red-dispatcher.h"
+#include "red-qxl.h"
#include "sound.h"
#include "common/snd_codec.h"
#include "demarshallers.h"
--
2.5.0
More information about the Spice-devel
mailing list