[Spice-devel] [PATCH 1/4] Move CommonGraphicsChannel to a new file
Jonathon Jongsma
jjongsma at redhat.com
Fri Oct 7 22:01:34 UTC 2016
Move out of red-worker.c. This requires a little bit of minor
refactoring to avoid accessing some RedWorker internals in the
constructor function, etc.
---
server/Makefile.am | 2 +
server/common-graphics-channel.c | 129 +++++++++++++++++++++++++++++++++++++++
server/common-graphics-channel.h | 89 +++++++++++++++++++++++++++
server/cursor-channel-client.c | 1 +
server/cursor-channel.c | 11 ++--
server/cursor-channel.h | 5 +-
server/display-channel.c | 9 +--
server/display-channel.h | 6 +-
server/red-worker.c | 117 +++--------------------------------
server/red-worker.h | 64 +------------------
10 files changed, 248 insertions(+), 185 deletions(-)
create mode 100644 server/common-graphics-channel.c
create mode 100644 server/common-graphics-channel.h
diff --git a/server/Makefile.am b/server/Makefile.am
index f217399..3382946 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -77,6 +77,8 @@ libserver_la_SOURCES = \
cache-item.h \
char-device.c \
char-device.h \
+ common-graphics-channel.c \
+ common-graphics-channel.h \
demarshallers.h \
event-loop.c \
glz-encoder.c \
diff --git a/server/common-graphics-channel.c b/server/common-graphics-channel.c
new file mode 100644
index 0000000..625162c
--- /dev/null
+++ b/server/common-graphics-channel.c
@@ -0,0 +1,129 @@
+/*
+ Copyright (C) 2009-2016 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 <fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include "common-graphics-channel.h"
+#include "dcc.h"
+#include "main-channel-client.h"
+
+static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
+{
+ RedChannel *channel = red_channel_client_get_channel(rcc);
+ CommonGraphicsChannel *common = SPICE_CONTAINEROF(channel, CommonGraphicsChannel, base);
+
+ /* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is dynamic */
+ if (type == SPICE_MSGC_MIGRATE_DATA) {
+ return spice_malloc(size);
+ }
+
+ if (size > CHANNEL_RECEIVE_BUF_SIZE) {
+ spice_critical("unexpected message size %u (max is %d)", size, CHANNEL_RECEIVE_BUF_SIZE);
+ return NULL;
+ }
+ return common->recv_buf;
+}
+
+static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
+ uint8_t* msg)
+{
+ if (type == SPICE_MSGC_MIGRATE_DATA) {
+ free(msg);
+ }
+}
+
+int common_channel_config_socket(RedChannelClient *rcc)
+{
+ RedClient *client = red_channel_client_get_client(rcc);
+ MainChannelClient *mcc = red_client_get_main(client);
+ RedsStream *stream = red_channel_client_get_stream(rcc);
+ int flags;
+ int delay_val;
+ gboolean is_low_bandwidth;
+
+ if ((flags = fcntl(stream->socket, F_GETFL)) == -1) {
+ spice_warning("accept failed, %s", strerror(errno));
+ return FALSE;
+ }
+
+ if (fcntl(stream->socket, F_SETFL, flags | O_NONBLOCK) == -1) {
+ spice_warning("accept failed, %s", strerror(errno));
+ return FALSE;
+ }
+
+ // TODO - this should be dynamic, not one time at channel creation
+ is_low_bandwidth = main_channel_client_is_low_bandwidth(mcc);
+ delay_val = is_low_bandwidth ? 0 : 1;
+ /* FIXME: Using Nagle's Algorithm can lead to apparent delays, depending
+ * on the delayed ack timeout on the other side.
+ * Instead of using Nagle's, we need to implement message buffering on
+ * the application level.
+ * see: http://www.stuartcheshire.org/papers/NagleDelayedAck/
+ */
+ if (setsockopt(stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
+ sizeof(delay_val)) == -1) {
+ if (errno != ENOTSUP) {
+ spice_warning("setsockopt failed, %s", strerror(errno));
+ }
+ }
+ // TODO: move wide/narrow ack setting to red_channel.
+ red_channel_client_ack_set_client_window(rcc,
+ is_low_bandwidth ?
+ WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
+ return TRUE;
+}
+
+CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
+ QXLInstance *qxl,
+ const SpiceCoreInterfaceInternal *core,
+ int size, uint32_t channel_type,
+ int migration_flags,
+ ChannelCbs *channel_cbs,
+ channel_handle_parsed_proc handle_parsed)
+{
+ RedChannel *channel = NULL;
+ CommonGraphicsChannel *common;
+
+ spice_return_val_if_fail(channel_cbs, NULL);
+ spice_return_val_if_fail(!channel_cbs->alloc_recv_buf, NULL);
+ spice_return_val_if_fail(!channel_cbs->release_recv_buf, NULL);
+
+ if (!channel_cbs->config_socket)
+ channel_cbs->config_socket = common_channel_config_socket;
+ channel_cbs->alloc_recv_buf = common_alloc_recv_buf;
+ channel_cbs->release_recv_buf = common_release_recv_buf;
+
+ channel = red_channel_create_parser(size, server,
+ core, channel_type,
+ qxl->id, TRUE /* handle_acks */,
+ spice_get_client_channel_parser(channel_type, NULL),
+ handle_parsed,
+ channel_cbs,
+ migration_flags);
+ spice_return_val_if_fail(channel, NULL);
+
+ common = (CommonGraphicsChannel *)channel;
+ common->qxl = qxl;
+ return common;
+}
+
diff --git a/server/common-graphics-channel.h b/server/common-graphics-channel.h
new file mode 100644
index 0000000..7b2aeff
--- /dev/null
+++ b/server/common-graphics-channel.h
@@ -0,0 +1,89 @@
+/*
+ Copyright (C) 2009-2016 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 _COMMON_GRAPHICS_CHANNEL_H
+#define _COMMON_GRAPHICS_CHANNEL_H
+
+#include "red-channel.h"
+#include "red-worker.h"
+
+int common_channel_config_socket(RedChannelClient *rcc);
+
+#define COMMON_CLIENT_TIMEOUT (NSEC_PER_SEC * 30)
+
+#define CHANNEL_RECEIVE_BUF_SIZE 1024
+typedef struct CommonGraphicsChannel {
+ RedChannel base; // Must be the first thing
+
+ QXLInstance *qxl;
+ uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE];
+ int during_target_migrate; /* TRUE when the client that is associated with the channel
+ is during migration. Turned off when the vm is started.
+ The flag is used to avoid sending messages that are artifacts
+ of the transition from stopped vm to loaded vm (e.g., recreation
+ of the primary surface) */
+} CommonGraphicsChannel;
+
+#define COMMON_GRAPHICS_CHANNEL(Channel) ((CommonGraphicsChannel*)(Channel))
+
+enum {
+ RED_PIPE_ITEM_TYPE_VERB = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
+ RED_PIPE_ITEM_TYPE_INVAL_ONE,
+
+ RED_PIPE_ITEM_TYPE_COMMON_LAST
+};
+
+typedef struct RedVerbItem {
+ RedPipeItem base;
+ uint16_t verb;
+} RedVerbItem;
+
+static inline void red_marshall_verb(RedChannelClient *rcc, RedVerbItem *item)
+{
+ red_channel_client_init_send_data(rcc, item->verb, NULL);
+}
+
+static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb)
+{
+ RedVerbItem *item = spice_new(RedVerbItem, 1);
+
+ red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_VERB);
+ item->verb = verb;
+ red_channel_client_pipe_add(rcc, &item->base);
+}
+
+static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer data)
+{
+ uint16_t verb = GPOINTER_TO_UINT(data);
+ red_pipe_add_verb(rcc, verb);
+}
+
+
+static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
+{
+ red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy, GUINT_TO_POINTER(verb));
+}
+
+CommonGraphicsChannel* common_graphics_channel_new(RedsState *server,
+ QXLInstance *qxl,
+ const SpiceCoreInterfaceInternal *core,
+ int size, uint32_t channel_type,
+ int migration_flags,
+ ChannelCbs *channel_cbs,
+ channel_handle_parsed_proc handle_parsed);
+
+#endif /* _COMMON_GRAPHICS_CHANNEL_H */
diff --git a/server/cursor-channel-client.c b/server/cursor-channel-client.c
index 25082d7..90778ed 100644
--- a/server/cursor-channel-client.c
+++ b/server/cursor-channel-client.c
@@ -21,6 +21,7 @@
#include <common/generated_server_marshallers.h>
+#include "common-graphics-channel.h"
#include "red-channel-client.h"
#include "cache-item.h"
#include "cursor-channel.h"
diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index b152697..c73745f 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -22,6 +22,7 @@
#include <glib.h>
#include <common/generated_server_marshallers.h>
+#include "common-graphics-channel.h"
#include "cursor-channel.h"
#include "cursor-channel-client.h"
#include "reds.h"
@@ -308,7 +309,8 @@ static void cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
red_channel_client_begin_send_message(rcc);
}
-CursorChannel* cursor_channel_new(RedWorker *worker)
+CursorChannel* cursor_channel_new(RedsState *server, QXLInstance *qxl,
+ const SpiceCoreInterfaceInternal *core)
{
CursorChannel *cursor_channel;
CommonGraphicsChannel *channel = NULL;
@@ -318,9 +320,10 @@ CursorChannel* cursor_channel_new(RedWorker *worker)
};
spice_info("create cursor channel");
- channel = red_worker_new_channel(worker, sizeof(CursorChannel), "cursor_channel",
- SPICE_CHANNEL_CURSOR, 0,
- &cbs, red_channel_client_handle_message);
+ channel = common_graphics_channel_new(server, qxl, core,
+ sizeof(CursorChannel),
+ SPICE_CHANNEL_CURSOR, 0,
+ &cbs, red_channel_client_handle_message);
cursor_channel = (CursorChannel *)channel;
cursor_channel->priv->cursor_visible = TRUE;
diff --git a/server/cursor-channel.h b/server/cursor-channel.h
index 6149e2d..a3ddaa3 100644
--- a/server/cursor-channel.h
+++ b/server/cursor-channel.h
@@ -18,7 +18,7 @@
#ifndef CURSOR_CHANNEL_H_
# define CURSOR_CHANNEL_H_
-#include "red-worker.h"
+#include "common-graphics-channel.h"
/**
* This type it's a RedChannel class which implement cursor (mouse)
@@ -39,7 +39,8 @@ typedef struct CursorChannel CursorChannel;
* provided as helper functions and should only be called from the
* CursorChannel thread.
*/
-CursorChannel* cursor_channel_new (RedWorker *worker);
+CursorChannel* cursor_channel_new (RedsState *server, QXLInstance *qxl,
+ const SpiceCoreInterfaceInternal *core);
/**
* Cause the channel to disconnect all clients
diff --git a/server/display-channel.c b/server/display-channel.c
index b9366b5..93744a4 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -1903,7 +1903,9 @@ static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t su
return display->priv->surfaces[surface_id].context.canvas;
}
-DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
+DisplayChannel* display_channel_new(RedsState *reds,
+ QXLInstance *qxl,
+ const SpiceCoreInterfaceInternal *core,
int migrate, int stream_video,
GArray *video_codecs,
uint32_t n_surfaces)
@@ -1922,9 +1924,8 @@ DisplayChannel* display_channel_new(SpiceServer *reds, RedWorker *worker,
};
spice_info("create display channel");
- display = (DisplayChannel *)red_worker_new_channel(
- worker, sizeof(*display), "display_channel",
- SPICE_CHANNEL_DISPLAY,
+ display = (DisplayChannel *)common_graphics_channel_new(
+ reds, qxl, core, sizeof(*display), SPICE_CHANNEL_DISPLAY,
SPICE_MIGRATE_NEED_FLUSH | SPICE_MIGRATE_NEED_DATA_TRANSFER,
&cbs, dcc_handle_message);
spice_return_val_if_fail(display, NULL);
diff --git a/server/display-channel.h b/server/display-channel.h
index bbae6f1..936768e 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -43,6 +43,7 @@
#include "stream.h"
#include "dcc.h"
#include "image-encoders.h"
+#include "common-graphics-channel.h"
typedef struct DependItem {
Drawable *drawable;
@@ -230,8 +231,9 @@ typedef struct RedUpgradeItem {
} RedUpgradeItem;
-DisplayChannel* display_channel_new (SpiceServer *reds,
- RedWorker *worker,
+DisplayChannel* display_channel_new (RedsState *reds,
+ QXLInstance *qxl,
+ const SpiceCoreInterfaceInternal *core,
int migrate,
int stream_video,
GArray *video_codecs,
diff --git a/server/red-worker.c b/server/red-worker.c
index b3f6c12..085f4f3 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -91,39 +91,12 @@ struct RedWorker {
RedRecord *record;
};
-static RedsState* red_worker_get_server(RedWorker *worker);
-
static int display_is_connected(RedWorker *worker)
{
return (worker->display_channel && red_channel_is_connected(
&worker->display_channel->common.base));
}
-static uint8_t *common_alloc_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size)
-{
- RedChannel *channel = red_channel_client_get_channel(rcc);
- CommonGraphicsChannel *common = SPICE_CONTAINEROF(channel, CommonGraphicsChannel, base);
-
- /* SPICE_MSGC_MIGRATE_DATA is the only client message whose size is dynamic */
- if (type == SPICE_MSGC_MIGRATE_DATA) {
- return spice_malloc(size);
- }
-
- if (size > CHANNEL_RECEIVE_BUF_SIZE) {
- spice_critical("unexpected message size %u (max is %d)", size, CHANNEL_RECEIVE_BUF_SIZE);
- return NULL;
- }
- return common->recv_buf;
-}
-
-static void common_release_recv_buf(RedChannelClient *rcc, uint16_t type, uint32_t size,
- uint8_t* msg)
-{
- if (type == SPICE_MSGC_MIGRATE_DATA) {
- free(msg);
- }
-}
-
void red_drawable_unref(RedDrawable *red_drawable)
{
if (--red_drawable->refs) {
@@ -401,82 +374,6 @@ static void flush_all_qxl_commands(RedWorker *worker)
flush_cursor_commands(worker);
}
-int common_channel_config_socket(RedChannelClient *rcc)
-{
- RedClient *client = red_channel_client_get_client(rcc);
- MainChannelClient *mcc = red_client_get_main(client);
- RedsStream *stream = red_channel_client_get_stream(rcc);
- int flags;
- int delay_val;
- gboolean is_low_bandwidth;
-
- if ((flags = fcntl(stream->socket, F_GETFL)) == -1) {
- spice_warning("accept failed, %s", strerror(errno));
- return FALSE;
- }
-
- if (fcntl(stream->socket, F_SETFL, flags | O_NONBLOCK) == -1) {
- spice_warning("accept failed, %s", strerror(errno));
- return FALSE;
- }
-
- // TODO - this should be dynamic, not one time at channel creation
- is_low_bandwidth = main_channel_client_is_low_bandwidth(mcc);
- delay_val = is_low_bandwidth ? 0 : 1;
- /* FIXME: Using Nagle's Algorithm can lead to apparent delays, depending
- * on the delayed ack timeout on the other side.
- * Instead of using Nagle's, we need to implement message buffering on
- * the application level.
- * see: http://www.stuartcheshire.org/papers/NagleDelayedAck/
- */
- if (setsockopt(stream->socket, IPPROTO_TCP, TCP_NODELAY, &delay_val,
- sizeof(delay_val)) == -1) {
- if (errno != ENOTSUP) {
- spice_warning("setsockopt failed, %s", strerror(errno));
- }
- }
- // TODO: move wide/narrow ack setting to red_channel.
- red_channel_client_ack_set_client_window(rcc,
- is_low_bandwidth ?
- WIDE_CLIENT_ACK_WINDOW : NARROW_CLIENT_ACK_WINDOW);
- return TRUE;
-}
-
-CommonGraphicsChannel *red_worker_new_channel(RedWorker *worker, int size,
- const char *name,
- uint32_t channel_type, int migration_flags,
- ChannelCbs *channel_cbs,
- channel_handle_parsed_proc handle_parsed)
-{
- RedChannel *channel = NULL;
- CommonGraphicsChannel *common;
-
- spice_return_val_if_fail(worker, NULL);
- spice_return_val_if_fail(channel_cbs, NULL);
- spice_return_val_if_fail(!channel_cbs->alloc_recv_buf, NULL);
- spice_return_val_if_fail(!channel_cbs->release_recv_buf, NULL);
-
- if (!channel_cbs->config_socket)
- channel_cbs->config_socket = common_channel_config_socket;
- channel_cbs->alloc_recv_buf = common_alloc_recv_buf;
- channel_cbs->release_recv_buf = common_release_recv_buf;
-
- channel = red_channel_create_parser(size, red_worker_get_server(worker),
- &worker->core, channel_type,
- worker->qxl->id, TRUE /* handle_acks */,
- spice_get_client_channel_parser(channel_type, NULL),
- handle_parsed,
- channel_cbs,
- migration_flags);
- spice_return_val_if_fail(channel, NULL);
- red_channel_set_stat_node(channel, stat_add_node(red_worker_get_server(worker),
- worker->stat, name, TRUE));
-
- common = (CommonGraphicsChannel *)channel;
- common->qxl = worker->qxl;
- return common;
-}
-
static void guest_set_client_capabilities(RedWorker *worker)
{
int i;
@@ -1465,18 +1362,23 @@ RedWorker* red_worker_new(QXLInstance *qxl,
worker->event_timeout = INF_EVENT_WAIT;
- worker->cursor_channel = cursor_channel_new(worker);
+ worker->cursor_channel = cursor_channel_new(reds, qxl,
+ &worker->core);
channel = RED_CHANNEL(worker->cursor_channel);
+ red_channel_set_stat_node(channel, stat_add_node(reds, worker->stat,
+ "cursor_channel", TRUE));
red_channel_register_client_cbs(channel, client_cursor_cbs, dispatcher);
reds_register_channel(reds, channel);
// TODO: handle seemless migration. Temp, setting migrate to FALSE
- worker->display_channel = display_channel_new(reds, worker, FALSE,
+ worker->display_channel = display_channel_new(reds, qxl, &worker->core, FALSE,
reds_get_streaming_video(reds),
reds_get_video_codecs(reds),
init_info.n_surfaces);
channel = RED_CHANNEL(worker->display_channel);
+ red_channel_set_stat_node(channel, stat_add_node(reds, worker->stat,
+ "display_channel", TRUE));
red_channel_register_client_cbs(channel, client_display_cbs, dispatcher);
red_channel_set_cap(channel, SPICE_DISPLAY_CAP_MONITORS_CONFIG);
red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
@@ -1526,8 +1428,3 @@ bool red_worker_run(RedWorker *worker)
return r == 0;
}
-
-static RedsState* red_worker_get_server(RedWorker *worker)
-{
- return red_qxl_get_server(worker->qxl->st);
-}
diff --git a/server/red-worker.h b/server/red-worker.h
index 7d68678..370240f 100644
--- a/server/red-worker.h
+++ b/server/red-worker.h
@@ -25,74 +25,12 @@
typedef struct RedWorker RedWorker;
-int common_channel_config_socket(RedChannelClient *rcc);
-
-#define COMMON_CLIENT_TIMEOUT (NSEC_PER_SEC * 30)
-
-#define CHANNEL_RECEIVE_BUF_SIZE 1024
-typedef struct CommonGraphicsChannel {
- RedChannel base; // Must be the first thing
-
- QXLInstance *qxl;
- uint8_t recv_buf[CHANNEL_RECEIVE_BUF_SIZE];
- int during_target_migrate; /* TRUE when the client that is associated with the channel
- is during migration. Turned off when the vm is started.
- The flag is used to avoid sending messages that are artifacts
- of the transition from stopped vm to loaded vm (e.g., recreation
- of the primary surface) */
-} CommonGraphicsChannel;
-
-#define COMMON_GRAPHICS_CHANNEL(Channel) ((CommonGraphicsChannel*)(Channel))
-
-enum {
- RED_PIPE_ITEM_TYPE_VERB = RED_PIPE_ITEM_TYPE_CHANNEL_BASE,
- RED_PIPE_ITEM_TYPE_INVAL_ONE,
-
- RED_PIPE_ITEM_TYPE_COMMON_LAST
-};
-
-typedef struct RedVerbItem {
- RedPipeItem base;
- uint16_t verb;
-} RedVerbItem;
-
-static inline void red_marshall_verb(RedChannelClient *rcc, RedVerbItem *item)
-{
- red_channel_client_init_send_data(rcc, item->verb, NULL);
-}
-
-static inline void red_pipe_add_verb(RedChannelClient* rcc, uint16_t verb)
-{
- RedVerbItem *item = spice_new(RedVerbItem, 1);
-
- red_pipe_item_init(&item->base, RED_PIPE_ITEM_TYPE_VERB);
- item->verb = verb;
- red_channel_client_pipe_add(rcc, &item->base);
-}
-
-static inline void red_pipe_add_verb_proxy(RedChannelClient *rcc, gpointer data)
-{
- uint16_t verb = GPOINTER_TO_UINT(data);
- red_pipe_add_verb(rcc, verb);
-}
-
-
-static inline void red_pipes_add_verb(RedChannel *channel, uint16_t verb)
-{
- red_channel_apply_clients_data(channel, red_pipe_add_verb_proxy, GUINT_TO_POINTER(verb));
-}
-
RedWorker* red_worker_new(QXLInstance *qxl,
const ClientCbs *client_cursor_cbs,
const ClientCbs *client_display_cbs);
bool red_worker_run(RedWorker *worker);
+SpiceCoreInterfaceInternal* red_worker_get_core_interface(RedWorker *worker);
void red_drawable_unref(RedDrawable *red_drawable);
-CommonGraphicsChannel *red_worker_new_channel(RedWorker *worker, int size,
- const char *name,
- uint32_t channel_type, int migration_flags,
- ChannelCbs *channel_cbs,
- channel_handle_parsed_proc handle_parsed);
-
#endif
--
2.7.4
More information about the Spice-devel
mailing list