[Spice-devel] [PATCH v2 2/4] rename red-dispatcher.* files to red-qxl.*
Jonathon Jongsma
jjongsma at redhat.com
Thu Mar 3 17:40:24 UTC 2016
Acked-by: Jonathon Jongsma <jjongsma at redhat.com>
On Thu, 2016-03-03 at 16:28 +0000, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio <fziglio 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 decf846..8ab4bbd 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 54891c5..227c6f1 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"
More information about the Spice-devel
mailing list