Re: [Spice-devel] [PATCH spice-server v2 12/12] display-channel: Inline red_migrate_display function

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> The only caller only called that function.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/display-channel.c | 10 +++---
>  1 file changed, 3 insertions(+), 7 deletions(-)
> 
> diff --git a/server/display-channel.c b/server/display-channel.c
> index 7b833e4c..9f3555e5 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -2633,8 +2633,10 @@ static void
> display_channel_disconnect(RedChannelClient *rcc)
>  red_channel_client_disconnect(rcc);
>  }
>  
> -static void red_migrate_display(DisplayChannel *display,
> RedChannelClient *rcc)
> +static void display_channel_migrate(RedChannelClient *rcc)
>  {
> +DisplayChannel *display =
> DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
> +
>  /* We need to stop the streams, and to send upgrade_items to the
> client.
>   * Otherwise, (1) the client might display lossy regions that we
> don't track
>   * (streams are not part of the migration data) (2)
> streams_timeout may occur
> @@ -2651,12 +2653,6 @@ static void red_migrate_display(DisplayChannel
> *display, RedChannelClient *rcc)
>  }
>  }
>  
> -static void display_channel_migrate(RedChannelClient *rcc)
> -{
> -DisplayChannel *display =
> DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
> -red_migrate_display(display, rcc);
> -}
> -
>  void display_channel_set_image_compression(DisplayChannel *display,
> SpiceImageCompression
> image_compression)
>  {

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2 11/12] Move image_compression field from RedWorker to DisplayChannel

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/display-channel-private.h |  1 +
>  server/display-channel.c | 10 --
>  server/display-channel.h |  2 ++
>  server/red-worker.c  |  7 +++
>  4 files changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/server/display-channel-private.h b/server/display-
> channel-private.h
> index 58179531..4cdae8dc 100644
> --- a/server/display-channel-private.h
> +++ b/server/display-channel-private.h
> @@ -87,6 +87,7 @@ struct DisplayChannelPrivate
>  MonitorsConfig *monitors_config;
>  
>  uint32_t renderer;
> +SpiceImageCompression image_compression;
>  int enable_jpeg;
>  int enable_zlib_glz_wrap;
>  
> diff --git a/server/display-channel.c b/server/display-channel.c
> index c2129c71..7b833e4c 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -2273,6 +2273,7 @@ display_channel_init(DisplayChannel *self)
>  /* must be manually allocated here since
> g_type_class_add_private() only
>   * supports structs smaller than 64k */
>  self->priv = g_new0(DisplayChannelPrivate, 1);
> +self->priv->image_compression =
> SPICE_IMAGE_COMPRESSION_AUTO_GLZ;
>  self->priv->pub = self;
>  
>  image_encoder_shared_init(>priv->encoder_shared_data);
> @@ -2611,10 +2612,9 @@ display_channel_connect(RedChannel *channel,
> RedClient *client,
>  
>  spice_debug("connect new client");
>  
> -// FIXME not sure how safe is reading directly from reds
>  SpiceServer *reds = red_channel_get_server(channel);
>  dcc = dcc_new(display, client, stream, migration, caps,
> -  spice_server_get_image_compression(reds),
> reds_get_jpeg_state(reds),
> +  display->priv->image_compression,
> reds_get_jpeg_state(reds),
>reds_get_zlib_glz_state(reds));
>  if (!dcc) {
>  return;
> @@ -2656,3 +2656,9 @@ static void
> display_channel_migrate(RedChannelClient *rcc)
>  DisplayChannel *display =
> DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
>  red_migrate_display(display, rcc);
>  }
> +
> +void display_channel_set_image_compression(DisplayChannel *display,
> +   SpiceImageCompression
> image_compression)
> +{
> +display->priv->image_compression = image_compression;
> +}
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 8dfdf523..6af9e129 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -159,6 +159,8 @@ void
> display_channel_reset_image_cache(DisplayChannel *self);
>  void display_channel_debug_oom(DisplayChannel *display, const char
> *msg);
>  
>  void display_channel_update_qxl_running(DisplayChannel *display,
> bool running);
> +void display_channel_set_image_compression(DisplayChannel *display,
> +   SpiceImageCompression
> image_compression);
>  
>  G_END_DECLS
>  
> diff --git a/server/red-worker.c b/server/red-worker.c
> index 7382e24d..bc63fc34 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -76,8 +76,6 @@ struct RedWorker {
>  
>  RedMemSlotInfo mem_slots;
>  
> -SpiceImageCompression image_compression;
> -
>  uint32_t process_display_generation;
>  RedStatNode stat;
>  RedStatCounter wakeup_counter;
> @@ -684,7 +682,7 @@ static void handle_dev_set_compression(void
> *opaque, void *payload)
>  RedWorker *worker = opaque;
>  SpiceImageCompression image_compression = msg-
> >image_compression;
>  
> -worker->image_compression = image_compression;
> +display_channel_set_image_compression(worker->display_channel,
> image_compression);
>  
>  display_channel_compress_stats_print(worker->display_channel);
>  display_channel_compress_stats_reset(worker->display_channel);
> @@ -1078,7 +1076,6 @@ RedWorker* red_worker_new(QXLInstance *qxl)
>  dispatcher_register_universal_handler(dispatcher,
> worker_dispatcher_record);
>  }
>  
> -worker->image_compression =
> spice_server_get_image_compression(reds);
>  worker->driver_cap_monitors_config = 0;
>  char worker_str[SPICE_STAT_NODE_NAME_MAX];
>  snprintf(worker_str, sizeof(worker_str), "display[%d]", worker-
> >qxl->id & 0xff);
> @@ -1120,6 +1117,8 @@ RedWorker* red_worker_new(QXLInstance *qxl)
>init_info.n_surfac
> es);
>  channel = RED_CHANNEL(worker

Re: [Spice-devel] [PATCH spice-server v2 10/12] Check image compression value earlier

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> Do not check it after assigning to reds->config->image_compression,
> check the value as soon as possible.
> This prevent potential invalid settings.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/red-worker.c | 28 
>  server/reds.c   | 34 +++---
>  2 files changed, 31 insertions(+), 31 deletions(-)
> 
> diff --git a/server/red-worker.c b/server/red-worker.c
> index d883f419..7382e24d 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -684,34 +684,6 @@ static void handle_dev_set_compression(void
> *opaque, void *payload)
>  RedWorker *worker = opaque;
>  SpiceImageCompression image_compression = msg-
> >image_compression;
>  
> -switch (image_compression) {
> -case SPICE_IMAGE_COMPRESSION_AUTO_LZ:
> -spice_debug("ic auto_lz");
> -break;
> -case SPICE_IMAGE_COMPRESSION_AUTO_GLZ:
> -spice_debug("ic auto_glz");
> -break;
> -case SPICE_IMAGE_COMPRESSION_QUIC:
> -spice_debug("ic quic");
> -break;
> -#ifdef USE_LZ4
> -case SPICE_IMAGE_COMPRESSION_LZ4:
> -spice_debug("ic lz4");
> -break;
> -#endif
> -case SPICE_IMAGE_COMPRESSION_LZ:
> -spice_debug("ic lz");
> -break;
> -case SPICE_IMAGE_COMPRESSION_GLZ:
> -spice_debug("ic glz");
> -break;
> -case SPICE_IMAGE_COMPRESSION_OFF:
> -spice_debug("ic off");
> -break;
> -default:
> -spice_warning("ic invalid");
> -image_compression = worker->image_compression;
> -}
>  worker->image_compression = image_compression;
>  
>  display_channel_compress_stats_print(worker->display_channel);
> diff --git a/server/reds.c b/server/reds.c
> index 14e5728b..28542bd0 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -3010,12 +3010,40 @@ static inline void
> on_activating_ticketing(RedsState *reds)
>  }
>  }
>  
> -static void reds_config_set_image_compression(RedsState *reds,
> SpiceImageCompression val)
> +static void reds_config_set_image_compression(RedsState *reds,
> SpiceImageCompression image_compression)
>  {
> -if (val == reds->config->image_compression) {
> +if (image_compression == reds->config->image_compression) {
>  return;
>  }
> -reds->config->image_compression = val;
> +switch (image_compression) {
> +case SPICE_IMAGE_COMPRESSION_AUTO_LZ:
> +spice_debug("ic auto_lz");
> +break;
> +case SPICE_IMAGE_COMPRESSION_AUTO_GLZ:
> +spice_debug("ic auto_glz");
> +break;
> +case SPICE_IMAGE_COMPRESSION_QUIC:
> +spice_debug("ic quic");
> +break;
> +#ifdef USE_LZ4
> +case SPICE_IMAGE_COMPRESSION_LZ4:
> +spice_debug("ic lz4");
> +break;
> +#endif
> +case SPICE_IMAGE_COMPRESSION_LZ:
> +spice_debug("ic lz");
> +break;
> +case SPICE_IMAGE_COMPRESSION_GLZ:
> +spice_debug("ic glz");
> +break;
> +case SPICE_IMAGE_COMPRESSION_OFF:
> +spice_debug("ic off");
> +break;
> +default:
> +spice_warning("ic invalid");
> +return;
> +}
> +reds->config->image_compression = image_compression;
>  reds_on_ic_change(reds);
>  }
>  

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2 09/12] red-worker: Remove only assigned fields

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 



On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> DisplayChannelClient get them directly from reds (they are changed
> only during initialisation so they can be read freely from any
> thread).
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/red-worker.c | 4 
>  1 file changed, 4 deletions(-)
> 
> diff --git a/server/red-worker.c b/server/red-worker.c
> index 129f9f93..d883f419 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -77,8 +77,6 @@ struct RedWorker {
>  RedMemSlotInfo mem_slots;
>  
>  SpiceImageCompression image_compression;
> -spice_wan_compression_t jpeg_state;
> -spice_wan_compression_t zlib_glz_state;
>  
>  uint32_t process_display_generation;
>  RedStatNode stat;
> @@ -1109,8 +1107,6 @@ RedWorker* red_worker_new(QXLInstance *qxl)
>  }
>  
>  worker->image_compression =
> spice_server_get_image_compression(reds);
> -worker->jpeg_state = reds_get_jpeg_state(reds);
> -worker->zlib_glz_state = reds_get_zlib_glz_state(reds);
>  worker->driver_cap_monitors_config = 0;
>  char worker_str[SPICE_STAT_NODE_NAME_MAX];
>  snprintf(worker_str, sizeof(worker_str), "display[%d]", worker-
> >qxl->id & 0xff);

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2 08/12] cursor-channel: Update some declarations and documentation

2019-03-28 Thread Jonathon Jongsma
This also looks like a patch that should get squashed (maybe parts
should be squashed into two different previous commits, see below), but
I agree with all of the changes.

Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/cursor-channel-client.h |  6 ++
>  server/cursor-channel.c|  2 --
>  server/cursor-channel.h| 17 ++---
>  3 files changed, 8 insertions(+), 17 deletions(-)
> 
> diff --git a/server/cursor-channel-client.h b/server/cursor-channel-
> client.h
> index 56b3b312..4deae535 100644
> --- a/server/cursor-channel-client.h
> +++ b/server/cursor-channel-client.h
> @@ -75,6 +75,12 @@ enum {
>  RED_PIPE_ITEM_TYPE_INVAL_CURSOR_CACHE,
>  };
>  
> +/**
> + * Migrate a client channel from a CursorChannel.
> + * This is the equivalent of RedChannel client migrate callback.
> + */
> +void cursor_channel_client_migrate(RedChannelClient
> *client);
> +
>  G_END_DECLS

It seems that this hunk and the last should get squashed with patch
06/12


>  
>  #endif /* CURSOR_CHANNEL_CLIENT_H_ */
> diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> index c88e5cd1..d936b791 100644
> --- a/server/cursor-channel.c
> +++ b/server/cursor-channel.c
> @@ -337,8 +337,6 @@ void cursor_channel_set_mouse_mode(CursorChannel
> *cursor, uint32_t mode)
>  
>  /**
>   * Connect a new client to CursorChannel.
> - * This is the equivalent of RedChannel client connect callback.
> - * See comment on cursor_channel_new.
>   */
>  static void
>  cursor_channel_connect(CursorChannel *cursor, RedClient *client,
> RedStream *stream,
> diff --git a/server/cursor-channel.h b/server/cursor-channel.h
> index ce1b92cc..dc48279a 100644
> --- a/server/cursor-channel.h
> +++ b/server/cursor-channel.h
> @@ -48,14 +48,8 @@ GType cursor_channel_get_type(void) G_GNUC_CONST;
>  /**
>   * Create CursorChannel.
>   * Since CursorChannel is intended to be run in a separate thread,
> - * it does not register its own client callbacks since they would
> - * be called from a different thread. Therefore users of this
> - * class are responsible for registering their own client callbacks
> - * for CursorChannel. These 'wrapper' client callbacks must forward
> - * execution on to the CursorChannel thread.
> - * cursor_channel_client_migrate() and cursor_channel_connect() are
> - * provided as helper functions and should only be called from the
> - * CursorChannel thread.
> + * the function accepts a dispatcher parameter to allows some
> + * operations to be executed in the channel thread.
>   */
>  CursorChannel* cursor_channel_new(RedsState *server, int id,
>const SpiceCoreInterfaceInternal
> *core,

I think these hunks should be squashed into patch 02/12


> @@ -66,13 +60,6 @@
> void cursor_channel_do_init (CursorChannel
> *cursor);
>  void cursor_channel_process_cmd (CursorChannel
> *cursor, RedCursorCmd *cursor_cmd);
>  void cursor_channel_set_mouse_mode(CursorChannel
> *cursor, uint32_t mode);
>  
> -/**
> - * Migrate a client channel from a CursorChannel.
> - * This is the equivalent of RedChannel client migrate callback.
> - * See comment on cursor_channel_new.
> - */
> -void cursor_channel_client_migrate(RedChannelClient
> *client);
> -
>  G_END_DECLS
>  
>  #endif /* CURSOR_CHANNEL_H_ */


Patch 06/12

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2 07/12] Make some function static

2019-03-28 Thread Jonathon Jongsma
Personally, I would squash this patch with the previous one

Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> Now that stuff are a bit more on their correct place some
> function can be static.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/cursor-channel.c  | 11 ---
>  server/cursor-channel.h  | 10 --
>  server/display-channel.c | 12 +---
>  server/display-channel.h |  5 -
>  4 files changed, 17 insertions(+), 21 deletions(-)
> 
> diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> index d1294322..c88e5cd1 100644
> --- a/server/cursor-channel.c
> +++ b/server/cursor-channel.c
> @@ -335,9 +335,14 @@ void cursor_channel_set_mouse_mode(CursorChannel
> *cursor, uint32_t mode)
>  cursor->mouse_mode = mode;
>  }
>  
> -void cursor_channel_connect(CursorChannel *cursor, RedClient
> *client, RedStream *stream,
> -int migrate,
> -RedChannelCapabilities *caps)
> +/**
> + * Connect a new client to CursorChannel.
> + * This is the equivalent of RedChannel client connect callback.
> + * See comment on cursor_channel_new.
> + */
> +static void
> +cursor_channel_connect(CursorChannel *cursor, RedClient *client,
> RedStream *stream,
> +   int migrate, RedChannelCapabilities *caps)
>  {
>  CursorChannelClient *ccc;
>  
> diff --git a/server/cursor-channel.h b/server/cursor-channel.h
> index 767325ea..ce1b92cc 100644
> --- a/server/cursor-channel.h
> +++ b/server/cursor-channel.h
> @@ -66,16 +66,6 @@
> void cursor_channel_do_init (CursorChannel
> *cursor);
>  void cursor_channel_process_cmd (CursorChannel
> *cursor, RedCursorCmd *cursor_cmd);
>  void cursor_channel_set_mouse_mode(CursorChannel
> *cursor, uint32_t mode);
>  
> -/**
> - * Connect a new client to CursorChannel.
> - * This is the equivalent of RedChannel client connect callback.
> - * See comment on cursor_channel_new.
> - */
> -void cursor_channel_connect (CursorChannel
> *cursor, RedClient *client,
> - RedStream *stream,
> - int migrate,
> - RedChannelCapabilit
> ies *caps);
> -
>  /**
>   * Migrate a client channel from a CursorChannel.
>   * This is the equivalent of RedChannel client migrate callback.
> diff --git a/server/display-channel.c b/server/display-channel.c
> index b8f85682..c2129c71 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -26,6 +26,12 @@
>  
>  G_DEFINE_TYPE(DisplayChannel, display_channel,
> TYPE_COMMON_GRAPHICS_CHANNEL)
>  
> +static void display_channel_connect(RedChannel *channel, RedClient
> *client,
> +RedStream *stream, int
> migration,
> +RedChannelCapabilities *caps);
> +static void display_channel_disconnect(RedChannelClient *rcc);
> +static void display_channel_migrate(RedChannelClient *rcc);
> +
>  enum {
>  PROP0,
>  PROP_N_SURFACES,
> @@ -2595,7 +2601,7 @@ void
> display_channel_update_qxl_running(DisplayChannel *display, bool
> running)
>  }
>  }
>  
> -void
> +static void
>  display_channel_connect(RedChannel *channel, RedClient *client,
>  RedStream *stream, int migration,
>  RedChannelCapabilities *caps)
> @@ -2618,7 +2624,7 @@ display_channel_connect(RedChannel *channel,
> RedClient *client,
>  dcc_start(dcc);
>  }
>  
> -void display_channel_disconnect(RedChannelClient *rcc)
> +static void display_channel_disconnect(RedChannelClient *rcc)
>  {
>  DisplayChannel *display =
> DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
>  
> @@ -2645,7 +2651,7 @@ static void red_migrate_display(DisplayChannel
> *display, RedChannelClient *rcc)
>  }
>  }
>  
> -void display_channel_migrate(RedChannelClient *rcc)
> +static void display_channel_migrate(RedChannelClient *rcc)
>  {
>  DisplayChannel *display =
> DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
>  red_migrate_display(display, rcc);
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 7dfedd75..8dfdf523 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -159,11 +159,6 @@ void
> display_channel_reset_image_cache(DisplayChannel *self);
>  void display_channel_debug_oom(DisplayChannel *display, const char
> *msg);
>  
>  void display_channel_update_qxl_run

Re: [Spice-devel] [PATCH spice-server v2 05/12] Check running state in red_qxl_set_client_capabilities

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> No reasons to expose red_qxl_is_running, this was used to not
> send capability is the state was not running.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/display-channel.c | 3 ---
>  server/red-qxl.c | 5 -
>  server/red-qxl.h | 3 ---
>  server/red-worker.h  | 1 +
>  4 files changed, 5 insertions(+), 7 deletions(-)
> 
> diff --git a/server/display-channel.c b/server/display-channel.c
> index 1af87ba4..e9368668 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -2566,9 +2566,6 @@ static void
> guest_set_client_capabilities(DisplayChannel *display)
>  #define
> CLEAR_CAP(a,c)  \
>  ((a)[(c) / 8] &= ~(1 << ((c) % 8)))
>  
> -if (!red_qxl_is_running(display->priv->qxl)) {
> -return;
> -}
>  if ((red_channel_get_n_clients(RED_CHANNEL(display)) == 0)) {
>  red_qxl_set_client_capabilities(display->priv->qxl, FALSE,
> caps);
>  } else {
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index e3fbf7b7..6dbd224c 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -68,6 +68,7 @@ struct QXLState {
>  
>  #define GL_DRAW_COOKIE_INVALID (~((uint64_t) 0))
>  
> +/* used by RedWorker */
>  bool red_qxl_is_running(QXLInstance *qxl)
>  {
>  return qxl->st->running;
> @@ -1048,7 +1049,9 @@ void
> red_qxl_set_client_capabilities(QXLInstance *qxl,
>  {
>  QXLInterface *interface = qxl_get_interface(qxl);
>  
> -interface->set_client_capabilities(qxl, client_present, caps);
> +if (qxl->st->running) {
> +interface->set_client_capabilities(qxl, client_present,
> caps);
> +}
>  }
>  
>  void red_qxl_async_complete(QXLInstance *qxl, uint64_t cookie)
> diff --git a/server/red-qxl.h b/server/red-qxl.h
> index 521f3659..94753948 100644
> --- a/server/red-qxl.h
> +++ b/server/red-qxl.h
> @@ -44,9 +44,6 @@ const char* red_qxl_get_device_address(const
> QXLInstance *qxl);
>  const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl);
>  size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
>  
> -/* check if QXL is running, should be used inside the worker thread
> */
> -bool red_qxl_is_running(QXLInstance *qxl);
> -
>  /* Wrappers around QXLInterface vfuncs */
>  void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
>  int red_qxl_get_command(QXLInstance *qxl, struct QXLCommandExt
> *cmd);
> diff --git a/server/red-worker.h b/server/red-worker.h
> index 54ab4da8..34c5b4af 100644
> --- a/server/red-worker.h
> +++ b/server/red-worker.h
> @@ -35,6 +35,7 @@ void red_worker_free(RedWorker *worker);
>  struct Dispatcher *red_qxl_get_dispatcher(QXLInstance *qxl);
>  void red_qxl_destroy_primary_surface_complete(QXLState *qxl_state);
>  void red_qxl_create_primary_surface_complete(QXLState *qxl_state,
> const QXLDevSurfaceCreate* surface);
> +bool red_qxl_is_running(QXLInstance *qxl);
>  void red_qxl_set_running(QXLInstance *qxl, bool running);
>  
>  typedef uint32_t RedWorkerMessage;

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2 04/12] Move DisplayChannel callbacks from RedWorker to DisplayChannel

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/display-channel.c | 108 +
>  server/display-channel.h |   7 +++
>  server/red-worker.c  | 114 ++---
> --
>  3 files changed, 120 insertions(+), 109 deletions(-)
> 
> diff --git a/server/display-channel.c b/server/display-channel.c
> index cb052bfc..1af87ba4 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -2540,3 +2540,111 @@ void display_channel_debug_oom(DisplayChannel
> *display, const char *msg)
>  ring_get_length(>priv->current_list),
>  red_channel_sum_pipes_size(channel));
>  }
> +
> +static void guest_set_client_capabilities(DisplayChannel *display)
> +{
> +int i;
> +RedChannelClient *rcc;
> +uint8_t caps[SPICE_CAPABILITIES_SIZE] = { 0 };
> +int caps_available[] = {
> +SPICE_DISPLAY_CAP_SIZED_STREAM,
> +SPICE_DISPLAY_CAP_MONITORS_CONFIG,
> +SPICE_DISPLAY_CAP_COMPOSITE,
> +SPICE_DISPLAY_CAP_A8_SURFACE,
> +};
> +QXLInterface *qif = qxl_get_interface(display->priv->qxl);
> +
> +if (!red_qxl_check_qxl_version(display->priv->qxl, 3, 2)) {
> +return;
> +}
> +if (!qif->set_client_capabilities) {
> +return;
> +}
> +#define
> SET_CAP(a,c)\
> +((a)[(c) / 8] |= (1 << ((c) % 8)))
> +
> +#define
> CLEAR_CAP(a,c)  \
> +((a)[(c) / 8] &= ~(1 << ((c) % 8)))
> +
> +if (!red_qxl_is_running(display->priv->qxl)) {
> +return;
> +}
> +if ((red_channel_get_n_clients(RED_CHANNEL(display)) == 0)) {
> +red_qxl_set_client_capabilities(display->priv->qxl, FALSE,
> caps);
> +} else {
> +// Take least common denominator
> +for (i = 0 ; i < SPICE_N_ELEMENTS(caps_available); ++i) {
> +SET_CAP(caps, caps_available[i]);
> +}
> +FOREACH_CLIENT(display, rcc) {
> +for (i = 0 ; i < SPICE_N_ELEMENTS(caps_available); ++i)
> {
> +if (!red_channel_client_test_remote_cap(rcc,
> caps_available[i]))
> +CLEAR_CAP(caps, caps_available[i]);
> +}
> +}
> +red_qxl_set_client_capabilities(display->priv->qxl, TRUE,
> caps);
> +}
> +}
> +
> +void display_channel_update_qxl_running(DisplayChannel *display,
> bool running)
> +{
> +if (running) {
> +guest_set_client_capabilities(display);
> +}
> +}
> +
> +void
> +display_channel_connect(RedChannel *channel, RedClient *client,
> +RedStream *stream, int migration,
> +RedChannelCapabilities *caps)
> +{
> +DisplayChannel *display = DISPLAY_CHANNEL(channel);
> +DisplayChannelClient *dcc;
> +
> +spice_debug("connect new client");
> +
> +// FIXME not sure how safe is reading directly from reds
> +SpiceServer *reds = red_channel_get_server(channel);
> +dcc = dcc_new(display, client, stream, migration, caps,
> +  spice_server_get_image_compression(reds),
> reds_get_jpeg_state(reds),
> +  reds_get_zlib_glz_state(reds));
> +if (!dcc) {
> +return;
> +}
> +display_channel_update_compression(display, dcc);
> +guest_set_client_capabilities(display);
> +dcc_start(dcc);
> +}
> +
> +void display_channel_disconnect(RedChannelClient *rcc)
> +{
> +DisplayChannel *display =
> DISPLAY_CHANNEL(red_channel_client_get_channel(rcc));
> +
> +guest_set_client_capabilities(display);
> +
> +red_channel_client_disconnect(rcc);
> +}
> +
> +static void red_migrate_display(DisplayChannel *display,
> RedChannelClient *rcc)
> +{
> +/* We need to stop the streams, and to send upgrade_items to the
> client.
> + * Otherwise, (1) the client might display lossy regions that we
> don't track
> + * (streams are not part of the migration data) (2)
> streams_timeout may occur
> + * after the MIGRATE message has been sent. This can result in
> messages
> + * being sent to the client after MSG_MIGRATE and before
> MSG_MIGRATE_DATA (e.g.,
> + * STREAM_CLIP, STREAM_DESTROY, DRAW_COPY)
> + * No message besides MSG_MIGRATE_DATA should be sent after
> MSG_MIGRATE.
> + * Notice that detach_and_stop_streams won't lead to any dev ram
> changes, since
> + * handle_dev_stop already took care of 

Re: [Spice-devel] [PATCH spice-server v2 02/12] Move thread/dispatching handling to RedChannel

2019-03-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-03-26 at 19:10 +, Frediano Ziglio wrote:
> Currently channel threading/handling is spread between RedQxl,
> RedWorker and RedChannel.
> Move more to RedChannel simplify RedQxl and RedWorker.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/cursor-channel.c|   4 +-
>  server/cursor-channel.h|   4 +-
>  server/display-channel.c   |   2 +
>  server/display-channel.h   |   1 +
>  server/red-channel.c   | 112 +++--
>  server/red-qxl.c   | 110 +---
>  server/red-replay-qxl.c|   3 -
>  server/red-stream-device.c |   2 +-
>  server/red-worker.c| 126 +
> 
>  server/red-worker.h|  46 +++---
>  10 files changed, 157 insertions(+), 253 deletions(-)
> 
> diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> index 4220084f..e8af01b0 100644
> --- a/server/cursor-channel.c
> +++ b/server/cursor-channel.c
> @@ -228,7 +228,8 @@ static void
> cursor_channel_send_item(RedChannelClient *rcc, RedPipeItem *pipe_it
>  }
>  
>  CursorChannel* cursor_channel_new(RedsState *server, int id,
> -  const SpiceCoreInterfaceInternal
> *core)
> +  const SpiceCoreInterfaceInternal
> *core,
> +  Dispatcher *dispatcher)
>  {
>  spice_debug("create cursor channel");
>  return g_object_new(TYPE_CURSOR_CHANNEL,
> @@ -238,6 +239,7 @@ CursorChannel* cursor_channel_new(RedsState
> *server, int id,
>  "id", id,
>  "migration-flags", 0,
>  "handle-acks", TRUE,
> +"dispatcher", dispatcher,
>  NULL);
>  }
>  
> diff --git a/server/cursor-channel.h b/server/cursor-channel.h
> index 603c2c0a..767325ea 100644
> --- a/server/cursor-channel.h
> +++ b/server/cursor-channel.h
> @@ -21,6 +21,7 @@
>  
>  #include "common-graphics-channel.h"
>  #include "red-parse-qxl.h"
> +#include "dispatcher.h"
>  
>  G_BEGIN_DECLS
>  
> @@ -57,7 +58,8 @@ GType cursor_channel_get_type(void) G_GNUC_CONST;
>   * CursorChannel thread.
>   */
>  CursorChannel* cursor_channel_new(RedsState *server, int id,
> -  const SpiceCoreInterfaceInternal
> *core);
> +  const SpiceCoreInterfaceInternal
> *core,
> +  Dispatcher *dispatcher);
>  
>  void cursor_channel_reset   (CursorChannel
> *cursor);
>  void cursor_channel_do_init (CursorChannel
> *cursor);
> diff --git a/server/display-channel.c b/server/display-channel.c
> index e179abfd..cb052bfc 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -2227,6 +2227,7 @@ static SpiceCanvas
> *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t su
>  DisplayChannel* display_channel_new(RedsState *reds,
>  QXLInstance *qxl,
>  const SpiceCoreInterfaceInternal
> *core,
> +Dispatcher *dispatcher,
>  int migrate, int stream_video,
>  GArray *video_codecs,
>  uint32_t n_surfaces)
> @@ -2246,6 +2247,7 @@ DisplayChannel* display_channel_new(RedsState
> *reds,
> "n-surfaces", n_surfaces,
> "video-codecs", video_codecs,
> "handle-acks", TRUE,
> +   "dispatcher", dispatcher,
> NULL);
>  if (display) {
>  display_channel_set_stream_video(display, stream_video);
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 948018cf..f64da0bd 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -99,6 +99,7 @@ struct Drawable {
>  DisplayChannel*display_channel_new  
>  (RedsState *reds,
>  
>   QXLInstance *qxl,
>  
>   const SpiceCoreInterfaceInternal *core,
> +
>   Dispatcher *dispatcher,
>  
>   int migrate,
>

Re: [Spice-devel] [PATCH spice-server v2 01/12] dispatcher: Allows to manage messages without registering them

2019-03-28 Thread Jonathon Jongsma
nt32_t
> message_type,
> - void *payload)
> +static void
> +dispatcher_send_message_internal(Dispatcher *dispatcher, const
> DispatcherMessage*msg,
> + void *payload)
>  {
> -DispatcherMessage *msg;
>  uint32_t ack;
>  int send_fd = dispatcher->priv->send_fd;
>  
> -assert(dispatcher->priv->max_message_type > message_type);
> -assert(dispatcher->priv->messages[message_type].handler);

You've removed a bunch of asserts here, but do we want to assert (or at
least g_return_if_fail) if msg is NULL?

> -msg = >priv->messages[message_type];
>  pthread_mutex_lock(>priv->lock);
> -if (write_safe(send_fd, (uint8_t*)_type,
> sizeof(message_type)) == -1) {
> +if (write_safe(send_fd, (uint8_t*)msg, sizeof(*msg)) == -1) {
>  g_warning("error: failed to send message type for message
> %d",

Perhaps this warning message should be changed from "failed to send
message type" to "failed to send message header"?

> -  message_type);
> +  msg->type);
>  goto unlock;
>  }
>  if (write_safe(send_fd, payload, msg->size) == -1) {
>  g_warning("error: failed to send message body for message
> %d",
> -  message_type);
> +  msg->type);
>  goto unlock;
>  }
>  if (msg->ack) {
> @@ -326,7 +331,7 @@ void dispatcher_send_message(Dispatcher
> *dispatcher, uint32_t message_type,
>  g_warning("error: failed to read ack");
>  } else if (ack != ACK) {
>  g_warning("error: got wrong ack value in dispatcher "
> -  "for message %d\n", message_type);
> +  "for message %d\n", msg->type);
>  /* TODO handling error? */
>  }
>  }
> @@ -334,6 +339,29 @@ unlock:
>  pthread_mutex_unlock(>priv->lock);
>  }
>  
> +void dispatcher_send_message(Dispatcher *dispatcher, uint32_t
> message_type,
> + void *payload)
> +{
> +DispatcherMessage *msg;
> +
> +assert(dispatcher->priv->max_message_type > message_type);
> +assert(dispatcher->priv->messages[message_type].handler);
> +msg = >priv->messages[message_type];
> +dispatcher_send_message_internal(dispatcher, msg, payload);
> +}
> +
> +void dispatcher_send_message_custom(Dispatcher *dispatcher,
> dispatcher_handle_message handler,
> +void *payload, uint32_t
> payload_size, bool ack)
> +{
> +DispatcherMessage msg = {
> +.handler = handler,
> +.size = payload_size,
> +.type = DISPATCHER_CUSTOM_TYPE,
> +.ack = ack,
> +};
> +dispatcher_send_message_internal(dispatcher, , payload);
> +}
> +
>  void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t
> message_type,
>   dispatcher_handle_message handler,
>   size_t size, bool ack)
> @@ -345,6 +373,7 @@ void dispatcher_register_handler(Dispatcher
> *dispatcher, uint32_t message_type,
>  msg = >priv->messages[message_type];
>  msg->handler = handler;
>  msg->size = size;
> +msg->type = message_type;
>  msg->ack = ack;
>  if (msg->size > dispatcher->priv->payload_size) {
>  dispatcher->priv->payload = g_realloc(dispatcher->priv-
> >payload, msg->size);
> diff --git a/server/dispatcher.h b/server/dispatcher.h
> index bb968e56..a7aaebed 100644
> --- a/server/dispatcher.h
> +++ b/server/dispatcher.h
> @@ -99,6 +99,21 @@ typedef void (*dispatcher_handle_any_message)(void
> *opaque,
>  void dispatcher_send_message(Dispatcher *dispatcher, uint32_t
> message_type,
>   void *payload);
>  
> +/* dispatcher_send_message_custom
> + *
> + * Sends a message to the receiving thread.
> + *
> + * If the sent message is a message type requires an ACK, this 
> function will
> + * block until it receives an ACK from the receiving thread.

The comment above is a little bit confusing because in this case the
message type doesn't determine whether an ACK is required. The @ack
argument determines whether an ACK is required. Maybe remove the phrase
"is a message type ". So it becomes:

"If the sent message requires an ACK, this function..."

> + *
> + * @handler:  callback to handle message
> + * @payload:  payload
> + * @payload_size: size of payload
> + * @ack:  acknowledge required. Make message synchronous
> + */
> +void dispatcher_send_message_custom(Dispatcher *dispatcher,
> dispatcher_handle_message handler,
> +void *payload, uint32_t
> payload_size, bool ack);
> +
>  /* dispatcher_register_handler
>   *
>   * This function registers a message type with the dispatcher, and
> registers


with minor comments above:

Acked-by: Jonathon Jongsma 

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server] Save running property in QXLState

2019-03-21 Thread Jonathon Jongsma
From: Frediano Ziglio 

This is a preparatory patch that states the running property in QXLState
and provides accessor functions that allows us to check whether the QXL
device is running from different threads.

Signed-off-by: Jonathon Jongsma 
---
Alternate proposal for patch 7/10. I also rebased the rest of Frediano's branch 
that follows this
commit, which can be found in the dispatcher_red_channel branch at
https://gitlab.freedesktop.org/jjongsma/spice.git

 server/display-channel-private.h |  1 +
 server/red-qxl.c | 19 +++
 server/red-qxl.h |  2 ++
 server/red-worker.c  | 23 +++
 4 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/server/display-channel-private.h b/server/display-channel-private.h
index 58179531d..067c64188 100644
--- a/server/display-channel-private.h
+++ b/server/display-channel-private.h
@@ -89,6 +89,7 @@ struct DisplayChannelPrivate
 uint32_t renderer;
 int enable_jpeg;
 int enable_zlib_glz_wrap;
+bool running;
 
 /* A ring of pending drawables for this DisplayChannel, regardless of which
  * surface they're associated with. This list is mainly used to flush older
diff --git a/server/red-qxl.c b/server/red-qxl.c
index 8274be567..152e9f068 100644
--- a/server/red-qxl.c
+++ b/server/red-qxl.c
@@ -59,6 +59,9 @@ struct QXLState {
 uint32_t device_display_ids[MAX_MONITORS_COUNT];
 size_t monitors_count;  // length of ^^^
 
+bool running;
+pthread_mutex_t running_mutex;
+
 pthread_mutex_t scanout_mutex;
 SpiceMsgDisplayGlScanoutUnix scanout;
 uint64_t gl_draw_cookie;
@@ -66,6 +69,21 @@ struct QXLState {
 
 #define GL_DRAW_COOKIE_INVALID (~((uint64_t) 0))
 
+bool red_qxl_is_running(QXLInstance *qxl) {
+bool running;
+pthread_mutex_lock(>st->running_mutex);
+running = qxl->st->running;
+pthread_mutex_unlock(>st->running_mutex);
+return running;
+}
+
+void red_qxl_set_running(QXLInstance *qxl, bool running) {
+pthread_mutex_lock(>st->running_mutex);
+qxl->st->running = running;
+pthread_mutex_unlock(>st->running_mutex);
+}
+
+
 int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int minor)
 {
 int qxl_major = qxl_get_interface(qxl)->base.major_version;
@@ -825,6 +843,7 @@ void red_qxl_init(RedsState *reds, QXLInstance *qxl)
 qxl_state->reds = reds;
 qxl_state->qxl = qxl;
 pthread_mutex_init(_state->scanout_mutex, NULL);
+pthread_mutex_init(_state->running_mutex, NULL);
 qxl_state->scanout.drm_dma_buf_fd = -1;
 qxl_state->gl_draw_cookie = GL_DRAW_COOKIE_INVALID;
 qxl_state->dispatcher = dispatcher_new(RED_WORKER_MESSAGE_COUNT);
diff --git a/server/red-qxl.h b/server/red-qxl.h
index 947539482..97d28d67c 100644
--- a/server/red-qxl.h
+++ b/server/red-qxl.h
@@ -60,5 +60,7 @@ void red_qxl_update_area_complete(QXLInstance *qxl, uint32_t 
surface_id,
 void red_qxl_set_client_capabilities(QXLInstance *qxl,
  uint8_t client_present,
  uint8_t caps[SPICE_CAPABILITIES_SIZE]);
+void red_qxl_set_running(QXLInstance *qxl, bool running);
+bool red_qxl_is_running(QXLInstance *qxl);
 
 #endif /* RED_QXL_H_ */
diff --git a/server/red-worker.c b/server/red-worker.c
index 27fe04ccb..b80fefabe 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -63,7 +63,6 @@ struct RedWorker {
 pthread_t thread;
 QXLInstance *qxl;
 SpiceWatch *dispatch_watch;
-int running;
 SpiceCoreInterfaceInternal core;
 
 unsigned int event_timeout;
@@ -115,7 +114,7 @@ static int red_process_cursor(RedWorker *worker, int 
*ring_is_empty)
 QXLCommandExt ext_cmd;
 int n = 0;
 
-if (!worker->running) {
+if (!red_qxl_is_running(worker->qxl)) {
 *ring_is_empty = TRUE;
 return n;
 }
@@ -173,7 +172,7 @@ static int red_process_display(RedWorker *worker, int 
*ring_is_empty)
 int n = 0;
 uint64_t start = spice_get_monotonic_time_ns();
 
-if (!worker->running) {
+if (!red_qxl_is_running(worker->qxl)) {
 *ring_is_empty = TRUE;
 return n;
 }
@@ -378,7 +377,7 @@ static void guest_set_client_capabilities(RedWorker *worker)
 #define CLEAR_CAP(a,c)  \
 ((a)[(c) / 8] &= ~(1 << ((c) % 8)))
 
-if (!worker->running) {
+if (!red_qxl_is_running(worker->qxl)) {
 return;
 }
 if ((worker->display_channel == NULL) ||
@@ -406,7 +405,7 @@ static void handle_dev_update_async(void *opaque, void 
*payload)
 QXLRect *qxl_dirty_rects = NULL;
 uint32_t num_dirty_rects = 0;
 
-spice_return_if_fail(worker->running);
+spice_return_if_fail(red_qxl_is_running(worker->qxl));
 spice_return_if_fail(qxl_get_interface(worker->qxl)->update_area_complete);
 
 flush_

Re: [Spice-devel] [PATCH spice-server 07/10] Propagate running property from RedWorker to DisplayChannel

2019-03-20 Thread Jonathon Jongsma
Somehow this information doesn't really seem to belong to
DisplayChannel, but I can't put my finger on exactly why it feels out
of place...



On Wed, 2019-03-20 at 09:59 +, Frediano Ziglio wrote:
> This is a preparatory patch to allows DisplayChannel to check
> if device is running.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/display-channel-private.h | 1 +
>  server/display-channel.c | 8 
>  server/display-channel.h | 2 ++
>  server/red-worker.c  | 2 ++
>  4 files changed, 13 insertions(+)
> 
> diff --git a/server/display-channel-private.h b/server/display-
> channel-private.h
> index 58179531..067c6418 100644
> --- a/server/display-channel-private.h
> +++ b/server/display-channel-private.h
> @@ -89,6 +89,7 @@ struct DisplayChannelPrivate
>  uint32_t renderer;
>  int enable_jpeg;
>  int enable_zlib_glz_wrap;
> +bool running;

At minimum, this seems like way too generic of a name. I will probably
look at this later and wonder what it means for a DisplayChannel to be
'running'. But in reality this variable indicates that the QXL device
is started? Actually, after looking briefly at this handle_dev_start()
function, I can't even figure out what causes this function to be
called...

>  
>  /* A ring of pending drawables for this DisplayChannel,
> regardless of which
>   * surface they're associated with. This list is mainly used to
> flush older
> diff --git a/server/display-channel.c b/server/display-channel.c
> index cb052bfc..49a2bd48 100644
> --- a/server/display-channel.c
> +++ b/server/display-channel.c
> @@ -2540,3 +2540,11 @@ void display_channel_debug_oom(DisplayChannel
> *display, const char *msg)
>  ring_get_length(>priv->current_list),
>  red_channel_sum_pipes_size(channel));
>  }
> +
> +void display_channel_set_running(DisplayChannel *display, bool
> running)
> +{
> +if (running == display->priv->running) {
> +return;
> +}
> +display->priv->running = running;
> +}
> diff --git a/server/display-channel.h b/server/display-channel.h
> index f64da0bd..bdf2f059 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -158,6 +158,8 @@ void
> display_channel_reset_image_cache(DisplayChannel *self);
>  
>  void display_channel_debug_oom(DisplayChannel *display, const char
> *msg);
>  
> +void display_channel_set_running(DisplayChannel *display, bool
> running);
> +
>  G_END_DECLS
>  
>  #endif /* DISPLAY_CHANNEL_H_ */
> diff --git a/server/red-worker.c b/server/red-worker.c
> index 07329b17..c9c47133 100644
> --- a/server/red-worker.c
> +++ b/server/red-worker.c
> @@ -588,6 +588,7 @@ static void handle_dev_stop(void *opaque, void
> *payload)
>  spice_assert(worker->running);
>  
>  worker->running = FALSE;
> +display_channel_set_running(worker->display_channel, false);
>  
>  display_channel_free_glz_drawables(worker->display_channel);
>  display_channel_flush_all_surfaces(worker->display_channel);
> @@ -616,6 +617,7 @@ static void handle_dev_start(void *opaque, void
> *payload)
>  display_channel_wait_for_migrate_data(worker-
> >display_channel);
>  }
>  worker->running = TRUE;
> +display_channel_set_running(worker->display_channel, true);
>  worker->event_timeout = 0;
>  guest_set_client_capabilities(worker);
>  }

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 06/10] Move thread/dispatching handling to RedChannel

2019-03-20 Thread Jonathon Jongsma
ot;);
> -red_channel_register_client_cbs(channel, client_cursor_cbs);
> -g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher);
> +
> +ClientCbs client_cursor_cbs = { NULL, };
> +client_cursor_cbs.connect = (channel_client_connect_proc)
> cursor_channel_connect;
> +client_cursor_cbs.disconnect = NULL;
> +client_cursor_cbs.migrate = cursor_channel_client_migrate;
> +red_channel_register_client_cbs(channel, _cursor_cbs);
>  
>  // TODO: handle seamless migration. Temp, setting migrate to
> FALSE
> -worker->display_channel = display_channel_new(reds, qxl,
> >core, FALSE,
> +worker->display_channel = display_channel_new(reds, qxl,
> >core, dispatcher,
> +  FALSE,
>reds_get_streaming
> _video(reds),
>reds_get_video_cod
> ecs(reds),
>init_info.n_surfac
> es);
>  channel = RED_CHANNEL(worker->display_channel);
>  red_channel_init_stat_node(channel, >stat,
> "display_channel");
> -red_channel_register_client_cbs(channel, client_display_cbs);
> -g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher);
> +g_object_set_data(G_OBJECT(channel), "worker", worker);
> +
> +ClientCbs client_display_cbs = { NULL, };
> +client_display_cbs.connect = handle_dev_display_connect;
> +client_display_cbs.disconnect = handle_dev_display_disconnect;
> +client_display_cbs.migrate = handle_dev_display_migrate;
> +red_channel_register_client_cbs(channel, _display_cbs);
>  
>  return worker;
>  }
> diff --git a/server/red-worker.h b/server/red-worker.h
> index 767329da..3d2841ba 100644
> --- a/server/red-worker.h
> +++ b/server/red-worker.h
> @@ -28,9 +28,7 @@
>  
>  typedef struct RedWorker RedWorker;
>  
> -RedWorker* red_worker_new(QXLInstance *qxl,
> -  const ClientCbs *client_cursor_cbs,
> -  const ClientCbs *client_display_cbs);
> +RedWorker* red_worker_new(QXLInstance *qxl);
>  bool   red_worker_run(RedWorker *worker);
>  void red_worker_free(RedWorker *worker);
>  
> @@ -51,14 +49,14 @@ enum {
>  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_DISPLAY_CONNECT_DEPRECATED,
> +RED_WORKER_MESSAGE_DISPLAY_DISCONNECT_DEPRECATED,
> +RED_WORKER_MESSAGE_DISPLAY_MIGRATE_DEPRECATED,
>  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_CURSOR_CONNECT_DEPRECATED,
> +RED_WORKER_MESSAGE_CURSOR_DISCONNECT_DEPRECATED,
> +RED_WORKER_MESSAGE_CURSOR_MIGRATE_DEPRECATED,
>  RED_WORKER_MESSAGE_SET_COMPRESSION,
>  RED_WORKER_MESSAGE_SET_STREAMING_VIDEO,
>  RED_WORKER_MESSAGE_SET_MOUSE_MODE,
> @@ -97,36 +95,6 @@ enum {
>  RED_WORKER_MESSAGE_COUNT // LAST
>  };
>  
> -typedef struct RedWorkerMessageDisplayConnect {
> -RedClient * client;
> -RedStream * stream;
> -RedChannelCapabilities caps;   // red_worker should reset
> -int migration;
> -} RedWorkerMessageDisplayConnect;
> -
> -typedef struct RedWorkerMessageDisplayDisconnect {
> -RedChannelClient *rcc;
> -} RedWorkerMessageDisplayDisconnect;
> -
> -typedef struct RedWorkerMessageDisplayMigrate {
> -RedChannelClient *rcc;
> -} RedWorkerMessageDisplayMigrate;
> -
> -typedef struct RedWorkerMessageCursorConnect {
> -RedClient *client;
> -RedStream *stream;
> -int migration;
> -RedChannelCapabilities caps;   // red_worker should reset
> -} RedWorkerMessageCursorConnect;
> -
> -typedef struct RedWorkerMessageCursorDisconnect {
> -RedChannelClient *rcc;
> -} RedWorkerMessageCursorDisconnect;
> -
> -typedef struct RedWorkerMessageCursorMigrate {
> -RedChannelClient *rcc;
> -} RedWorkerMessageCursorMigrate;
> -
>  typedef struct RedWorkerMessageUpdate {
>  uint32_t surface_id;
>  QXLRect * qxl_area;


Reviewed-by: Jonathon Jongsma 


___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 05/10] main-dispatcher: Use dispatcher_send_message_generic

2019-03-20 Thread Jonathon Jongsma
There should be some justification in the commit log about why this is
an improvement. 

Jonathon

On Wed, 2019-03-20 at 09:59 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/main-dispatcher.c | 38 --
>  1 file changed, 8 insertions(+), 30 deletions(-)
> 
> diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> index 839e7242..904579a8 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -121,15 +121,6 @@ main_dispatcher_init(MainDispatcher *self)
>  self->priv = main_dispatcher_get_instance_private(self);
>  }
>  
> -enum {
> -MAIN_DISPATCHER_CHANNEL_EVENT = 0,
> -MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
> -MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
> -MAIN_DISPATCHER_CLIENT_DISCONNECT,
> -
> -MAIN_DISPATCHER_NUM_MESSAGES
> -};
> -
>  typedef struct MainDispatcherChannelEventMessage {
>  int event;
>  SpiceChannelEventInfo *info;
> @@ -168,8 +159,8 @@ void main_dispatcher_channel_event(MainDispatcher
> *self, int event, SpiceChannel
>  }
>  msg.event = event;
>  msg.info = info;
> -dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_CHANNEL_EVENT,
> -);
> +dispatcher_send_message_generic(DISPATCHER(self),
> main_dispatcher_handle_channel_event,
> +, sizeof(msg), false);
>  }
>  
>  
> @@ -214,8 +205,8 @@ void
> main_dispatcher_seamless_migrate_dst_complete(MainDispatcher *self,
>  }
>  
>  msg.client = g_object_ref(client);
> -dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
> -);
> +dispatcher_send_message_generic(DISPATCHER(self),
> main_dispatcher_handle_migrate_complete,
> +, sizeof(msg), false);
>  }
>  
>  void main_dispatcher_set_mm_time_latency(MainDispatcher *self,
> RedClient *client, uint32_t latency)
> @@ -229,8 +220,8 @@ void
> main_dispatcher_set_mm_time_latency(MainDispatcher *self, RedClient
> *client
>  
>  msg.client = g_object_ref(client);
>  msg.latency = latency;
> -dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
> -);
> +dispatcher_send_message_generic(DISPATCHER(self),
> main_dispatcher_handle_mm_time_latency,
> +, sizeof(msg), false);
>  }
>  
>  void main_dispatcher_client_disconnect(MainDispatcher *self,
> RedClient *client)
> @@ -240,8 +231,8 @@ void
> main_dispatcher_client_disconnect(MainDispatcher *self, RedClient
> *client)
>  if (!red_client_is_disconnecting(client)) {
>  spice_debug("client %p", client);
>  msg.client = g_object_ref(client);
> -dispatcher_send_message(DISPATCHER(self),
> MAIN_DISPATCHER_CLIENT_DISCONNECT,
> -);
> +dispatcher_send_message_generic(DISPATCHER(self),
> main_dispatcher_handle_client_disconnect,
> +, sizeof(msg), false);
>  } else {
>  spice_debug("client %p already during disconnection",
> client);
>  }
> @@ -263,7 +254,6 @@ MainDispatcher* main_dispatcher_new(RedsState
> *reds)
>  {
>  MainDispatcher *self = g_object_new(TYPE_MAIN_DISPATCHER,
>  "spice-server", reds,
> -"max-message-type",
> MAIN_DISPATCHER_NUM_MESSAGES,
>  NULL);
>  return self;
>  }
> @@ -280,18 +270,6 @@ void main_dispatcher_constructed(GObject
> *object)
>  dispatcher_get_recv_fd(DISPATCHER(self))
> ,
>  SPICE_WATCH_EVENT_READ,
> dispatcher_handle_read,
>  DISPATCHER(self));
> -dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_CHANNEL_EVENT,
> -main_dispatcher_handle_channel_event
> ,
> -sizeof(MainDispatcherChannelEventMes
> sage), false);
> -dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_MIGRATE_SEAMLESS_DST_COMPLETE,
> -main_dispatcher_handle_migrate_compl
> ete,
> -sizeof(MainDispatcherMigrateSeamless
> DstCompleteMessage), false);
> -dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_SET_MM_TIME_LATENCY,
> -main_dispatcher_handle_mm_time_laten
> cy,
> -sizeof(MainDispatcherMmTimeLatencyMe
> ssage), false);
> -dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_CLIENT_DISCONNECT,
> -main_dispatcher_handle_client_discon
> nect,
> -sizeof(MainDispatcherClientDisconnec
> tMessage), false);
>  }
>  
>  static void main_dispatcher_finalize(GObject *object)


Re: [Spice-devel] [PATCH spice-server 04/10] main-dispatcher: Use reds as opaque for dispatcher

2019-03-20 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Wed, 2019-03-20 at 09:59 +, Frediano Ziglio wrote:
> No reason to pass through MainDispatcher, the purpose of
> MainDispatcher is to call reds functions from the right thread.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/main-dispatcher.c | 18 +-
>  1 file changed, 9 insertions(+), 9 deletions(-)
> 
> diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> index 0dcfb2d4..839e7242 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -152,10 +152,10 @@ typedef struct
> MainDispatcherClientDisconnectMessage {
>  static void main_dispatcher_handle_channel_event(void *opaque,
>   void *payload)
>  {
> -MainDispatcher *self = opaque;
> +RedsState *reds = opaque;
>  MainDispatcherChannelEventMessage *channel_event = payload;
>  
> -reds_handle_channel_event(self->priv->reds, channel_event-
> >event, channel_event->info);
> +reds_handle_channel_event(reds, channel_event->event,
> channel_event->info);
>  }
>  
>  void main_dispatcher_channel_event(MainDispatcher *self, int event,
> SpiceChannelEventInfo *info)
> @@ -176,30 +176,30 @@ void
> main_dispatcher_channel_event(MainDispatcher *self, int event,
> SpiceChannel
>  static void main_dispatcher_handle_migrate_complete(void *opaque,
>  void *payload)
>  {
> -MainDispatcher *self = opaque;
> +RedsState *reds = opaque;
>  MainDispatcherMigrateSeamlessDstCompleteMessage *mig_complete =
> payload;
>  
> -reds_on_client_seamless_migrate_complete(self->priv->reds,
> mig_complete->client);
> +reds_on_client_seamless_migrate_complete(reds, mig_complete-
> >client);
>  g_object_unref(mig_complete->client);
>  }
>  
>  static void main_dispatcher_handle_mm_time_latency(void *opaque,
> void *payload)
>  {
> -MainDispatcher *self = opaque;
> +RedsState *reds = opaque;
>  MainDispatcherMmTimeLatencyMessage *msg = payload;
> -reds_set_client_mm_time_latency(self->priv->reds, msg->client,
> msg->latency);
> +reds_set_client_mm_time_latency(reds, msg->client, msg-
> >latency);
>  g_object_unref(msg->client);
>  }
>  
>  static void main_dispatcher_handle_client_disconnect(void *opaque,
>   void *payload)
>  {
> -MainDispatcher *self = opaque;
> +RedsState *reds = opaque;
>  MainDispatcherClientDisconnectMessage *msg = payload;
>  
>  spice_debug("client=%p", msg->client);
> -reds_client_disconnect(self->priv->reds, msg->client);
> +reds_client_disconnect(reds, msg->client);
>  g_object_unref(msg->client);
>  }
>  
> @@ -273,7 +273,7 @@ void main_dispatcher_constructed(GObject *object)
>  MainDispatcher *self = MAIN_DISPATCHER(object);
>  
>  G_OBJECT_CLASS(main_dispatcher_parent_class)-
> >constructed(object);
> -dispatcher_set_opaque(DISPATCHER(self), self);
> +dispatcher_set_opaque(DISPATCHER(self), self->priv->reds);
>  
>  self->priv->watch =
>  reds_core_watch_add(self->priv->reds,

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 03/10] main-dispatcher: Remove main_dispatcher_self_handle_channel_event

2019-03-20 Thread Jonathon Jongsma
That's a weird function, but seems rather unrelated to the current
series.

Acked-by: Jonathon Jongsma 


On Wed, 2019-03-20 at 09:59 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/main-dispatcher.c | 13 ++---
>  1 file changed, 2 insertions(+), 11 deletions(-)
> 
> diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> index 82b25e6e..0dcfb2d4 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -149,22 +149,13 @@ typedef struct
> MainDispatcherClientDisconnectMessage {
>  } MainDispatcherClientDisconnectMessage;
>  
>  /* channel_event - calls core->channel_event, must be done in main
> thread */
> -static void main_dispatcher_self_handle_channel_event(MainDispatcher
> *self,
> -  int event,
> -  SpiceChannelEv
> entInfo *info)
> -{
> -reds_handle_channel_event(self->priv->reds, event, info);
> -}
> -
>  static void main_dispatcher_handle_channel_event(void *opaque,
>   void *payload)
>  {
>  MainDispatcher *self = opaque;
>  MainDispatcherChannelEventMessage *channel_event = payload;
>  
> -main_dispatcher_self_handle_channel_event(self,
> -  channel_event->event,
> -  channel_event->info);
> +reds_handle_channel_event(self->priv->reds, channel_event-
> >event, channel_event->info);
>  }
>  
>  void main_dispatcher_channel_event(MainDispatcher *self, int event,
> SpiceChannelEventInfo *info)
> @@ -172,7 +163,7 @@ void main_dispatcher_channel_event(MainDispatcher
> *self, int event, SpiceChannel
>  MainDispatcherChannelEventMessage msg = {0,};
>  
>  if (pthread_self() ==
> dispatcher_get_thread_id(DISPATCHER(self))) {
> -main_dispatcher_self_handle_channel_event(self, event,
> info);
> +reds_handle_channel_event(self->priv->reds, event, info);
>  return;
>  }
>  msg.event = event;

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 02/10] dispatcher: Allows to manage message without registering them

2019-03-20 Thread Jonathon Jongsma
02,22 @@ void dispatcher_handle_recv_read(Dispatcher
> *dispatcher)
>  }
>  }
>  
> -void dispatcher_send_message(Dispatcher *dispatcher, uint32_t
> message_type,
> - void *payload)
> +static void
> +dispatcher_send_message_internal(Dispatcher *dispatcher, const
> DispatcherMessage*msg,
> + void *payload)
>  {
> -DispatcherMessage *msg;
>  uint32_t ack;
>  int send_fd = dispatcher->priv->send_fd;
>  
> -assert(dispatcher->priv->max_message_type > message_type);
> -assert(dispatcher->priv->messages[message_type].handler);
> -msg = >priv->messages[message_type];
>  pthread_mutex_lock(>priv->lock);
> -if (write_safe(send_fd, (uint8_t*)_type,
> sizeof(message_type)) == -1) {
> +if (write_safe(send_fd, (uint8_t*)msg, sizeof(*msg)) == -1) {
>  g_warning("error: failed to send message type for message
> %d",
> -  message_type);
> +  msg->type);
>  goto unlock;
>  }
>  if (write_safe(send_fd, payload, msg->size) == -1) {
>  g_warning("error: failed to send message body for message
> %d",
> -  message_type);
> +  msg->type);
>  goto unlock;
>  }
>  if (msg->ack) {
> @@ -326,7 +325,7 @@ void dispatcher_send_message(Dispatcher
> *dispatcher, uint32_t message_type,
>  g_warning("error: failed to read ack");
>  } else if (ack != ACK) {
>  g_warning("error: got wrong ack value in dispatcher "
> -  "for message %d\n", message_type);
> +  "for message %d\n", msg->type);
>  /* TODO handling error? */
>  }
>  }
> @@ -334,6 +333,29 @@ unlock:
>  pthread_mutex_unlock(>priv->lock);
>  }
>  
> +void dispatcher_send_message(Dispatcher *dispatcher, uint32_t
> message_type,
> + void *payload)
> +{
> +DispatcherMessage *msg;
> +
> +assert(dispatcher->priv->max_message_type > message_type);
> +assert(dispatcher->priv->messages[message_type].handler);
> +msg = >priv->messages[message_type];
> +dispatcher_send_message_internal(dispatcher, msg, payload);
> +}
> +
> +void dispatcher_send_message_generic(Dispatcher *dispatcher,
> dispatcher_handle_message handler,
> + void *payload, uint32_t
> payload_size, bool ack)
> +{
> +DispatcherMessage msg = {
> +.handler = handler,
> +.size = payload_size,
> +.type = DISPATCHER_GENERIC_TYPE,
> +.ack = ack,
> +};
> +dispatcher_send_message_internal(dispatcher, , payload);
> +}
> +
>  void dispatcher_register_handler(Dispatcher *dispatcher, uint32_t
> message_type,
>   dispatcher_handle_message handler,
>   size_t size, bool ack)
> @@ -345,6 +367,7 @@ void dispatcher_register_handler(Dispatcher
> *dispatcher, uint32_t message_type,
>  msg = >priv->messages[message_type];
>  msg->handler = handler;
>  msg->size = size;
> +msg->type = message_type;
>  msg->ack = ack;
>  if (msg->size > dispatcher->priv->payload_size) {
>  dispatcher->priv->payload = g_realloc(dispatcher->priv-
> >payload, msg->size);
> diff --git a/server/dispatcher.h b/server/dispatcher.h
> index bb968e56..b8339c06 100644
> --- a/server/dispatcher.h
> +++ b/server/dispatcher.h
> @@ -99,6 +99,21 @@ typedef void (*dispatcher_handle_any_message)(void
> *opaque,
>  void dispatcher_send_message(Dispatcher *dispatcher, uint32_t
> message_type,
>   void *payload);
>  
> +/* dispatcher_send_message_generic
> + *
> + * Sends a message to the receiving thread.
> + *
> + * If the sent message is a message type requires an ACK, this
> function will
> + * block until it receives an ACK from the receiving thread.
> + *
> + * @handler:  callback to handle message
> + * @payload:  payload
> + * @payload_size: size of payload
> + * @ack:  acknowledge required. Make message synchronous
> + */
> +void dispatcher_send_message_generic(Dispatcher *dispatcher,
> dispatcher_handle_message handler,
> + void *payload, uint32_t
> payload_size, bool ack);
> +
>  /* dispatcher_register_handler
>   *
>   * This function registers a message type with the dispatcher, and
> registers


Reviewed-by: Jonathon Jongsma 


___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 01/10] dispatcher: Use NULL for pointer check

2019-03-20 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Wed, 2019-03-20 at 09:59 +, Frediano Ziglio wrote:
> handler is a pointer, check for NULL, not 0.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/dispatcher.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/server/dispatcher.c b/server/dispatcher.c
> index ce487f63..5f839ec4 100644
> --- a/server/dispatcher.c
> +++ b/server/dispatcher.c
> @@ -341,7 +341,7 @@ void dispatcher_register_handler(Dispatcher
> *dispatcher, uint32_t message_type,
>  DispatcherMessage *msg;
>  
>  assert(message_type < dispatcher->priv->max_message_type);
> -assert(dispatcher->priv->messages[message_type].handler == 0);
> +assert(dispatcher->priv->messages[message_type].handler ==
> NULL);
>  msg = >priv->messages[message_type];
>  msg->handler = handler;
>  msg->size = size;

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server 1/2] Move CursorChannel definition to header

2019-03-19 Thread Jonathon Jongsma
This way, the cursor channel can be subclassed. This will be used in
future commits as I refactor the client callbacks.
---
 server/cursor-channel.c | 62 +++--
 server/cursor-channel.h | 12 
 2 files changed, 40 insertions(+), 34 deletions(-)

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 4220084f5..d751211af 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -32,10 +32,8 @@ typedef struct RedCursorPipeItem {
 RedCursorCmd *red_cursor;
 } RedCursorPipeItem;
 
-struct CursorChannel
+struct CursorChannelPrivate
 {
-CommonGraphicsChannel parent;
-
 RedCursorPipeItem *item;
 bool cursor_visible;
 SpicePoint16 cursor_position;
@@ -44,12 +42,7 @@ struct CursorChannel
 uint32_t mouse_mode;
 };
 
-struct CursorChannelClass
-{
-CommonGraphicsChannelClass parent_class;
-};
-
-G_DEFINE_TYPE(CursorChannel, cursor_channel, TYPE_COMMON_GRAPHICS_CHANNEL)
+G_DEFINE_TYPE_WITH_PRIVATE(CursorChannel, cursor_channel, 
TYPE_COMMON_GRAPHICS_CHANNEL)
 
 static void cursor_pipe_item_free(RedPipeItem *pipe_item);
 
@@ -79,10 +72,10 @@ static void cursor_channel_set_item(CursorChannel *cursor, 
RedCursorPipeItem *it
 if (item) {
 red_pipe_item_ref(>base);
 }
-if (cursor->item) {
-red_pipe_item_unref(>item->base);
+if (cursor->priv->item) {
+red_pipe_item_unref(>priv->item->base);
 }
-cursor->item = item;
+cursor->priv->item = item;
 }
 
 static void cursor_fill(CursorChannelClient *ccc, RedCursorPipeItem *cursor,
@@ -128,12 +121,12 @@ static void red_marshall_cursor_init(CursorChannelClient 
*ccc, SpiceMarshaller *
 cursor_channel = CURSOR_CHANNEL(red_channel_client_get_channel(rcc));
 
 red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_INIT);
-msg.visible = cursor_channel->cursor_visible;
-msg.position = cursor_channel->cursor_position;
-msg.trail_length = cursor_channel->cursor_trail_length;
-msg.trail_frequency = cursor_channel->cursor_trail_frequency;
+msg.visible = cursor_channel->priv->cursor_visible;
+msg.position = cursor_channel->priv->cursor_position;
+msg.trail_length = cursor_channel->priv->cursor_trail_length;
+msg.trail_frequency = cursor_channel->priv->cursor_trail_frequency;
 
-cursor_fill(ccc, cursor_channel->item, , base_marshaller);
+cursor_fill(ccc, cursor_channel->priv->item, , base_marshaller);
 spice_marshall_msg_cursor_init(base_marshaller, );
 }
 
@@ -164,7 +157,7 @@ static void red_marshall_cursor(CursorChannelClient *ccc,
 
 red_channel_client_init_send_data(rcc, SPICE_MSG_CURSOR_SET);
 cursor_set.position = cmd->u.set.position;
-cursor_set.visible = cursor_channel->cursor_visible;
+cursor_set.visible = cursor_channel->priv->cursor_visible;
 
 cursor_fill(ccc, item, _set.cursor, m);
 spice_marshall_msg_cursor_set(m, _set);
@@ -253,20 +246,20 @@ void cursor_channel_process_cmd(CursorChannel *cursor, 
RedCursorCmd *cursor_cmd)
 
 switch (cursor_cmd->type) {
 case QXL_CURSOR_SET:
-cursor->cursor_visible = !!cursor_cmd->u.set.visible;
+cursor->priv->cursor_visible = !!cursor_cmd->u.set.visible;
 cursor_channel_set_item(cursor, cursor_pipe_item);
 break;
 case QXL_CURSOR_MOVE:
-cursor_show = !cursor->cursor_visible;
-cursor->cursor_visible = true;
-cursor->cursor_position = cursor_cmd->u.position;
+cursor_show = !cursor->priv->cursor_visible;
+cursor->priv->cursor_visible = true;
+cursor->priv->cursor_position = cursor_cmd->u.position;
 break;
 case QXL_CURSOR_HIDE:
-cursor->cursor_visible = false;
+cursor->priv->cursor_visible = false;
 break;
 case QXL_CURSOR_TRAIL:
-cursor->cursor_trail_length = cursor_cmd->u.trail.length;
-cursor->cursor_trail_frequency = cursor_cmd->u.trail.frequency;
+cursor->priv->cursor_trail_length = cursor_cmd->u.trail.length;
+cursor->priv->cursor_trail_frequency = cursor_cmd->u.trail.frequency;
 break;
 default:
 spice_warning("invalid cursor command %u", cursor_cmd->type);
@@ -275,7 +268,7 @@ void cursor_channel_process_cmd(CursorChannel *cursor, 
RedCursorCmd *cursor_cmd)
 }
 
 if (red_channel_is_connected(RED_CHANNEL(cursor)) &&
-(cursor->mouse_mode == SPICE_MOUSE_MODE_SERVER
+(cursor->priv->mouse_mode == SPICE_MOUSE_MODE_SERVER
  || cursor_cmd->type != QXL_CURSOR_MOVE
  || cursor_show)) {
 red_channel_pipes_add(RED_CHANNEL(cursor), _pipe_item->base);
@@ -291,9 +284,9 @@ void cursor_channel_reset(CursorChannel *cursor)
 spice_return_if_fail(cursor);
 
 cursor_channel_set_item(cursor, NULL);
-cursor->cursor_visible = true;
-cursor->cursor_position.x = cursor->cursor_position.y = 0;
-cursor->cursor_trail_length = 

[Spice-devel] [PATCH spice-server 2/2] Make channel client callbacks virtual functions

2019-03-19 Thread Jonathon Jongsma
Rather than having an API to register client callbacks for each channel
type, make them vfuncs.

Since the client callbacks are registered identically for each channel
of the same type, it doesn't make sense for to require these to be
registered separately for each object.  It's cleaner to have these be
per-class properties, so they've been converted to virtual functions.

Note that In order to avoid dependencies from the display and cursor
channels to the worker (necessary to perform the message dispatching
required), the worker itself subclasses these channels to provide
dispatching client callbacks.
---
 server/cursor-channel.c |   4 +
 server/display-channel.c|  29 
 server/display-channel.h|   7 -
 server/inputs-channel.c |   9 +-
 server/main-channel.c   |   7 +-
 server/red-channel.c|  35 ++---
 server/red-channel.h|  19 ++-
 server/red-qxl.c| 111 +-
 server/red-stream-device.c  |   5 -
 server/red-worker.c | 280 ++--
 server/red-worker.h |   4 +-
 server/smartcard.c  |   6 +-
 server/sound.c  |  18 ++-
 server/spicevmc.c   |   7 +-
 server/stream-channel.c |   5 +-
 server/tests/test-channel.c |  13 +-
 16 files changed, 316 insertions(+), 243 deletions(-)

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index d751211af..749c1c6b8 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -383,6 +383,10 @@ cursor_channel_class_init(CursorChannelClass *klass)
 channel_class->handle_message = red_channel_client_handle_message;
 
 channel_class->send_item = cursor_channel_send_item;
+
+// client callbacks
+channel_class->connect = (channel_client_connect_proc) 
cursor_channel_connect;
+channel_class->migrate = cursor_channel_client_migrate;
 }
 
 static void
diff --git a/server/display-channel.c b/server/display-channel.c
index e179abfd3..71912c1b9 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2224,35 +2224,6 @@ static SpiceCanvas 
*image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t su
 return p->surfaces[surface_id].context.canvas;
 }
 
-DisplayChannel* display_channel_new(RedsState *reds,
-QXLInstance *qxl,
-const SpiceCoreInterfaceInternal *core,
-int migrate, int stream_video,
-GArray *video_codecs,
-uint32_t n_surfaces)
-{
-DisplayChannel *display;
-
-/* FIXME: migrate is not used...? */
-spice_debug("create display channel");
-display = g_object_new(TYPE_DISPLAY_CHANNEL,
-   "spice-server", reds,
-   "core-interface", core,
-   "channel-type", SPICE_CHANNEL_DISPLAY,
-   "id", qxl->id,
-   "migration-flags",
-   (SPICE_MIGRATE_NEED_FLUSH | 
SPICE_MIGRATE_NEED_DATA_TRANSFER),
-   "qxl", qxl,
-   "n-surfaces", n_surfaces,
-   "video-codecs", video_codecs,
-   "handle-acks", TRUE,
-   NULL);
-if (display) {
-display_channel_set_stream_video(display, stream_video);
-}
-return display;
-}
-
 static SpiceCanvas *image_surfaces_get(SpiceImageSurfaces *surfaces, uint32_t 
surface_id);
 static void drawables_init(DisplayChannel *display);
 static void
diff --git a/server/display-channel.h b/server/display-channel.h
index 948018cf3..83727e17a 100644
--- a/server/display-channel.h
+++ b/server/display-channel.h
@@ -96,13 +96,6 @@ struct Drawable {
 DisplayChannel *display;
 };
 
-DisplayChannel*display_channel_new   
(RedsState *reds,
-  
QXLInstance *qxl,
-  const 
SpiceCoreInterfaceInternal *core,
-  int 
migrate,
-  int 
stream_video,
-  GArray 
*video_codecs,
-  uint32_t 
n_surfaces);
 void   display_channel_create_surface
(DisplayChannel *display, uint32_t surface_id,
   uint32_t 
width, uint32_t height,
   int32_t 
stride, uint32_t format, void *line_0,
diff --git a/server/inputs-channel.c b/server/inputs-channel.c
index a7df62e2a..eff5421ae 100644
--- a/server/inputs-channel.c
+++ 

Re: [Spice-devel] [PATCH spice-common v3 0/5] Generate C declarations automatically

2019-03-18 Thread Jonathon Jongsma
On Mon, 2019-03-18 at 09:53 -0400, Frediano Ziglio wrote:
> > On Mon, Mar 11, 2019 at 12:42:10PM -0400, Frediano Ziglio wrote:
> > > > 
> > > > Series looks good to me,
> > > > 
> > > > Reviewed-by: Christophe Fergeau 
> > > > 
> > > 
> > > Why not ack? Not good enough? Not tested? Missing something?
> > 
> > libvirt/qemu use of Reviewed-by/Acked-by confuses me, and to me
> > they are
> > more or less equivalent.
> > 
> > Christophe
> > 
> 
> As long as we are coherent is fine. But to me looks like some
> (Jonathon?)
> use Reviewed-by to mark as "the patch was fully reviewed but some
> thinks
> need updates".
> 
> Frediano

I usually use Reviewed-by to indicate that I looked at it, but am not
necessarily comfortable Acking it yet. But you're right that there's
not really any agreement on what this means. Would be good to be
consistent.

Jonathon

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2] Move channel registration to constructed vfunc

2019-03-15 Thread Jonathon Jongsma
On Fri, 2019-03-15 at 05:05 -0400, Frediano Ziglio wrote:
> > 
> > For the Display Channel and the Cursor channel, move the call to
> > reds_register_channel() to the _constructed() vfunc rather than
> > calling
> > it explicitly from RedWorker. This matches what other channels do.
> > ---
> > Changes in v2:
> >  - remove cursor channel registration in stream device
> > 
> > Note that I didn't implement a couple other suggestions from
> > Frediano's first
> > review. Reference
> > earlier email reply for justification.
> > 
> 
> Why this comment? Were you waiting for my reply?
> I though was the normal review process and I had no reason to reply.
> Did I misunderstand?
> 

No, I was just explaining why I didn't change some things that you had
suggested in your first review. It took a little while between my
initial patch and this one, so I thought I'd provide a bit more context
in case you had forgotten.

Jonathon

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server v2] Move channel registration to constructed vfunc

2019-03-14 Thread Jonathon Jongsma
For the Display Channel and the Cursor channel, move the call to
reds_register_channel() to the _constructed() vfunc rather than calling
it explicitly from RedWorker. This matches what other channels do.
---
Changes in v2:
 - remove cursor channel registration in stream device

Note that I didn't implement a couple other suggestions from Frediano's first 
review. Reference
earlier email reply for justification.

 server/cursor-channel.c| 12 
 server/display-channel.c   |  2 ++
 server/red-stream-device.c |  1 -
 server/red-worker.c|  2 --
 4 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 9dd69fa25..4220084f5 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -366,12 +366,24 @@ cursor_channel_finalize(GObject *object)
 G_OBJECT_CLASS(cursor_channel_parent_class)->finalize(object);
 }
 
+static void
+cursor_channel_constructed(GObject *object)
+{
+RedChannel *red_channel = RED_CHANNEL(object);
+RedsState *reds = red_channel_get_server(red_channel);
+
+G_OBJECT_CLASS(cursor_channel_parent_class)->constructed(object);
+
+reds_register_channel(reds, red_channel);
+}
+
 static void
 cursor_channel_class_init(CursorChannelClass *klass)
 {
 GObjectClass *object_class = G_OBJECT_CLASS(klass);
 RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
 
+object_class->constructed = cursor_channel_constructed;
 object_class->finalize = cursor_channel_finalize;
 
 channel_class->parser = 
spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
diff --git a/server/display-channel.c b/server/display-channel.c
index e68ed10f8..6684135eb 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2304,6 +2304,8 @@ display_channel_constructed(GObject *object)
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE);
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
+
+reds_register_channel(reds, channel);
 }
 
 void display_channel_process_surface_cmd(DisplayChannel *display,
diff --git a/server/red-stream-device.c b/server/red-stream-device.c
index b9e0827af..78a8c9083 100644
--- a/server/red-stream-device.c
+++ b/server/red-stream-device.c
@@ -701,7 +701,6 @@ stream_device_create_channel(StreamDevice *dev)
 client_cbs.connect = (channel_client_connect_proc) cursor_channel_connect;
 client_cbs.migrate = cursor_channel_client_migrate;
 red_channel_register_client_cbs(RED_CHANNEL(cursor_channel), _cbs);
-reds_register_channel(reds, RED_CHANNEL(cursor_channel));
 
 dev->stream_channel = stream_channel;
 dev->cursor_channel = cursor_channel;
diff --git a/server/red-worker.c b/server/red-worker.c
index c74ae8886..3cb12b9c2 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1322,7 +1322,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
 red_channel_init_stat_node(channel, >stat, "cursor_channel");
 red_channel_register_client_cbs(channel, client_cursor_cbs);
 g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher);
-reds_register_channel(reds, channel);
 
 // TODO: handle seamless migration. Temp, setting migrate to FALSE
 worker->display_channel = display_channel_new(reds, qxl, >core, 
FALSE,
@@ -1333,7 +1332,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
 red_channel_init_stat_node(channel, >stat, "display_channel");
 red_channel_register_client_cbs(channel, client_display_cbs);
 g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher);
-reds_register_channel(reds, channel);
 
 return worker;
 }
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH win-vdagent v2] Don't exit when receiving unknown messages

2019-03-04 Thread Jonathon Jongsma
In 8251fa25, a check on the minimum size of a message was introduced.
For unsupported messages, the vdagent simply exited. This makes it
inconsistent with previous behavior and inconsistent with the behavior
of the linux vdagent.  Instead, just print a warning indicating that an
unsupported message was received and ignore it.

Signed-off-by: Jonathon Jongsma 
---
changes in v2:
 - change rationale in commit log

 vdagent/vdagent.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 89019bb..177e663 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -1288,8 +1288,7 @@ void VDAgent::dispatch_message(VDAgentMessage* msg, 
uint32_t port)
 break;
 }
 if (min_size < 0) {
-vd_printf("Unsupported message type %u size %u", msg->type, msg->size);
-_running = false;
+vd_printf("Unsupported message type %u size %u, ignoring", msg->type, 
msg->size);
 return;
 }
 if (msg->size < (unsigned) min_size) {
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server v2 3/3] Switch some boolean fields to 'bool' type

2019-03-04 Thread Jonathon Jongsma
For coding style consistency, use 'bool' when we want to represent a
boolean value.

Signed-off-by: Jonathon Jongsma 
---
Changes in v2:
 - new patch


 server/reds.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 07562b555..db93acd16 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -231,9 +231,9 @@ typedef enum {
 } VDIPortReadStates;
 
 struct RedCharDeviceVDIPortPrivate {
-gboolean agent_attached;
+bool agent_attached;
 uint32_t plug_generation;
-int client_agent_started;
+bool client_agent_started;
 bool agent_supports_graphics_device_info;
 
 /* write to agent */
@@ -486,7 +486,7 @@ static void reds_reset_vdp(RedsState *reds)
  * to be sent from the client. This TODO will require server, protocol, 
and client changes */
 dev->priv->write_filter.result = AGENT_MSG_FILTER_DISCARD;
 dev->priv->write_filter.discard_all = TRUE;
-dev->priv->client_agent_started = FALSE;
+dev->priv->client_agent_started = false;
 dev->priv->agent_supports_graphics_device_info = false;
 
 /*  The client's tokens are set once when the main channel is initialized
@@ -1151,7 +1151,7 @@ void reds_on_main_agent_start(RedsState *reds, 
MainChannelClient *mcc, uint32_t
 spice_assert(reds->vdagent->st && reds->vdagent->st == dev_state);
 rcc = RED_CHANNEL_CLIENT(mcc);
 client = red_channel_client_get_client(rcc);
-reds->agent_dev->priv->client_agent_started = TRUE;
+reds->agent_dev->priv->client_agent_started = true;
 /*
  * Note that in older releases, send_tokens were set to ~0 on both client
  * and server. The server ignored the client given tokens.
@@ -3156,7 +3156,7 @@ static RedCharDevice *attach_to_red_agent(RedsState 
*reds, SpiceCharDeviceInstan
 RedCharDeviceVDIPort *dev = reds->agent_dev;
 SpiceCharDeviceInterface *sif;
 
-dev->priv->agent_attached = TRUE;
+dev->priv->agent_attached = true;
 red_char_device_reset_dev_instance(RED_CHAR_DEVICE(dev), sin);
 
 reds->vdagent = sin;
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server v2 1/3] Refactor agent_adjust_capabilities() function

2019-03-04 Thread Jonathon Jongsma
Make this a RedsState member function rather than a standalone function.
This means that we simply pass RedsState* as an argument rather than the
internal member variables of RedsState. This enables the following
commit which handles the VD_AGENT_CAP_GRAPHICS_DEVICE_INFO capability to
avoid sending graphics device info to agents that do not support it.

Signed-off-by: Jonathon Jongsma 
---
 server/reds.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 2e5c69e60..63bfadb22 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -793,8 +793,9 @@ static void vdi_port_read_buf_free(RedPipeItem *base)
 g_free(buf);
 }
 
-static void agent_adjust_capabilities(VDAgentMessage *message,
-  bool clipboard_enabled, bool 
xfer_enabled)
+/* certain agent capabilities can be overridden and disabled in the server. In 
these cases, unset
+ * these capabilities before sending them on to the client */
+static void reds_adjust_agent_capabilities(RedsState *reds, VDAgentMessage 
*message)
 {
 VDAgentAnnounceCapabilities *capabilities;
 
@@ -803,13 +804,13 @@ static void agent_adjust_capabilities(VDAgentMessage 
*message,
 }
 capabilities = (VDAgentAnnounceCapabilities *) message->data;
 
-if (!clipboard_enabled) {
+if (!reds->config->agent_copypaste) {
 VD_AGENT_CLEAR_CAPABILITY(capabilities->caps, VD_AGENT_CAP_CLIPBOARD);
 VD_AGENT_CLEAR_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
 VD_AGENT_CLEAR_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_CLIPBOARD_SELECTION);
 }
 
-if (!xfer_enabled) {
+if (!reds->config->agent_file_xfer) {
 VD_AGENT_SET_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_FILE_XFER_DISABLED);
 }
 }
@@ -879,9 +880,7 @@ static RedPipeItem 
*vdi_port_read_one_msg_from_device(RedCharDevice *self,
 }
 switch (vdi_port_read_buf_process(dev, dispatch_buf)) {
 case AGENT_MSG_FILTER_OK:
-agent_adjust_capabilities((VDAgentMessage *) 
dispatch_buf->data,
-  reds->config->agent_copypaste,
-  reds->config->agent_file_xfer);
+reds_adjust_agent_capabilities(reds, (VDAgentMessage *) 
dispatch_buf->data);
 return _buf->base;
 case AGENT_MSG_FILTER_PROTO_ERROR:
 reds_agent_remove(reds);
@@ -1380,9 +1379,7 @@ void reds_on_main_channel_migrate(RedsState *reds, 
MainChannelClient *mcc)
 read_buf->len = read_data_len;
 switch (vdi_port_read_buf_process(agent_dev, read_buf)) {
 case AGENT_MSG_FILTER_OK:
-agent_adjust_capabilities((VDAgentMessage *)read_buf->data,
-  reds->config->agent_copypaste,
-  reds->config->agent_file_xfer);
+reds_adjust_agent_capabilities(reds, (VDAgentMessage 
*)read_buf->data);
 main_channel_client_push_agent_data(mcc,
 read_buf->data,
 read_buf->len,
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server v2 2/3] Only send device display info to supported agents

2019-03-04 Thread Jonathon Jongsma
Only send the graphics device display info to agents that advertise the
VD_AGENT_CAP_GRAPHICS_DEVICE_INFO capability

Signed-off-by: Jonathon Jongsma 
---
Changes in v2:
 - renamed member variable
 - moved variable to RedCharDeviceVDIPortPrivate
 - reset variable when agent disconnects
 - make sure the message is sent immediately when we receive the capabilities.

NOTE: I did not change the function name as requested to 
filter_agent_capabilities because there is
already a agent message filter which determines whether a message should be 
handled or discarded,
etc. Adding another 'filter' concept would confuse things. I think "adjust_" 
seems fine to me.

 server/reds.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/server/reds.c b/server/reds.c
index 63bfadb22..07562b555 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -234,6 +234,7 @@ struct RedCharDeviceVDIPortPrivate {
 gboolean agent_attached;
 uint32_t plug_generation;
 int client_agent_started;
+bool agent_supports_graphics_device_info;
 
 /* write to agent */
 RedCharDeviceWriteBuffer *recv_from_client_buf;
@@ -486,6 +487,7 @@ static void reds_reset_vdp(RedsState *reds)
 dev->priv->write_filter.result = AGENT_MSG_FILTER_DISCARD;
 dev->priv->write_filter.discard_all = TRUE;
 dev->priv->client_agent_started = FALSE;
+dev->priv->agent_supports_graphics_device_info = false;
 
 /*  The client's tokens are set once when the main channel is initialized
  *  and once upon agent's connection with 
SPICE_MSG_MAIN_AGENT_CONNECTED_TOKENS.
@@ -813,6 +815,11 @@ static void reds_adjust_agent_capabilities(RedsState 
*reds, VDAgentMessage *mess
 if (!reds->config->agent_file_xfer) {
 VD_AGENT_SET_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_FILE_XFER_DISABLED);
 }
+
+size_t caps_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(message->size);
+reds->agent_dev->priv->agent_supports_graphics_device_info =
+VD_AGENT_HAS_CAPABILITY(capabilities->caps, caps_size, 
VD_AGENT_CAP_GRAPHICS_DEVICE_INFO);
+reds_send_device_display_info(reds);
 }
 
 /* reads from the device till completes reading a message that is addressed to 
the client,
@@ -965,6 +972,10 @@ void reds_send_device_display_info(RedsState *reds)
 if (!reds->agent_dev->priv->agent_attached) {
 return;
 }
+if (!reds->agent_dev->priv->agent_supports_graphics_device_info) {
+return;
+}
+
 g_debug("Sending device display info to the agent:");
 
 SpiceMarshaller *m = spice_marshaller_new();
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server 1/2] Refactor agent_adjust_capabilities() function

2019-02-28 Thread Jonathon Jongsma
Make this a RedsState member function rather than a standalone function.
This means that we simply pass RedsState* as an argument rather than the
internal member variables of RedsState. This enables the following
commit which handles the VD_AGENT_CAP_GRAPHICS_DEVICE_INFO capability to
avoid sending graphics device info to agents that do not support it.

Signed-off-by: Jonathon Jongsma 
---
 server/reds.c | 17 +++--
 1 file changed, 7 insertions(+), 10 deletions(-)

diff --git a/server/reds.c b/server/reds.c
index 2e5c69e60..63bfadb22 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -793,8 +793,9 @@ static void vdi_port_read_buf_free(RedPipeItem *base)
 g_free(buf);
 }
 
-static void agent_adjust_capabilities(VDAgentMessage *message,
-  bool clipboard_enabled, bool 
xfer_enabled)
+/* certain agent capabilities can be overridden and disabled in the server. In 
these cases, unset
+ * these capabilities before sending them on to the client */
+static void reds_adjust_agent_capabilities(RedsState *reds, VDAgentMessage 
*message)
 {
 VDAgentAnnounceCapabilities *capabilities;
 
@@ -803,13 +804,13 @@ static void agent_adjust_capabilities(VDAgentMessage 
*message,
 }
 capabilities = (VDAgentAnnounceCapabilities *) message->data;
 
-if (!clipboard_enabled) {
+if (!reds->config->agent_copypaste) {
 VD_AGENT_CLEAR_CAPABILITY(capabilities->caps, VD_AGENT_CAP_CLIPBOARD);
 VD_AGENT_CLEAR_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_CLIPBOARD_BY_DEMAND);
 VD_AGENT_CLEAR_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_CLIPBOARD_SELECTION);
 }
 
-if (!xfer_enabled) {
+if (!reds->config->agent_file_xfer) {
 VD_AGENT_SET_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_FILE_XFER_DISABLED);
 }
 }
@@ -879,9 +880,7 @@ static RedPipeItem 
*vdi_port_read_one_msg_from_device(RedCharDevice *self,
 }
 switch (vdi_port_read_buf_process(dev, dispatch_buf)) {
 case AGENT_MSG_FILTER_OK:
-agent_adjust_capabilities((VDAgentMessage *) 
dispatch_buf->data,
-  reds->config->agent_copypaste,
-  reds->config->agent_file_xfer);
+reds_adjust_agent_capabilities(reds, (VDAgentMessage *) 
dispatch_buf->data);
 return _buf->base;
 case AGENT_MSG_FILTER_PROTO_ERROR:
 reds_agent_remove(reds);
@@ -1380,9 +1379,7 @@ void reds_on_main_channel_migrate(RedsState *reds, 
MainChannelClient *mcc)
 read_buf->len = read_data_len;
 switch (vdi_port_read_buf_process(agent_dev, read_buf)) {
 case AGENT_MSG_FILTER_OK:
-agent_adjust_capabilities((VDAgentMessage *)read_buf->data,
-  reds->config->agent_copypaste,
-  reds->config->agent_file_xfer);
+reds_adjust_agent_capabilities(reds, (VDAgentMessage 
*)read_buf->data);
 main_channel_client_push_agent_data(mcc,
 read_buf->data,
 read_buf->len,
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server 2/2] Only send device display info to supported agents

2019-02-28 Thread Jonathon Jongsma
Only send the graphics device display info to agents that advertise the
VD_AGENT_CAP_GRAPHICS_DEVICE_INFO capability

Signed-off-by: Jonathon Jongsma 
---
 server/reds-private.h | 1 +
 server/reds.c | 9 +
 2 files changed, 10 insertions(+)

diff --git a/server/reds-private.h b/server/reds-private.h
index 9dbc7fa94..b2b99b50e 100644
--- a/server/reds-private.h
+++ b/server/reds-private.h
@@ -134,6 +134,7 @@ struct RedsState {
 GList *qxl_instances;
 MainDispatcher *main_dispatcher;
 RedRecord *record;
+gboolean agent_graphics_device_info;
 };
 
 #define FOREACH_QXL_INSTANCE(_reds, _qxl) \
diff --git a/server/reds.c b/server/reds.c
index 63bfadb22..4228ab6ad 100644
--- a/server/reds.c
+++ b/server/reds.c
@@ -813,6 +813,10 @@ static void reds_adjust_agent_capabilities(RedsState 
*reds, VDAgentMessage *mess
 if (!reds->config->agent_file_xfer) {
 VD_AGENT_SET_CAPABILITY(capabilities->caps, 
VD_AGENT_CAP_FILE_XFER_DISABLED);
 }
+
+size_t caps_size = VD_AGENT_CAPS_SIZE_FROM_MSG_SIZE(message->size);
+reds->agent_graphics_device_info = 
VD_AGENT_HAS_CAPABILITY(capabilities->caps, caps_size,
+   
VD_AGENT_CAP_GRAPHICS_DEVICE_INFO);
 }
 
 /* reads from the device till completes reading a message that is addressed to 
the client,
@@ -965,6 +969,11 @@ void reds_send_device_display_info(RedsState *reds)
 if (!reds->agent_dev->priv->agent_attached) {
 return;
 }
+if (!reds->agent_graphics_device_info) {
+g_debug("Not sending device display info to the agent because the 
agent does not support it");
+return;
+}
+
 g_debug("Sending device display info to the agent:");
 
 SpiceMarshaller *m = spice_marshaller_new();
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH linux vdagent] Advertise VD_AGENT_CAP_GRAPHICS_DEVICE_INFO

2019-02-28 Thread Jonathon Jongsma
Since we now support the graphics device info message, advertise this
fact when sending capabilities to the server.

Signed-off-by: Jonathon Jongsma 
---
 src/vdagentd/vdagentd.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c
index f80f48b..72a3e13 100644
--- a/src/vdagentd/vdagentd.c
+++ b/src/vdagentd/vdagentd.c
@@ -132,6 +132,7 @@ static void send_capabilities(struct vdagent_virtio_port 
*vport,
 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GUEST_LINEEND_LF);
 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_MAX_CLIPBOARD);
 VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_AUDIO_VOLUME_SYNC);
+VD_AGENT_SET_CAPABILITY(caps->caps, VD_AGENT_CAP_GRAPHICS_DEVICE_INFO);
 virtio_msg_uint32_to_le((uint8_t *)caps, size, 0);
 
 vdagent_virtio_port_write(vport, VDP_CLIENT_PORT,
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH win-vdagent] Don't exit when receiving unknown messages

2019-02-28 Thread Jonathon Jongsma
On Thu, 2019-02-28 at 03:31 -0500, Frediano Ziglio wrote:
> > 
> > In 8251fa25, a check on the minimum size of a message was
> > introduced.
> > For unsupported messages, the vdagent simply exited. This makes it
> > difficult to extend the vdagent protocol without breaking old
> 
> The protocol is using capabilities, there should not be
> unsupported messages.
> 
> > installations. Instead, just print a warning indicating that an
> > unsupported message was received and ignore it.
> > 
> 
> If you want to print a warning it means that it's not correct,
> this is another indication that it's wrong.
> 
> > Signed-off-by: Jonathon Jongsma 
> > ---
> >  vdagent/vdagent.cpp | 3 +--
> >  1 file changed, 1 insertion(+), 2 deletions(-)
> > 
> > diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
> > index 89019bb..177e663 100644
> > --- a/vdagent/vdagent.cpp
> > +++ b/vdagent/vdagent.cpp
> > @@ -1288,8 +1288,7 @@ void
> > VDAgent::dispatch_message(VDAgentMessage* msg,
> > uint32_t port)
> >  break;
> >  }
> >  if (min_size < 0) {
> > -vd_printf("Unsupported message type %u size %u", msg-
> > >type,
> > msg->size);
> > -_running = false;
> > +vd_printf("Unsupported message type %u size %u, ignoring",
> > msg->type, msg->size);
> >  return;
> >  }
> >  if (msg->size < (unsigned) min_size) {
> 
> RHEL 8 has 8251fa25 patch, should the users be forced to update
> the guests?
> If we want to change the protocol to allow unsupported message we
> should first change the protocol specification, this is not a
> fix, it's a workaround for a wrong/incomplete implementation on
> the server side.
> I prefer a proper fix than a workaround and this is not
> fixing already installed guests.
> 
> Frediano


Well, I didn't necessarily mean that this is a full solution, but I
think it is still an improvement. In fact, this was the behavior that
vdagent-win had before commit 8251fa25. For example, later on in this
function when we're handling the messages, there is the following code:

default:
vd_printf("Unsupported message type %u size %u", msg->type, msg->size);
}

The agent does not exit due to an unsupported message. It just prints a
warning.

In addition, this is the same behavior as the linux vdagent. In linux
src/vdagentd/vdagentd.c function virtio_port_read_complete():

default:
g_warn_if_reached();
}

return 0;

So: Linux vdagent prints a warning, but the vdagent does not exit. 

You say above that my change requires a change to the protocol, but in
fact this is how both vdagents worked for years until commit 8251fa25
made the windows agent exit when it encounters unsupported messages. So
I would argue that patch 8251fa25 actually introduced a regression in
RHEL 8.0.

Jonathon

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH win-vdagent] Don't exit when receiving unknown messages

2019-02-27 Thread Jonathon Jongsma
In 8251fa25, a check on the minimum size of a message was introduced.
For unsupported messages, the vdagent simply exited. This makes it
difficult to extend the vdagent protocol without breaking old
installations. Instead, just print a warning indicating that an
unsupported message was received and ignore it.

Signed-off-by: Jonathon Jongsma 
---
 vdagent/vdagent.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/vdagent/vdagent.cpp b/vdagent/vdagent.cpp
index 89019bb..177e663 100644
--- a/vdagent/vdagent.cpp
+++ b/vdagent/vdagent.cpp
@@ -1288,8 +1288,7 @@ void VDAgent::dispatch_message(VDAgentMessage* msg, 
uint32_t port)
 break;
 }
 if (min_size < 0) {
-vd_printf("Unsupported message type %u size %u", msg->type, msg->size);
-_running = false;
+vd_printf("Unsupported message type %u size %u, ignoring", msg->type, 
msg->size);
 return;
 }
 if (msg->size < (unsigned) min_size) {
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server] red-pipe-item: Removed some not necessary headers inclusions

2019-02-22 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Fri, 2019-02-22 at 16:12 +, Frediano Ziglio wrote:
> RedPipeItem is not using the Ring structures anymore.
> Also is not using GLib functionality.
> Just include base headers.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/red-pipe-item.h | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/server/red-pipe-item.h b/server/red-pipe-item.h
> index 8e9115725..2cfb5ddbd 100644
> --- a/server/red-pipe-item.h
> +++ b/server/red-pipe-item.h
> @@ -19,8 +19,8 @@
>  #ifndef RED_PIPE_ITEM_H_
>  #define RED_PIPE_ITEM_H_
>  
> -#include 
> -#include 
> +#include 
> +#include 
>  
>  typedef struct RedPipeItem RedPipeItem;
>  

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-common 6/6] Generate automatically most C message declarations

2019-02-22 Thread Jonathon Jongsma
So, I applied these patches, and generated the messages with the new
code and compared it to the old hand-coded message.h file. I had to re-
arrange a bunch of the newly-generated code to get a readable diff, but
I end up with the attached output. A few notable changes:

- Quite a few fields have changed type (uint32_t => uint16_t in most
cases, a few cases of uint32_t => uint8_t)

- SpiceMsgData lost its data_size field?

- SpiceMsgPlaybackPacket seems to have had some fields re-arranged. Old
type was { time, data, data_size }. New type is { time, data_size, data
}

- smartcard messages are gone

Jonathon



On Thu, 2019-02-21 at 10:38 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  common/messages.h | 495 +---
> --
>  spice.proto   | 192 +-
>  2 files changed, 102 insertions(+), 585 deletions(-)
> 
> diff --git a/common/messages.h b/common/messages.h
> index aae3212..43d0661 100644
> --- a/common/messages.h
> +++ b/common/messages.h
> @@ -42,10 +42,6 @@
>  
>  SPICE_BEGIN_DECLS
>  
> -typedef struct SpiceMsgData {
> -uint8_t data[0];
> -} SpiceMsgData;
> -
>  typedef struct SpiceMsgCompressedData {
>  uint8_t type;
>  uint32_t uncompressed_size;
> @@ -53,438 +49,8 @@ typedef struct SpiceMsgCompressedData {
>  uint8_t *compressed_data;
>  } SpiceMsgCompressedData;
>  
> -typedef struct SpiceMsgEmpty {
> -uint8_t padding;
> -} SpiceMsgEmpty;
> -
> -typedef struct SpiceMsgInputsInit {
> -uint32_t keyboard_modifiers;
> -} SpiceMsgInputsInit;
> -
> -typedef struct SpiceMsgInputsKeyModifiers {
> -uint32_t modifiers;
> -} SpiceMsgInputsKeyModifiers;
> -
> -typedef struct SpiceMsgMainMultiMediaTime {
> -uint32_t time;
> -} SpiceMsgMainMultiMediaTime;
> -
> -typedef struct SpiceMigrationDstInfo {
> -uint16_t port;
> -uint16_t sport;
> -uint32_t host_size;
> -uint8_t *host_data;
> -uint32_t cert_subject_size;
> -uint8_t *cert_subject_data;
> -} SpiceMigrationDstInfo;
> -
> -typedef struct SpiceMsgMainMigrationBegin {
> -SpiceMigrationDstInfo dst_info;
> -} SpiceMsgMainMigrationBegin;
> -
> -typedef struct SpiceMsgMainMigrateBeginSeamless {
> -SpiceMigrationDstInfo dst_info;
> -uint32_t src_mig_version;
> -} SpiceMsgMainMigrateBeginSeamless;
> -
> -typedef struct SpiceMsgcMainMigrateDstDoSeamless {
> -uint32_t src_version;
> -} SpiceMsgcMainMigrateDstDoSeamless;
> -
> -typedef struct SpiceMsgMainMigrationSwitchHost {
> -uint16_t port;
> -uint16_t sport;
> -uint32_t host_size;
> -uint8_t *host_data;
> -uint32_t cert_subject_size;
> -uint8_t *cert_subject_data;
> -} SpiceMsgMainMigrationSwitchHost;
> -
> -
> -typedef struct SpiceMsgMigrate {
> -uint32_t flags;
> -} SpiceMsgMigrate;
> -
> -typedef struct SpiceResourceID {
> -uint8_t type;
> -uint64_t id;
> -} SpiceResourceID;
> -
> -typedef struct SpiceResourceList {
> -uint16_t count;
> -SpiceResourceID resources[0];
> -} SpiceResourceList;
> -
> -typedef struct SpiceMsgSetAck {
> -uint32_t generation;
> -uint32_t window;
> -} SpiceMsgSetAck;
> -
> -typedef struct SpiceMsgcAckSync {
> -  uint32_t generation;
> -} SpiceMsgcAckSync;
> -
> -typedef struct SpiceWaitForChannel {
> -uint8_t channel_type;
> -uint8_t channel_id;
> -uint64_t message_serial;
> -} SpiceWaitForChannel;
> -
> -typedef struct SpiceMsgWaitForChannels {
> -uint8_t wait_count;
> -SpiceWaitForChannel wait_list[0];
> -} SpiceMsgWaitForChannels;
> -
> -typedef struct SpiceChannelId {
> -uint8_t type;
> -uint8_t id;
> -} SpiceChannelId;
> -
> -typedef struct SpiceMsgMainInit {
> -uint32_t session_id;
> -uint32_t display_channels_hint;
> -uint32_t supported_mouse_modes;
> -uint32_t current_mouse_mode;
> -uint32_t agent_connected;
> -uint32_t agent_tokens;
> -uint32_t multi_media_time;
> -uint32_t ram_hint;
> -} SpiceMsgMainInit;
> -
> -typedef struct SpiceMsgDisconnect {
> -uint64_t time_stamp;
> -uint32_t reason; // SPICE_ERR_?
> -} SpiceMsgDisconnect;
> -
> -typedef struct SpiceMsgNotify {
> -uint64_t time_stamp;
> -uint32_t severity;
> -uint32_t visibilty;
> -uint32_t what;
> -uint32_t message_len;
> -uint8_t message[0];
> -} SpiceMsgNotify;
> -
> -typedef struct SpiceMsgChannels {
> -uint32_t num_of_channels;
> -SpiceChannelId channels[0];
> -} SpiceMsgChannels;
> -
> -typedef struct SpiceMsgMainName {
> -uint32_t name_len;
> -uint8_t name[0];
> -} SpiceMsgMainName;
> -
> -typedef struct SpiceMsgMainUuid {
> -uint8_t uuid[16];
> -} SpiceMsgMainUuid;
> -
> -typedef struct SpiceMsgMainMouseMode {
> -uint32_t supported_modes;
> -uint32_t current_mode;
> -} SpiceMsgMainMouseMode;
> -
> -typedef struct SpiceMsgPing {
> -uint32_t id;
> -uint64_t timestamp;
> -void *data;
> -uint32_t data_len;
> -} SpiceMsgPing;
> -
> -typedef struct SpiceMsgMainAgentDisconnect {
> -   

Re: [Spice-devel] [PATCH spice-common 1/6] messages: Remove fields not used by the protocol

2019-02-22 Thread Jonathon Jongsma
On Thu, 2019-02-21 at 10:38 +, Frediano Ziglio wrote:
> These fields are not used by the protocol.
> Avoid spice-gtk and spice-server to use them by mistake.
> This can cause memory errors (data_size is not used or
> is not set correctly) and useless code (spice-gtk uses
> the pub_key* fields but these fields are not sent to
> the server as the protocol does not have them).
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  common/messages.h | 4 
>  1 file changed, 4 deletions(-)
> 
> diff --git a/common/messages.h b/common/messages.h
> index 3e37235..91ac7ad 100644
> --- a/common/messages.h
> +++ b/common/messages.h
> @@ -43,7 +43,6 @@
>  SPICE_BEGIN_DECLS
>  
>  typedef struct SpiceMsgData {
> -uint32_t data_size;
>  uint8_t data[0];
>  } SpiceMsgData;
>  
> @@ -75,9 +74,6 @@ typedef struct SpiceMigrationDstInfo {
>  uint16_t sport;
>  uint32_t host_size;
>  uint8_t *host_data;
> -uint16_t pub_key_type;
> -uint32_t pub_key_size;
> -uint8_t *pub_key_data;
>  uint32_t cert_subject_size;
>  uint8_t *cert_subject_data;
>  } SpiceMigrationDstInfo;


Hmm, slightly tricky, this one. It's technically an ABI change, but
since we only use spice-common as a submodule, I suppose it's OK to
remove.

I'd like to see the commit log mention that this is leftover from v1 of
the protocol, which we removed support for already.

Acked-by: Jonathon Jongsma 


___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server] Removed some not necessary headers inclusions

2019-02-21 Thread Jonathon Jongsma
On Thu, 2019-02-21 at 14:41 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/display-channel.h | 3 ---
>  server/inputs-channel.h  | 1 -
>  server/main-dispatcher.h | 1 -
>  server/red-channel.h | 1 -
>  server/red-parse-qxl.h   | 1 -
>  server/red-record-qxl.h  | 1 -
>  6 files changed, 8 deletions(-)
> 
> diff --git a/server/display-channel.h b/server/display-channel.h
> index 948018cf3..be853e891 100644
> --- a/server/display-channel.h
> +++ b/server/display-channel.h
> @@ -24,13 +24,10 @@
>  
>  #include "reds.h"
>  #include "red-parse-qxl.h"
> -#include "red-channel.h"
>  #include "main-channel.h"
> -#include "spice-bitmap-utils.h"
>  #include "tree.h"
>  #include "video-stream.h"
>  #include "dcc.h"
> -#include "image-encoders.h"
>  #include "common-graphics-channel.h"

Seems that display-channel.h uses a GlzImageRetention type which is
defined in image-encoders.h. And BitmapGradualType which is defined in
spice-bitmap-utils.h. Presumably these headers are indirectly pulled in
via other includes, but it's unwise to rely on that.

Other ones below have similar issues. How did you decide to remove
these headers?

Reviewed-by: Jonathon Jongsma 


>  
>  G_BEGIN_DECLS
> diff --git a/server/inputs-channel.h b/server/inputs-channel.h
> index 945ba6173..b771eb1af 100644
> --- a/server/inputs-channel.h
> +++ b/server/inputs-channel.h
> @@ -23,7 +23,6 @@
>  
>  #include 
>  #include 
> -#include 
>  
>  #include "red-channel.h"
>  
> diff --git a/server/main-dispatcher.h b/server/main-dispatcher.h
> index e1244f836..ba3efa2da 100644
> --- a/server/main-dispatcher.h
> +++ b/server/main-dispatcher.h
> @@ -19,7 +19,6 @@
>  #ifndef MAIN_DISPATCHER_H_
>  #define MAIN_DISPATCHER_H_
>  
> -#include "spice.h"
>  #include "dispatcher.h"
>  #include "red-channel.h"
>  
> diff --git a/server/red-channel.h b/server/red-channel.h
> index bb3a95e8b..25ade8579 100644
> --- a/server/red-channel.h
> +++ b/server/red-channel.h
> @@ -29,7 +29,6 @@
>  #include 
>  #include 
>  
> -#include "spice.h"
>  #include "red-common.h"
>  #include "red-stream.h"
>  #include "stat.h"
> diff --git a/server/red-parse-qxl.h b/server/red-parse-qxl.h
> index 61c71d6e4..d3cacc08f 100644
> --- a/server/red-parse-qxl.h
> +++ b/server/red-parse-qxl.h
> @@ -21,7 +21,6 @@
>  
>  #include 
>  
> -#include "red-common.h"
>  #include "memslot.h"
>  
>  typedef struct RedDrawable {
> diff --git a/server/red-record-qxl.h b/server/red-record-qxl.h
> index d19843279..b40922c86 100644
> --- a/server/red-record-qxl.h
> +++ b/server/red-record-qxl.h
> @@ -21,7 +21,6 @@
>  
>  #include 
>  
> -#include "red-common.h"
>  #include "memslot.h"
>  #include "utils.h"
>  

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-gtk v2] build-sys: Use always --buildtype=release

2019-02-21 Thread Jonathon Jongsma
On additional minor change that I would like: it would be nice if the
commit summary indicated that this is only for the gitlab CI
configuration. "build-sys: Use always --buildtype=release" makes it
sound like the change forces all developers to build in release mode.


Otherwise,
Acked-by: Jonathon Jongsma 


On Thu, 2019-02-21 at 15:59 +, Frediano Ziglio wrote:
> Allows the compiler to catch some errors which are only triggered
> when
> building with optimizations enabled.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  .gitlab-ci.yml | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
> index 8ffc6542..adf53e1c 100644
> --- a/.gitlab-ci.yml
> +++ b/.gitlab-ci.yml
> @@ -57,15 +57,15 @@ fedora-meson:
>before_script:
>  - dnf install -y $DEPS_COMMON $DEPS_FEDORA
>  - git clone ${CI_REPOSITORY_URL/spice-gtk/spice-protocol}
> -- meson spice-protocol build-spice-protocol --prefix=/usr
> +- meson --buildtype=release spice-protocol build-spice-protocol
> --prefix=/usr
>  - ninja -C build-spice-protocol install
>  
>script:
> -- meson build-default
> +- meson --buildtype=release build-default
>  - ninja -C build-default
>  - ninja -C build-default test
>  
> -- meson build-feat-disabled -Dauto_features=disabled
> +- meson --buildtype=release build-feat-disabled
> -Dauto_features=disabled
>  - ninja -C build-feat-disabled
>  - ninja -C build-feat-disabled test
>  
> @@ -92,11 +92,11 @@ windows-meson:
>  - dnf install -y $DEPS_COMMON $DEPS_MINGW
>  - git clone ${CI_REPOSITORY_URL/spice-gtk/spice-protocol}
>  - mkdir spice-protocol/build-spice-protocol && cd spice-
> protocol/build-spice-protocol
> -- mingw64-meson --prefix=/usr
> +- mingw64-meson --buildtype=release --prefix=/usr
>  - ninja install
>  
>script:
>  - cd $CI_PROJECT_DIR
>  - mkdir build-win64 && cd build-win64
> -- mingw64-meson -Dgtk_doc=disabled
> +- mingw64-meson --buildtype=release -Dgtk_doc=disabled
>  - ninja install

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-gtk] build-sys: Use always --buildtype=release

2019-02-21 Thread Jonathon Jongsma
On Wed, 2019-02-20 at 15:50 -0500, Frediano Ziglio wrote:
> > 
> > On Thu, 2019-02-14 at 12:56 +, Frediano Ziglio wrote:
> > > Allows to catch some errors which the compiler is not able to
> > > detect in debug mode (the default).
> > 
> > Seems fine, but what kind of errors are you talking about?
> > Reviewed-by: Jonathon Jongsma 
> > 
> 
> Like "this variable is not used" or "this variable is not
> initialized"
> for instance.
> Not sure if people prefers "release" or "debugoptimized" but without
> optimizations compilers cannot detect some potential issues.

Since this is just for the CI stuff, I don't really have a problem with
using the release buildtype. I'm not sure that debugoptimized provides
much advantage in this situation. But it'd be nice if the commit log
said something about optimization. e.g.

"Allows the compiler to catch some errors which are only triggered when
building with optimizations enabled"?

Jonathon


> 
> Frediano
> 
> > 
> > > 
> > > Signed-off-by: Frediano Ziglio 
> > > ---
> > >  .gitlab-ci.yml | 10 +-
> > >  1 file changed, 5 insertions(+), 5 deletions(-)
> > > 
> > > https://gitlab.freedesktop.org/fziglio/spice-gtk/pipelines/19157
> > > (only Meson builds)
> > > 
> > > diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
> > > index 8ffc6542..adf53e1c 100644
> > > --- a/.gitlab-ci.yml
> > > +++ b/.gitlab-ci.yml
> > > @@ -57,15 +57,15 @@ fedora-meson:
> > >before_script:
> > >  - dnf install -y $DEPS_COMMON $DEPS_FEDORA
> > >  - git clone ${CI_REPOSITORY_URL/spice-gtk/spice-protocol}
> > > -- meson spice-protocol build-spice-protocol --prefix=/usr
> > > +- meson --buildtype=release spice-protocol build-spice-
> > > protocol
> > > --prefix=/usr
> > >  - ninja -C build-spice-protocol install
> > >  
> > >script:
> > > -- meson build-default
> > > +- meson --buildtype=release build-default
> > >  - ninja -C build-default
> > >  - ninja -C build-default test
> > >  
> > > -- meson build-feat-disabled -Dauto_features=disabled
> > > +- meson --buildtype=release build-feat-disabled
> > > -Dauto_features=disabled
> > >  - ninja -C build-feat-disabled
> > >  - ninja -C build-feat-disabled test
> > >  
> > > @@ -92,11 +92,11 @@ windows-meson:
> > >  - dnf install -y $DEPS_COMMON $DEPS_MINGW
> > >  - git clone ${CI_REPOSITORY_URL/spice-gtk/spice-protocol}
> > >  - mkdir spice-protocol/build-spice-protocol && cd spice-
> > > protocol/build-spice-protocol
> > > -- mingw64-meson --prefix=/usr
> > > +- mingw64-meson --buildtype=release --prefix=/usr
> > >  - ninja install
> > >  
> > >script:
> > >  - cd $CI_PROJECT_DIR
> > >  - mkdir build-win64 && cd build-win64
> > > -- mingw64-meson -Dgtk_doc=disabled
> > > +- mingw64-meson --buildtype=release -Dgtk_doc=disabled
> > >  - ninja install
> > 
> > 

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server] Move channel registration to constructed vfunc

2019-02-20 Thread Jonathon Jongsma
On Wed, 2019-02-20 at 07:08 -0500, Frediano Ziglio wrote:
> > 
> > For the Display Channel and the Cursor channel, move the call to
> > reds_register_channel() to the _constructed() vfunc rather than
> > calling
> > it explicitly from RedWorker. This matches what other channels do.
> 
> I think this was different for these channels as they where created
> in a different thread.
> Is there a channel not registered to "reds"? I think not.

It turns out, there is. MainChannel is special and is not registered
with 'reds' like the other channels are. In fact, when channels are
registered, we advertise the new channel on the main channel, so it is
assumed that the main channel already exists before the first call to
reds_register_channel().


> Would make it sense to move the registration to RedChannel?

Since we can't register the main channel without changing some
assumptions (the main channel obviously cannot announce itself as a new
channel), I'm not sure it makes sense to move this registration down to
RedChannel.


> However I would implement it with a Initiable interface, registering
> a channel while constructing it does not seem a good idea.

After looking at it, I'm not sure that I agree with implementing the
Initable interface either. GInitable allows you to implement an object
for which simple allocation is not sufficient to use the object. In
other words, the object may be invalid after allocation if there is a
failure during an initialization step. But reds_register_channel()
cannot fail -- it has a 'void' return value. So it seems that making it
Initable just complicates the type heirarchy for no real benefit.


> 
> Also would be good to update docs/spice_threading_model.txt
> documenting
> that creating/shutdown should be handled in the main thread.
> 
> > ---
> >  server/cursor-channel.c  | 12 
> >  server/display-channel.c |  2 ++
> >  server/red-worker.c  |  2 --
> >  3 files changed, 14 insertions(+), 2 deletions(-)
> > 
> > diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> > index 9dd69fa25..4220084f5 100644
> > --- a/server/cursor-channel.c
> > +++ b/server/cursor-channel.c
> > @@ -366,12 +366,24 @@ cursor_channel_finalize(GObject *object)
> >  G_OBJECT_CLASS(cursor_channel_parent_class)->finalize(object);
> >  }
> >  
> > +static void
> > +cursor_channel_constructed(GObject *object)
> > +{
> > +RedChannel *red_channel = RED_CHANNEL(object);
> > +RedsState *reds = red_channel_get_server(red_channel);
> > +
> > +G_OBJECT_CLASS(cursor_channel_parent_class)-
> > >constructed(object);
> > +
> > +reds_register_channel(reds, red_channel);
> > +}
> > +
> >  static void
> >  cursor_channel_class_init(CursorChannelClass *klass)
> >  {
> >  GObjectClass *object_class = G_OBJECT_CLASS(klass);
> >  RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
> >  
> > +object_class->constructed = cursor_channel_constructed;
> >  object_class->finalize = cursor_channel_finalize;
> >  
> >  channel_class->parser =
> >  spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
> > diff --git a/server/display-channel.c b/server/display-channel.c
> > index e68ed10f8..6684135eb 100644
> > --- a/server/display-channel.c
> > +++ b/server/display-channel.c
> > @@ -2304,6 +2304,8 @@ display_channel_constructed(GObject *object)
> >  red_channel_set_cap(channel,
> > SPICE_DISPLAY_CAP_PREF_COMPRESSION);
> >  red_channel_set_cap(channel,
> > SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE);
> >  red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
> > +
> > +reds_register_channel(reds, channel);
> >  }
> >  
> >  void display_channel_process_surface_cmd(DisplayChannel *display,
> > diff --git a/server/red-worker.c b/server/red-worker.c
> > index c74ae8886..3cb12b9c2 100644
> > --- a/server/red-worker.c
> > +++ b/server/red-worker.c
> > @@ -1322,7 +1322,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
> >  red_channel_init_stat_node(channel, >stat,
> > "cursor_channel");
> >  red_channel_register_client_cbs(channel, client_cursor_cbs);
> >  g_object_set_data(G_OBJECT(channel), "dispatcher",
> > dispatcher);
> > -reds_register_channel(reds, channel);
> >  
> >  // TODO: handle seamless migration. Temp, setting migrate to
> > FALSE
> >  worker->display_channel = display_channel_new(reds, qxl,
> > >core,
> >  FALSE,
> > @@ -1333,7 +1332,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
> >  red_channel_init_stat_node(channel, >stat,
> > "display_channel");
> >  red_channel_register_client_cbs(channel, client_display_cbs);
> >  g_object_set_data(G_OBJECT(channel), "dispatcher",
> > dispatcher);
> > -reds_register_channel(reds, channel);
> >  
> >  return worker;
> >  }
> 
> Otherwise patch seems good, but I didn't test it.
> In particular I think CursorChannel is also registered in the
> StreamDevice so will be registered twice.
> There should be a test for double registration.
> 

Re: [Spice-devel] [PATCH spice-gtk] build-sys: Use always --buildtype=release

2019-02-20 Thread Jonathon Jongsma
On Thu, 2019-02-14 at 12:56 +, Frediano Ziglio wrote:
> Allows to catch some errors which the compiler is not able to
> detect in debug mode (the default).

Seems fine, but what kind of errors are you talking about?
Reviewed-by: Jonathon Jongsma 


> 
> Signed-off-by: Frediano Ziglio 
> ---
>  .gitlab-ci.yml | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> https://gitlab.freedesktop.org/fziglio/spice-gtk/pipelines/19157
> (only Meson builds)
> 
> diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
> index 8ffc6542..adf53e1c 100644
> --- a/.gitlab-ci.yml
> +++ b/.gitlab-ci.yml
> @@ -57,15 +57,15 @@ fedora-meson:
>before_script:
>  - dnf install -y $DEPS_COMMON $DEPS_FEDORA
>  - git clone ${CI_REPOSITORY_URL/spice-gtk/spice-protocol}
> -- meson spice-protocol build-spice-protocol --prefix=/usr
> +- meson --buildtype=release spice-protocol build-spice-protocol
> --prefix=/usr
>  - ninja -C build-spice-protocol install
>  
>script:
> -- meson build-default
> +- meson --buildtype=release build-default
>  - ninja -C build-default
>  - ninja -C build-default test
>  
> -- meson build-feat-disabled -Dauto_features=disabled
> +- meson --buildtype=release build-feat-disabled
> -Dauto_features=disabled
>  - ninja -C build-feat-disabled
>  - ninja -C build-feat-disabled test
>  
> @@ -92,11 +92,11 @@ windows-meson:
>  - dnf install -y $DEPS_COMMON $DEPS_MINGW
>  - git clone ${CI_REPOSITORY_URL/spice-gtk/spice-protocol}
>  - mkdir spice-protocol/build-spice-protocol && cd spice-
> protocol/build-spice-protocol
> -- mingw64-meson --prefix=/usr
> +- mingw64-meson --buildtype=release --prefix=/usr
>  - ninja install
>  
>script:
>  - cd $CI_PROJECT_DIR
>  - mkdir build-win64 && cd build-win64
> -- mingw64-meson -Dgtk_doc=disabled
> +- mingw64-meson --buildtype=release -Dgtk_doc=disabled
>  - ninja install

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server] Move channel registration to constructed vfunc

2019-02-20 Thread Jonathon Jongsma
On Wed, 2019-02-20 at 07:08 -0500, Frediano Ziglio wrote:
> > 
> > For the Display Channel and the Cursor channel, move the call to
> > reds_register_channel() to the _constructed() vfunc rather than
> > calling
> > it explicitly from RedWorker. This matches what other channels do.
> 
> I think this was different for these channels as they where created
> in a different thread.
> Is there a channel not registered to "reds"? I think not.
> Would make it sense to move the registration to RedChannel?
> However I would implement it with a Initiable interface, registering
> a channel while constructing it does not seem a good idea.

Good points, I'll try to rework it. 

> 
> Also would be good to update docs/spice_threading_model.txt
> documenting
> that creating/shutdown should be handled in the main thread.
> 
> > ---
> >  server/cursor-channel.c  | 12 
> >  server/display-channel.c |  2 ++
> >  server/red-worker.c  |  2 --
> >  3 files changed, 14 insertions(+), 2 deletions(-)
> > 
> > diff --git a/server/cursor-channel.c b/server/cursor-channel.c
> > index 9dd69fa25..4220084f5 100644
> > --- a/server/cursor-channel.c
> > +++ b/server/cursor-channel.c
> > @@ -366,12 +366,24 @@ cursor_channel_finalize(GObject *object)
> >  G_OBJECT_CLASS(cursor_channel_parent_class)->finalize(object);
> >  }
> >  
> > +static void
> > +cursor_channel_constructed(GObject *object)
> > +{
> > +RedChannel *red_channel = RED_CHANNEL(object);
> > +RedsState *reds = red_channel_get_server(red_channel);
> > +
> > +G_OBJECT_CLASS(cursor_channel_parent_class)-
> > >constructed(object);
> > +
> > +reds_register_channel(reds, red_channel);
> > +}
> > +
> >  static void
> >  cursor_channel_class_init(CursorChannelClass *klass)
> >  {
> >  GObjectClass *object_class = G_OBJECT_CLASS(klass);
> >  RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
> >  
> > +object_class->constructed = cursor_channel_constructed;
> >  object_class->finalize = cursor_channel_finalize;
> >  
> >  channel_class->parser =
> >  spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
> > diff --git a/server/display-channel.c b/server/display-channel.c
> > index e68ed10f8..6684135eb 100644
> > --- a/server/display-channel.c
> > +++ b/server/display-channel.c
> > @@ -2304,6 +2304,8 @@ display_channel_constructed(GObject *object)
> >  red_channel_set_cap(channel,
> > SPICE_DISPLAY_CAP_PREF_COMPRESSION);
> >  red_channel_set_cap(channel,
> > SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE);
> >  red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
> > +
> > +reds_register_channel(reds, channel);
> >  }
> >  
> >  void display_channel_process_surface_cmd(DisplayChannel *display,
> > diff --git a/server/red-worker.c b/server/red-worker.c
> > index c74ae8886..3cb12b9c2 100644
> > --- a/server/red-worker.c
> > +++ b/server/red-worker.c
> > @@ -1322,7 +1322,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
> >  red_channel_init_stat_node(channel, >stat,
> > "cursor_channel");
> >  red_channel_register_client_cbs(channel, client_cursor_cbs);
> >  g_object_set_data(G_OBJECT(channel), "dispatcher",
> > dispatcher);
> > -reds_register_channel(reds, channel);
> >  
> >  // TODO: handle seamless migration. Temp, setting migrate to
> > FALSE
> >  worker->display_channel = display_channel_new(reds, qxl,
> > >core,
> >  FALSE,
> > @@ -1333,7 +1332,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
> >  red_channel_init_stat_node(channel, >stat,
> > "display_channel");
> >  red_channel_register_client_cbs(channel, client_display_cbs);
> >  g_object_set_data(G_OBJECT(channel), "dispatcher",
> > dispatcher);
> > -reds_register_channel(reds, channel);
> >  
> >  return worker;
> >  }
> 
> Otherwise patch seems good, but I didn't test it.
> In particular I think CursorChannel is also registered in the
> StreamDevice so will be registered twice.
> There should be a test for double registration.

hmm, I'll check into it.

Thanks,
Jonathon

> 
> Frediano

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server] Move channel registration to constructed vfunc

2019-02-19 Thread Jonathon Jongsma
For the Display Channel and the Cursor channel, move the call to
reds_register_channel() to the _constructed() vfunc rather than calling
it explicitly from RedWorker. This matches what other channels do.
---
 server/cursor-channel.c  | 12 
 server/display-channel.c |  2 ++
 server/red-worker.c  |  2 --
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/server/cursor-channel.c b/server/cursor-channel.c
index 9dd69fa25..4220084f5 100644
--- a/server/cursor-channel.c
+++ b/server/cursor-channel.c
@@ -366,12 +366,24 @@ cursor_channel_finalize(GObject *object)
 G_OBJECT_CLASS(cursor_channel_parent_class)->finalize(object);
 }
 
+static void
+cursor_channel_constructed(GObject *object)
+{
+RedChannel *red_channel = RED_CHANNEL(object);
+RedsState *reds = red_channel_get_server(red_channel);
+
+G_OBJECT_CLASS(cursor_channel_parent_class)->constructed(object);
+
+reds_register_channel(reds, red_channel);
+}
+
 static void
 cursor_channel_class_init(CursorChannelClass *klass)
 {
 GObjectClass *object_class = G_OBJECT_CLASS(klass);
 RedChannelClass *channel_class = RED_CHANNEL_CLASS(klass);
 
+object_class->constructed = cursor_channel_constructed;
 object_class->finalize = cursor_channel_finalize;
 
 channel_class->parser = 
spice_get_client_channel_parser(SPICE_CHANNEL_CURSOR, NULL);
diff --git a/server/display-channel.c b/server/display-channel.c
index e68ed10f8..6684135eb 100644
--- a/server/display-channel.c
+++ b/server/display-channel.c
@@ -2304,6 +2304,8 @@ display_channel_constructed(GObject *object)
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_COMPRESSION);
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_PREF_VIDEO_CODEC_TYPE);
 red_channel_set_cap(channel, SPICE_DISPLAY_CAP_STREAM_REPORT);
+
+reds_register_channel(reds, channel);
 }
 
 void display_channel_process_surface_cmd(DisplayChannel *display,
diff --git a/server/red-worker.c b/server/red-worker.c
index c74ae8886..3cb12b9c2 100644
--- a/server/red-worker.c
+++ b/server/red-worker.c
@@ -1322,7 +1322,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
 red_channel_init_stat_node(channel, >stat, "cursor_channel");
 red_channel_register_client_cbs(channel, client_cursor_cbs);
 g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher);
-reds_register_channel(reds, channel);
 
 // TODO: handle seamless migration. Temp, setting migrate to FALSE
 worker->display_channel = display_channel_new(reds, qxl, >core, 
FALSE,
@@ -1333,7 +1332,6 @@ RedWorker* red_worker_new(QXLInstance *qxl,
 red_channel_init_stat_node(channel, >stat, "display_channel");
 red_channel_register_client_cbs(channel, client_display_cbs);
 g_object_set_data(G_OBJECT(channel), "dispatcher", dispatcher);
-reds_register_channel(reds, channel);
 
 return worker;
 }
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 2/2] QXL devices must be registered before Stream Devices

2019-02-13 Thread Jonathon Jongsma
On Wed, 2019-02-13 at 09:19 -0500, Frediano Ziglio wrote:
> > 
> > Stream devices assume that all QXL devices are registered with the
> > server before we receive any communications from the stream device.
> > This
> > is due to the fact that QXL display channel IDs are assigned
> > directly
> > from the QXL device ID, whereas Stream display channels are
> > assigned
> > channel IDs based on the next free ID. If the stream channel is
> > created first, it will find that 0 is the first available display
> > ID and
> > use that for its channel ID. Then when QXL device #0 is registered,
> > it
> > will also create a display channel with channel ID 0, and they will
> > conflict.
> 
> Interesting, should not be checked somewhere and detected as API
> violation?
> 
> Frediano


Maybe. Right now qemu always registers QXL devices immediately after
qemu starts. And obviously we can't communicate via the stream device
until the guest is fully up and running. So I think there's essentially
no way for the bug to happen with current code. I think QXL channels
will always get created before stream channels. But for completeness it
probably would be good to add a check somewhere. 

The alternative is to disconnect the QXL ID from the channel ID. In
other words, QXL display channels would use the next available channel
ID (just like the stream channels do) instead of using the qxl->id as
the channel_id. But I don't know if such a change would violate any
other assumptions in the code.

Jonathon

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server v2 3/3] Remove core parameter from main_dispatcher_new

2019-02-12 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-02-12 at 21:24 +, Frediano Ziglio wrote:
> This was added in bd8771adbcf3ff34d14333cf874191e8d105f612.
> There's no reason to not use reds function instead.
> MainDispatcher needs to listen in the main thread that is the
> one provided by reds_core_* functions.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/main-dispatcher.c | 29 ++---
>  server/main-dispatcher.h |  2 +-
>  server/reds.c|  2 +-
>  3 files changed, 8 insertions(+), 25 deletions(-)
> 
> diff --git a/server/main-dispatcher.c b/server/main-dispatcher.c
> index 99d2a6216..82b25e6e4 100644
> --- a/server/main-dispatcher.c
> +++ b/server/main-dispatcher.c
> @@ -48,7 +48,6 @@
>   */
>  struct MainDispatcherPrivate
>  {
> -SpiceCoreInterfaceInternal *core; /* weak */
>  RedsState *reds; /* weak */
>  SpiceWatch *watch;
>  };
> @@ -58,7 +57,6 @@ G_DEFINE_TYPE_WITH_PRIVATE(MainDispatcher,
> main_dispatcher, TYPE_DISPATCHER)
>  enum {
>  PROP0,
>  PROP_SPICE_SERVER,
> -PROP_CORE_INTERFACE
>  };
>  
>  static void
> @@ -73,9 +71,6 @@ main_dispatcher_get_property(GObject*object,
>  case PROP_SPICE_SERVER:
>   g_value_set_pointer(value, self->priv->reds);
>  break;
> -case PROP_CORE_INTERFACE:
> - g_value_set_pointer(value, self->priv->core);
> -break;
>  default:
>  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id,
> pspec);
>  }
> @@ -93,9 +88,6 @@ main_dispatcher_set_property(GObject  *object,
>  case PROP_SPICE_SERVER:
>  self->priv->reds = g_value_get_pointer(value);
>  break;
> -case PROP_CORE_INTERFACE:
> -self->priv->core = g_value_get_pointer(value);
> -break;
>  default:
>  G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id,
> pspec);
>  }
> @@ -121,14 +113,6 @@ main_dispatcher_class_init(MainDispatcherClass
> *klass)
>   "The spice
> server associated with this dispatcher",
>   G_PARAM_REA
> DWRITE |
>   G_PARAM_CON
> STRUCT_ONLY));
> -
> -g_object_class_install_property(object_class,
> -PROP_CORE_INTERFACE,
> -g_param_spec_pointer("core-
> interface",
> - "core-
> interface",
> - "The
> SpiceCoreInterface server associated with this dispatcher",
> - G_PARAM_REA
> DWRITE |
> - G_PARAM_CON
> STRUCT_ONLY));
>  }
>  
>  static void
> @@ -284,11 +268,10 @@ static void dispatcher_handle_read(int fd, int
> event, void *opaque)
>   * Reds routines shouldn't be exposed. Instead reds.c should
> register the callbacks,
>   * and the corresponding operations should be made only via
> main_dispatcher.
>   */
> -MainDispatcher* main_dispatcher_new(RedsState *reds,
> SpiceCoreInterfaceInternal *core)
> +MainDispatcher* main_dispatcher_new(RedsState *reds)
>  {
>  MainDispatcher *self = g_object_new(TYPE_MAIN_DISPATCHER,
>  "spice-server", reds,
> -"core-interface", core,
>  "max-message-type",
> MAIN_DISPATCHER_NUM_MESSAGES,
>  NULL);
>  return self;
> @@ -302,10 +285,10 @@ void main_dispatcher_constructed(GObject
> *object)
>  dispatcher_set_opaque(DISPATCHER(self), self);
>  
>  self->priv->watch =
> -self->priv->core->watch_add(self->priv->core,
> -dispatcher_get_recv_fd(DISPATCHE
> R(self)),
> -SPICE_WATCH_EVENT_READ,
> dispatcher_handle_read,
> -DISPATCHER(self));
> +reds_core_watch_add(self->priv->reds,
> +dispatcher_get_recv_fd(DISPATCHER(self))
> ,
> +SPICE_WATCH_EVENT_READ,
> dispatcher_handle_read,
> +DISPATCHER(self));
>  dispatcher_register_handler(DISPATCHER(self),
> MAIN_DISPATCHER_CHANNEL_EVENT,
>  m

Re: [Spice-devel] [PATCH spice-server v2 2/3] test-stream-device: Check monitor ID messages

2019-02-12 Thread Jonathon Jongsma
Looks fine to me. 

Insofar as I can ACK a patch that's partially my own code:

Acked-by: Jonathon Jongsma 

:)


On Tue, 2019-02-12 at 21:24 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> Signed-off-by: Jonathon Jongsma 
> Reviewed-by: Jonathon Jongsma 
> ---
>  server/tests/test-stream-device.c | 70
> +++
>  1 file changed, 70 insertions(+)
> 
> diff --git a/server/tests/test-stream-device.c b/server/tests/test-
> stream-device.c
> index f1707d2f8..e63952acb 100644
> --- a/server/tests/test-stream-device.c
> +++ b/server/tests/test-stream-device.c
> @@ -491,6 +491,75 @@ static void
> test_stream_device_data_message(TestFixture *fixture, gconstpointer
>  g_assert_cmpint(send_data_bytes, ==, 1017);
>  }
>  
> +static void test_display_info(TestFixture *fixture, gconstpointer
> user_data)
> +{
> +// initialize a QXL interface. This must be done before
> receiving the display info message from
> +// the stream
> +test_add_display_interface(test);
> +// qxl device supports 2 monitors
> +spice_qxl_set_device_info(>qxl_instance, "pci/0/1.2", 0,
> 2);
> +
> +// craft a message from the mock stream device that provides
> display info to the server for the
> +// given stream
> +static const char address[] = "pci/a/b.cde";
> +StreamMsgDeviceDisplayInfo info = {
> +.stream_id = GUINT32_TO_LE(0x01020304),
> +.device_display_id = GUINT32_TO_LE(0x0a0b0c0d),
> +.device_address_len = GUINT32_TO_LE(sizeof(address)),
> +};
> +uint8_t *p = message;
> +p = add_stream_hdr(p, STREAM_TYPE_DEVICE_DISPLAY_INFO,
> sizeof(info) + sizeof(address));
> +memcpy(p, , sizeof(info));
> +p += sizeof(info);
> +strcpy((char*)p, address);
> +p += sizeof(address);
> +
> +*message_sizes_end = p - message;
> +++message_sizes_end;
> +
> +// parse the simulated display info message from the stream
> device so the server now has display
> +// info for the mock stream device
> +test_kick();
> +
> +// build the buffer to send to the agent for display information
> +SpiceMarshaller *m = spice_marshaller_new();
> +reds_marshall_device_display_info(test->server, m);
> +int to_free;
> +size_t buf_len;
> +uint8_t *buf = spice_marshaller_linearize(m, 0, _len,
> _free);
> +
> +// check output buffer. The message that we send to the vdagent
> should combine display info for
> +// the stream device that we crafted above and the qxl device.
> +static const uint8_t expected_buffer[] = {
> +/* device count */3,  0,  0,  0,
> +
> +/* channel_id */  0,  0,  0,  0,
> +/* monitor_id */  0,  0,  0,  0,
> +/* device_display_id */   0,  0,  0,  0,
> +/* device_address_len */ 10,  0,  0,  0,
> +/* device_address
> */'p','c','i','/','0','/','1','.','2',  0,
> +
> +/* channel_id */  0,  0,  0,  0,
> +/* monitor_id */  1,  0,  0,  0,
> +/* device_display_id */   1,  0,  0,  0,
> +/* device_address_len */ 10,  0,  0,  0,
> +/* device_address */'p','c',
> 'i','/','0','/','1','.','2',  0,
> +
> +/* channel_id */  1,  0,  0,  0,
> +/* monitor_id */  4,  3,  2,  1,
> +/* device_display_id */  13, 12, 11, 10,
> +/* device_address_len */ 12,  0,  0,  0,
> +/* device_address
> */'p','c','i','/','a','/','b','.','c','d','e',  0
> +};
> +g_assert_cmpint(buf_len, ==, sizeof(expected_buffer));
> +g_assert_true(memcmp(buf, expected_buffer, buf_len) == 0);
> +
> +if (to_free) {
> +free(buf);
> +}
> +spice_marshaller_destroy(m);
> +}
> +
>  static void test_add(const char *name, void (*func)(TestFixture *,
> gconstpointer), gconstpointer arg)
>  {
>  g_test_add(name, TestFixture, arg, test_stream_device_setup,
> func, test_stream_device_teardown);
> @@ -516,6 +585,7 @@ int main(int argc, char *argv[])
>   test_stream_device_huge_data, NULL);
>  test_add("/server/stream-device-data-message",
>   test_stream_device_data_message, NULL);
> +test_add("/server/display-info", test_display_info, NULL);
>  
>  return g_test_run();
>  }

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 6/8] agent-msg-filter: Simplify code

2019-02-12 Thread Jonathon Jongsma
why not

Acked-by: Jonathon Jongsma 


On Mon, 2019-02-11 at 11:54 +, Frediano Ziglio wrote:
> Most of the time result is set to AGENT_MSG_FILTER_OK, set at
> the beginning and change if necessary.
> 
> Signed-off-by: Frediano Ziglio 
> ---
>  server/agent-msg-filter.c | 14 +-
>  1 file changed, 5 insertions(+), 9 deletions(-)
> 
> diff --git a/server/agent-msg-filter.c b/server/agent-msg-filter.c
> index 458f563b7..abead87a5 100644
> --- a/server/agent-msg-filter.c
> +++ b/server/agent-msg-filter.c
> @@ -82,35 +82,31 @@ data_to_read:
>  if (filter->discard_all) {
>  filter->result = AGENT_MSG_FILTER_DISCARD;
>  } else {
> +// default, easier to set once
> +filter->result = AGENT_MSG_FILTER_OK;
>  switch (msg_header.type) {
>  case VD_AGENT_CLIPBOARD:
>  case VD_AGENT_CLIPBOARD_GRAB:
>  case VD_AGENT_CLIPBOARD_REQUEST:
>  case VD_AGENT_CLIPBOARD_RELEASE:
> -if (filter->copy_paste_enabled) {
> -filter->result = AGENT_MSG_FILTER_OK;
> -} else {
> +if (!filter->copy_paste_enabled) {
>  filter->result = AGENT_MSG_FILTER_DISCARD;
>  }
>  break;
>  case VD_AGENT_FILE_XFER_START:
>  case VD_AGENT_FILE_XFER_STATUS:
>  case VD_AGENT_FILE_XFER_DATA:
> -if (filter->file_xfer_enabled) {
> -filter->result = AGENT_MSG_FILTER_OK;
> -} else {
> +if (!filter->file_xfer_enabled) {
>  filter->result = AGENT_MSG_FILTER_DISCARD;
>  }
>  break;
>  case VD_AGENT_MONITORS_CONFIG:
>  if (filter->use_client_monitors_config) {
>  filter->result = AGENT_MSG_FILTER_MONITORS_CONFIG;
> -} else {
> -filter->result = AGENT_MSG_FILTER_OK;
>  }
>  break;
>  default:
> -filter->result = AGENT_MSG_FILTER_OK;
> +break;
>  }
>  }
>  

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 3/8] test-stream-device: Check monitor ID messages

2019-02-12 Thread Jonathon Jongsma
Looks mostly good, but I found an issue and had a couple suggested
improvments. So I sent a couple follow-up patches that you can squash
with this patch if you think they're valid.

Reviewed-by: Jonathon Jongsma 

On Mon, 2019-02-11 at 11:54 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/tests/test-stream-device.c | 52
> +++
>  1 file changed, 52 insertions(+)
> 
> diff --git a/server/tests/test-stream-device.c b/server/tests/test-
> stream-device.c
> index f1707d2f8..cb3a1a4ff 100644
> --- a/server/tests/test-stream-device.c
> +++ b/server/tests/test-stream-device.c
> @@ -491,6 +491,57 @@ static void
> test_stream_device_data_message(TestFixture *fixture, gconstpointer
>  g_assert_cmpint(send_data_bytes, ==, 1017);
>  }
>  
> +static void test_display_info(TestFixture *fixture, gconstpointer
> user_data)
> +{
> +// build a message for the streaming device
> +static const char address[] = "pci/a/b.cde";
> +StreamMsgDeviceDisplayInfo info = {
> +.stream_id = GUINT32_TO_LE(0x01020304),
> +.device_display_id = GUINT32_TO_LE(0x0a0b0c0d),
> +.device_address_len = GUINT32_TO_LE(sizeof(address)),
> +};
> +uint8_t *p = message;
> +p = add_stream_hdr(p, STREAM_TYPE_DEVICE_DISPLAY_INFO,
> sizeof(info) + sizeof(address));
> +memcpy(p, , sizeof(info));
> +p += sizeof(info);
> +strcpy((char*)p, address);
> +p += sizeof(address);
> +
> +*message_sizes_end = p - message;
> +++message_sizes_end;
> +
> +// parse the message we crafted
> +test_kick();
> +
> +// initialize a QXL interface
> +test_add_display_interface(test);
> +spice_qxl_set_device_info(>qxl_instance, "pci/0/1.2", 0,
> 2);
> +
> +// build the buffer to send to the agent for display information
> +SpiceMarshaller *m = spice_marshaller_new();
> +reds_marshall_device_display_info(test->server, m);
> +int to_free;
> +size_t buf_len;
> +uint8_t *buf = spice_marshaller_linearize(m, 0, _len,
> _free);
> +
> +// check output buffer
> +static const uint8_t expected_buffer[] = {
> +  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
>   0,
> + 10,  0,  0,  0,112, 99,105, 47, 48, 47, 49, 46,
> 50,  0,  0,  0,
> +  0,  0,  1,  0,  0,  0,  1,  0,  0,  0, 10,  0,  0,  0,112,
> 99,
> +105, 47, 48, 47, 49, 46,
> 50,  0,  0,  0,  0,  0,  4,  3,  2,  1,
> + 13, 12, 11, 10, 12,  0,  0,  0,112, 99,105, 47, 97, 47, 98,
> 46,
> + 99,100,101,  0
> +};
> +g_assert_cmpint(buf_len, ==, sizeof(expected_buffer));
> +g_assert_true(memcmp(buf, expected_buffer, buf_len) == 0);
> +
> +if (to_free) {
> +free(buf);
> +}
> +spice_marshaller_destroy(m);
> +}
> +
>  static void test_add(const char *name, void (*func)(TestFixture *,
> gconstpointer), gconstpointer arg)
>  {
>  g_test_add(name, TestFixture, arg, test_stream_device_setup,
> func, test_stream_device_teardown);
> @@ -516,6 +567,7 @@ int main(int argc, char *argv[])
>   test_stream_device_huge_data, NULL);
>  test_add("/server/stream-device-data-message",
>   test_stream_device_data_message, NULL);
> +test_add("/server/display-info", test_display_info, NULL);
>  
>  return g_test_run();
>  }

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server 1/2] Fixup display info test

2019-02-12 Thread Jonathon Jongsma
Rather than showing the expected data in raw format (ascii codes, etc),
which is hard to verify, show the characters themselves, and group them
by structure.

Also add a few more comments.
---
 server/tests/test-stream-device.c | 35 +++
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/server/tests/test-stream-device.c 
b/server/tests/test-stream-device.c
index cb3a1a4ff..dcdd91896 100644
--- a/server/tests/test-stream-device.c
+++ b/server/tests/test-stream-device.c
@@ -493,7 +493,8 @@ static void test_stream_device_data_message(TestFixture 
*fixture, gconstpointer
 
 static void test_display_info(TestFixture *fixture, gconstpointer user_data)
 {
-// build a message for the streaming device
+// craft a message from the mock stream device that provides display info 
to the server for the
+// given stream
 static const char address[] = "pci/a/b.cde";
 StreamMsgDeviceDisplayInfo info = {
 .stream_id = GUINT32_TO_LE(0x01020304),
@@ -510,11 +511,13 @@ static void test_display_info(TestFixture *fixture, 
gconstpointer user_data)
 *message_sizes_end = p - message;
 ++message_sizes_end;
 
-// parse the message we crafted
+// parse the simulated display info message from the stream device so the 
server now has display
+// info for the mock stream device
 test_kick();
 
 // initialize a QXL interface
 test_add_display_interface(test);
+/* qxl device supports 2 monitors */
 spice_qxl_set_device_info(>qxl_instance, "pci/0/1.2", 0, 2);
 
 // build the buffer to send to the agent for display information
@@ -524,14 +527,28 @@ static void test_display_info(TestFixture *fixture, 
gconstpointer user_data)
 size_t buf_len;
 uint8_t *buf = spice_marshaller_linearize(m, 0, _len, _free);
 
-// check output buffer
+// check output buffer. The message that we send to the vdagent should 
combine display info for
+// the stream device that we crafted above and the qxl device.
 static const uint8_t expected_buffer[] = {
-  3,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
- 10,  0,  0,  0,112, 99,105, 47, 48, 47, 49, 46, 50,  0,  0,  0,
-  0,  0,  1,  0,  0,  0,  1,  0,  0,  0, 10,  0,  0,  0,112, 99,
-105, 47, 48, 47, 49, 46, 50,  0,  0,  0,  0,  0,  4,  3,  2,  1,
- 13, 12, 11, 10, 12,  0,  0,  0,112, 99,105, 47, 97, 47, 98, 46,
- 99,100,101,  0
+  /* device count */3,  0,  0,  0,
+
+  /* channel_id */  0,  0,  0,  0,
+  /* monitor_id */  0,  0,  0,  0,
+  /* device_display_id */   0,  0,  0,  0,
+  /* device_address_len */ 10,  0,  0,  0,
+  /* device_address */'p','c','i','/','0','/','1','.','2',  0,
+
+  /* channel_id */  0,  0,  0,  0,
+  /* monitor_id */  1,  0,  0,  0,
+  /* device_display_id */   1,  0,  0,  0,
+  /* device_address_len */ 10,  0,  0,  0,
+  /* device_address */'p','c', 'i','/','0','/','1','.','2',  0,
+
+  /* channel_id */  0,  0,  0,  0,
+  /* monitor_id */  4,  3,  2,  1,
+  /* device_display_id */  13, 12, 11, 10,
+  /* device_address_len */ 12,  0,  0,  0,
+  /* device_address */'p','c','i','/','a','/','b','.','c','d','e', 
 0
 };
 g_assert_cmpint(buf_len, ==, sizeof(expected_buffer));
 g_assert_true(memcmp(buf, expected_buffer, buf_len) == 0);
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

[Spice-devel] [PATCH spice-server 2/2] QXL devices must be registered before Stream Devices

2019-02-12 Thread Jonathon Jongsma
Stream devices assume that all QXL devices are registered with the
server before we receive any communications from the stream device. This
is due to the fact that QXL display channel IDs are assigned directly
from the QXL device ID, whereas Stream display channels are assigned
channel IDs based on the next free ID. If the stream channel is
created first, it will find that 0 is the first available display ID and
use that for its channel ID. Then when QXL device #0 is registered, it
will also create a display channel with channel ID 0, and they will
conflict.
---
 server/tests/test-stream-device.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/server/tests/test-stream-device.c 
b/server/tests/test-stream-device.c
index dcdd91896..86c33a145 100644
--- a/server/tests/test-stream-device.c
+++ b/server/tests/test-stream-device.c
@@ -493,6 +493,12 @@ static void test_stream_device_data_message(TestFixture 
*fixture, gconstpointer
 
 static void test_display_info(TestFixture *fixture, gconstpointer user_data)
 {
+// initialize a QXL interface. This must be done before recieving the 
display info message from
+// the stream
+test_add_display_interface(test);
+/* qxl device supports 2 monitors */
+spice_qxl_set_device_info(>qxl_instance, "pci/0/1.2", 0, 2);
+
 // craft a message from the mock stream device that provides display info 
to the server for the
 // given stream
 static const char address[] = "pci/a/b.cde";
@@ -515,11 +521,6 @@ static void test_display_info(TestFixture *fixture, 
gconstpointer user_data)
 // info for the mock stream device
 test_kick();
 
-// initialize a QXL interface
-test_add_display_interface(test);
-/* qxl device supports 2 monitors */
-spice_qxl_set_device_info(>qxl_instance, "pci/0/1.2", 0, 2);
-
 // build the buffer to send to the agent for display information
 SpiceMarshaller *m = spice_marshaller_new();
 reds_marshall_device_display_info(test->server, m);
@@ -544,7 +545,7 @@ static void test_display_info(TestFixture *fixture, 
gconstpointer user_data)
   /* device_address_len */ 10,  0,  0,  0,
   /* device_address */'p','c', 'i','/','0','/','1','.','2',  0,
 
-  /* channel_id */  0,  0,  0,  0,
+  /* channel_id */  1,  0,  0,  0,
   /* monitor_id */  4,  3,  2,  1,
   /* device_display_id */  13, 12, 11, 10,
   /* device_address_len */ 12,  0,  0,  0,
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel

Re: [Spice-devel] [PATCH spice-server 2/8] reds: Factor out a function to marshall VDAgentGraphicsDeviceInfo message

2019-02-12 Thread Jonathon Jongsma
On Tue, 2019-02-12 at 12:24 -0500, Frediano Ziglio wrote:
> > On Tue, 2019-02-12 at 04:05 -0500, Frediano Ziglio wrote:
> > >  
> > > > Untested, but looks fine.
> > > > 
> > > > Acked-by: Jonathon Jongsma 
> > > > 
> > > 
> > > It's partially tested by following patch. Partially as the new
> > > function is
> > > tested but the old function to send the message is not but is
> > > changed
> > > in
> > > this test.
> > > But I can see data sent to the guest (so I tested that part
> > > manually).
> > > 
> > > Should the verb be "marshall" or "marshal" ? I think the second,
> > > so
> > > I should rename the function.
> > 
> > Yeah, I believe marshal is technically correct
> > Jonathon
> > 
> 
> I did some grep+wc on our code... looks like we are changing the
> dictionary!
> I think 90% or more of the occurrences are marshalL.
> But we have to start fixing it somewhere, why not now?
> Looks like both marshaler and marshaller are correct although the
> later
> (marshaller) seems more accepted.

Yeah, it's a bit of an odd case because both "marshal" and "marshall"
are valid words (though the latter is more often a family name), so
they get mixed up a lot. To be honest, I don't mind too much whether
you decide to keep the wrong spelling for consistency or start changing
them to the 'correct' spelling. 

But yes, "marshaller" and "marshalling" usually have a double L due to
the normal pronunciation rules of English. "Marshaler" looks like it
should be pronounced with a long A sound. English is dumb ;)

Jonathon


> 
> > 
> > > 
> > > Frediano
> > > 
> > > > 
> > > > 
> > > > On Mon, 2019-02-11 at 11:54 +, Frediano Ziglio wrote:
> > > > > Instead of scanning the monitor twice (one to compute the
> > > > > size
> > > > > and another to build the message) use a single function to
> > > > > marshall the message.
> > > > > This also fixes big endian machines (which are not
> > > > > supported).
> > > > > Marshall function is exported to make easier to test (see
> > > > > following
> > > > > patch).
> > > > > 
> > > > > Signed-off-by: Frediano Ziglio 
> > > > > ---
> > > > > Also the reds_marshall_device_display_info function will be
> > > > > potentially used to separate VDIPort code.
> > > > > ---
> > > > >  server/reds.c | 143 ++
> > > > > 
> > > > > 
> > > > > 
> > > > >  server/reds.h |   3 ++
> > > > >  2 files changed, 66 insertions(+), 80 deletions(-)
> > > > > 
> > > > > diff --git a/server/reds.c b/server/reds.c
> > > > > index 86f020a87..c16655adf 100644
> > > > > --- a/server/reds.c
> > > > > +++ b/server/reds.c
> > > > > @@ -897,78 +897,33 @@ static RedPipeItem
> > > > > *vdi_port_read_one_msg_from_device(RedCharDevice *self,
> > > > >  return NULL;
> > > > >  }
> > > > >  
> > > > > -void reds_send_device_display_info(RedsState *reds)
> > > > > +void reds_marshall_device_display_info(RedsState *reds,
> > > > > SpiceMarshaller *m)
> > > > >  {
> > > > > -if (!reds->agent_dev->priv->agent_attached) {
> > > > > -return;
> > > > > -}
> > > > > -g_debug("Sending device display info to the agent:");
> > > > > -
> > > > >  QXLInstance *qxl;
> > > > >  RedCharDevice *dev;
> > > > >  
> > > > > -size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> > > > > -
> > > > > -// size for the qxl device info
> > > > > -FOREACH_QXL_INSTANCE(reds, qxl) {
> > > > > -message_size +=
> > > > > -(sizeof(VDAgentDeviceDisplayInfo) +
> > > > > strlen(red_qxl_get_device_address(qxl)) + 1) *
> > > > > -red_qxl_get_monitors_count(qxl);
> > > > > -}
> > > > > -
> > > > > -// size for the stream device info
> > > > > -GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
> > >

Re: [Spice-devel] [PATCH spice-server 2/8] reds: Factor out a function to marshall VDAgentGraphicsDeviceInfo message

2019-02-11 Thread Jonathon Jongsma
Untested, but looks fine.

Acked-by: Jonathon Jongsma 



On Mon, 2019-02-11 at 11:54 +, Frediano Ziglio wrote:
> Instead of scanning the monitor twice (one to compute the size
> and another to build the message) use a single function to
> marshall the message.
> This also fixes big endian machines (which are not supported).
> Marshall function is exported to make easier to test (see following
> patch).
> 
> Signed-off-by: Frediano Ziglio 
> ---
> Also the reds_marshall_device_display_info function will be
> potentially used to separate VDIPort code.
> ---
>  server/reds.c | 143 ++
> 
>  server/reds.h |   3 ++
>  2 files changed, 66 insertions(+), 80 deletions(-)
> 
> diff --git a/server/reds.c b/server/reds.c
> index 86f020a87..c16655adf 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -897,78 +897,33 @@ static RedPipeItem
> *vdi_port_read_one_msg_from_device(RedCharDevice *self,
>  return NULL;
>  }
>  
> -void reds_send_device_display_info(RedsState *reds)
> +void reds_marshall_device_display_info(RedsState *reds,
> SpiceMarshaller *m)
>  {
> -if (!reds->agent_dev->priv->agent_attached) {
> -return;
> -}
> -g_debug("Sending device display info to the agent:");
> -
>  QXLInstance *qxl;
>  RedCharDevice *dev;
>  
> -size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> -
> -// size for the qxl device info
> -FOREACH_QXL_INSTANCE(reds, qxl) {
> -message_size +=
> -(sizeof(VDAgentDeviceDisplayInfo) +
> strlen(red_qxl_get_device_address(qxl)) + 1) *
> -red_qxl_get_monitors_count(qxl);
> -}
> -
> -// size for the stream device info
> -GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
> -if (IS_STREAM_DEVICE(dev)) {
> -size_t device_address_len =
> -strlen(stream_device_get_device_display_info(STREAM_
> DEVICE(dev))->device_address);
> -
> -if (device_address_len == 0) {
> -// the device info wasn't set (yet), don't send it
> -continue;
> -}
> -
> -message_size += (sizeof(VDAgentDeviceDisplayInfo) +
> device_address_len + 1);
> -}
> -}
> -
> -RedCharDeviceWriteBuffer *char_dev_buf =
> vdagent_new_write_buffer(reds->agent_dev,
> - VD_AGENT_GRAPHICS_DEVICE_IN
> FO,
> - message_size,
> - true);
> -
> -if (!char_dev_buf) {
> -reds->pending_device_display_info_message = true;
> -return;
> -}
> -
> -VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf-
> >buf;
> -VDAgentGraphicsDeviceInfo *graphics_device_info = _buf-
> >u.graphics_device_info;
> -graphics_device_info->count = 0;
> -
> -VDAgentDeviceDisplayInfo *device_display_info =
> graphics_device_info->display_info;
> +uint32_t device_count = 0;
> +void *device_count_ptr = spice_marshaller_add_uint32(m,
> device_count);
>  
>  // add the qxl devices to the message
>  FOREACH_QXL_INSTANCE(reds, qxl) {
> +const char *const device_address =
> red_qxl_get_device_address(qxl);
> +const size_t device_address_len = strlen(device_address) +
> 1;
> +if (device_address_len == 1) {
> +continue;
> +}
>  for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i)
> {
> -device_display_info->channel_id = qxl->id;
> -device_display_info->monitor_id = i;
> -device_display_info->device_display_id =
> red_qxl_get_device_display_ids(qxl)[i];
> -
> -strcpy((char*) device_display_info->device_address,
> red_qxl_get_device_address(qxl));
> -
> -device_display_info->device_address_len =
> -strlen((char*) device_display_info->device_address)
> + 1;
> -
> -g_debug("   (qxl)channel_id: %u monitor_id: %u,
> device_address: %s, device_display_id: %u",
> -device_display_info->channel_id,
> -device_display_info->monitor_id,
> -device_display_info->device_address,
> -device_display_info->device_display_id);
> -
> -device_display_info = (VDAgentDeviceDisplayInfo*)
> ((char*) device_display_info +
> -sizeof(VDAgentDeviceDisplayInfo) +
> device_display_info->device_address_len);
> -
> -graphics_device_info->count+

Re: [Spice-devel] [PATCH v2 spice-gtk] Update the codeflow description comment

2019-02-11 Thread Jonathon Jongsma
On Mon, 2019-02-11 at 16:14 +0200, Snir Sheriber wrote:
> ---
>  src/channel-display-gst.c | 39 ++---
> --
>  1 file changed, 22 insertions(+), 17 deletions(-)
> 
> diff --git a/src/channel-display-gst.c b/src/channel-display-gst.c
> index 4272ade..c63592b 100644
> --- a/src/channel-display-gst.c
> +++ b/src/channel-display-gst.c
> @@ -580,34 +580,39 @@ static void
> spice_gst_decoder_destroy(VideoDecoder *video_decoder)
>  /* spice_gst_decoder_queue_frame() queues the SpiceFrame for
> decoding and
>   * displaying. The steps it goes through are as follows:
>   *
> - * 1) A SpiceGstFrame is created to keep track of SpiceFrame and
> some additional
> - *metadata. The SpiceGstFrame is then pushed to the
> decoding_queue.
> - * 2) frame->data, which contains the compressed frame data, is
> reffed and
> - *wrapped in a GstBuffer which is pushed to the GStreamer
> pipeline for
> - *decoding.
> - * 3) As soon as the GStreamer pipeline no longer needs the
> compressed frame it
> - *will call frame->unref_data() to free it.
> + * 1) frame->data, which contains the compressed frame data, is
> wrapped in a GstBuffer
> + *(encoded_buffer) which owns the SpiceFrame.
> + * 2) A SpiceGstFrame is created to keep track of SpiceFrame
> (encoded_frame), and some
> + *additional metadata. The encoded_buffer is referenced and the
> SpiceGstFrame is then
> + *pushed into the decoding_queue.
>   *
>   * If GstVideoOverlay is used (window handle was obtained
> successfully at the widget):
> - *   4) Decompressed frames will be renderd to widget directly from
> gstreamer's pipeline
> - *  using some gstreamer sink plugin which implements the
> GstVideoOverlay interface
> + *   3) Decompressed frames will be rendered to widget directly from
> GStreamer's pipeline

"to *the* widget" sounds more correct. Otherwise I'd say the rest of
this patch looks fine. I only reviewed it for language, though. I
didn't check that the description actually matches the code.

Reviewed-by: Jonathon Jongsma 



> + *  using some GStreamer sink plugin which implements the
> GstVideoOverlay interface
>   *  (last step).
> + *   4) As soon as GStreamer's pipeline no longer needs the
> compressed frame it will
> + *  unref the encoded_buffer
> + *   5) Once a decoded buffer arrives to the sink (notified by probe
> event) we will pop
> + *  its matching SpiceGstFrame from the decoding_queue and free
> it using
> + *  free_gst_frame, this will also unref the encoded_buffer
> which will allow
> + *  GStreamer to call spice_frame_free and free its
> encoded_frame.
>   *
>   * Otherwise appsink is used:
> - *   4) Once the decompressed frame is available the GStreamer
> pipeline calls
> + *   3) Once the decompressed frame is available the GStreamer
> pipeline calls
>   *  new_sample() in the GStreamer thread.
> - *   5) new_sample() then matches the decompressed frame to a
> SpiceGstFrame from
> + *   4) new_sample() then matches the decompressed frame to a
> SpiceGstFrame from
>   *  the decoding queue using the GStreamer timestamp information
> to deal with
>   *  dropped frames. The SpiceGstFrame is popped from the
> decoding_queue.
> - *   6) new_sample() then attaches the decompressed frame to the
> SpiceGstFrame,
> + *   5) new_sample() then attaches the decompressed frame to the
> SpiceGstFrame,
>   *  set into display_frame and calls schedule_frame().
> - *   7) schedule_frame() then uses gstframe->frame->mm_time to
> arrange for
> + *   6) schedule_frame() then uses gstframe->encoded_frame->mm_time
> to arrange for
>   *  display_frame() to be called, in the main thread, at the
> right time for
>   *  the next frame.
> - *   8) display_frame() use SpiceGstFrame from display_frame and
> - *  calls stream_display_frame().
> - *   9) display_frame() then frees the SpiceGstFrame, which frees
> the SpiceFrame
> - *  and decompressed frame with it.
> + *   7) display_frame() uses SpiceGstFrame from display_frame and
> calls
> + *  stream_display_frame().
> + *   8) display_frame() then calls to free_gst_frame to free the
> SpiceGstFrame and
> + *  unref the encoded_buffer which allows GStreamer to call
> spice_frame_free
> + *  and free its encoded_frame.
>   */
>  static gboolean spice_gst_decoder_queue_frame(VideoDecoder
> *video_decoder,
>SpiceFrame *frame, int
> latency)

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent] Fix coding style

2019-01-29 Thread Jonathon Jongsma
Use brackets everywhere.
---
 src/vdagent/device-info.c | 28 +++-
 1 file changed, 19 insertions(+), 9 deletions(-)

diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
index 7c0f615..4983543 100644
--- a/src/vdagent/device-info.c
+++ b/src/vdagent/device-info.c
@@ -84,8 +84,9 @@ static int read_next_hex_number(const char *input, char 
delim, char **endptr)
 n = strtol(input, , 16);
 
 // check if we read all characters until the delimiter
-if (endpos != pos)
+if (endpos != pos) {
 endpos = NULL;
+}
 
 *endptr = endpos;
 return n;
@@ -95,15 +96,19 @@ static int read_next_hex_number(const char *input, char 
delim, char **endptr)
 // see https://wiki.xen.org/wiki/Bus:Device.Function_(BDF)_Notation
 static bool parse_pci_device(const char *bdf, const char *end, PciDevice 
*device)
 {
-if (!end) end = strchr(bdf, 0);
+if (!end) {
+end = strchr(bdf, 0);
+}
 
 int endpos = -1;
 int domain, bus, slot, function;
 sscanf(bdf, "%x:%x:%x.%x%n", , , , , );
-if (!device || endpos < 0 || bdf + endpos != end)
+if (!device || endpos < 0 || bdf + endpos != end) {
 return false;
-if (domain < 0 || bus < 0 || slot < 0 || function < 0)
+}
+if (domain < 0 || bus < 0 || slot < 0 || function < 0) {
 return false;
+}
 
 device->domain = domain;
 device->bus = bus;
@@ -121,8 +126,9 @@ static bool parse_pci_device(const char *bdf, const char 
*end, PciDevice *device
 static PciAddress* parse_pci_address_from_sysfs_path(const char* addr)
 {
 char *pos = strstr(addr, "/pci");
-if (!pos)
+if (!pos) {
 return NULL;
+}
 
 // advance to the numbers in pci:00
 pos += 4;
@@ -157,8 +163,9 @@ static PciAddress* parse_pci_address_from_sysfs_path(const 
char* addr)
 static PciAddress* parse_pci_address_from_spice(char *input)
 {
 static const char prefix[] = "pci/";
-if (strncmp(input, prefix, strlen(prefix)) != 0)
+if (strncmp(input, prefix, strlen(prefix)) != 0) {
 return NULL;
+}
 
 char *pos = input + strlen(prefix);
 int domain = read_next_hex_number(pos, '/', );
@@ -187,8 +194,9 @@ static PciAddress* parse_pci_address_from_spice(char *input)
 
 address->devices = g_list_append(address->devices, dev);
 pos = next;
-if (!pos)
+if (!pos) {
 break;
+}
 }
 return address;
 }
@@ -298,12 +306,14 @@ static void drm_conn_name_modesetting(drmModeConnector 
*conn, char *dest, size_t
 
 static bool read_hex_value_from_file(const char *path, int* value)
 {
-if (value == NULL || path == NULL)
+if (value == NULL || path == NULL) {
 return false;
+}
 
 FILE *f = fopen(path, "r");
-if (f == NULL)
+if (f == NULL) {
 return false;
+}
 
 int endpos = -1;
 bool result = (fscanf(f, "%x\n%n", value, ) > 0 && endpos >= 0);
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH linux vdagent v5 1/7] Add lookup_xrand_output_for_device_info()

2019-01-29 Thread Jonathon Jongsma
On Tue, 2019-01-29 at 10:17 -0500, Frediano Ziglio wrote:
> Can you use the coding style at least for new code?
> In particular always use brackets, code is half with and half without

Oh, I already pushed after Lukas's ACK. I'll send a follow-up patch
fixing some bracket usage. Not sure how I missed so many...


> 
> > 
> > Add a function to look up an xrandr output for a given device
> > display
> > id. This uses sysfs and the drm subsystem to lookup information
> > about a
> > graphics device output. It then compares the drm output name to
> > xrandr
> > output names to try to match that device output to an xrandr
> > output.
> > This is necesary for guests that have multiple graphics devices.
> > ---
> >  Makefile.am   |  14 ++
> >  configure.ac  |   1 +
> >  src/vdagent/device-info.c | 506
> > ++
> >  src/vdagent/device-info.h |  30 +++
> >  tests/test-device-info.c  | 262 
> >  5 files changed, 813 insertions(+)
> >  create mode 100644 src/vdagent/device-info.c
> >  create mode 100644 src/vdagent/device-info.h
> >  create mode 100644 tests/test-device-info.c
> > 
> > diff --git a/Makefile.am b/Makefile.am
> > index 97b8bf0..c2e9668 100644
> > --- a/Makefile.am
> > +++ b/Makefile.am
> > @@ -14,6 +14,7 @@ common_sources =  \
> > $(NULL)
> >  
> >  src_spice_vdagent_CFLAGS = \
> > +   $(DRM_CFLAGS)   \
> > $(X_CFLAGS) \
> > $(SPICE_CFLAGS) \
> > $(GLIB2_CFLAGS) \
> > @@ -24,6 +25,7 @@ src_spice_vdagent_CFLAGS =
> > \
> > $(NULL)
> >  
> >  src_spice_vdagent_LDADD =  \
> > +   $(DRM_LIBS) \
> > $(X_LIBS)   \
> > $(SPICE_LIBS)   \
> > $(GLIB2_LIBS)   \
> > @@ -37,6 +39,8 @@ src_spice_vdagent_SOURCES =   
> > \
> > src/vdagent/audio.h \
> > src/vdagent/clipboard.c \
> > src/vdagent/clipboard.h \
> > +   src/vdagent/device-info.c   \
> > +   src/vdagent/device-info.h   \
> > src/vdagent/file-xfers.c\
> > src/vdagent/file-xfers.h\
> > src/vdagent/x11-priv.h  \
> > @@ -159,3 +163,13 @@ EXTRA_DIST =   
> > \
> >  DISTCHECK_CONFIGURE_FLAGS =\
> > --with-init-script=redhat   \
> > $(NULL)
> > +
> > +tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD)
> > +tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS)
> > +
> > +check_PROGRAMS =   \
> > +   tests/test-device-info  \
> > +   $(NULL)
> > +
> > +TESTS = $(check_PROGRAMS)
> > +
> > diff --git a/configure.ac b/configure.ac
> > index 7cb44db..55b031e 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3
> > xinerama x11])
> >  PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
> >  PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
> >  PKG_CHECK_MODULES([DBUS], [dbus-1])
> > +PKG_CHECK_MODULES([DRM], [libdrm])
> >  
> >  if test "$with_session_info" = "auto" || test "$with_session_info"
> > =
> >  "systemd"; then
> >  PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
> > diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
> > new file mode 100644
> > index 000..7c0f615
> > --- /dev/null
> > +++ b/src/vdagent/device-info.c
> > @@ -0,0 +1,506 @@
> > +/*  device-info.c utility function for looking up the xrandr
> > output id for a
> > + *  given device address and display id
> > + *
> > + * Copyright 2018 Red Hat, Inc.
> > + *
> > + * Red Hat Authors:
> > + * Jonathon Jongsma 
> > + *
> > + * This program is free software: you can redistribute it and/or
> > modify
> > + * it under the terms of the GNU General Public License as
> > published by
> > + * the Free Software Foundation, either version 3 of the License,
> > or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in t

Re: [Spice-devel] [PATCH] QXL interface: improve the spice_qxl_set_device_info documentation

2019-01-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Mon, 2019-01-28 at 11:14 +0100, Lukáš Hrázký wrote:
> Instead of one unsupported example, present two real world examples.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/spice-qxl.h | 32 ++--
>  1 file changed, 22 insertions(+), 10 deletions(-)
> 
> diff --git a/server/spice-qxl.h b/server/spice-qxl.h
> index e7af5e5e..2f47910b 100644
> --- a/server/spice-qxl.h
> +++ b/server/spice-qxl.h
> @@ -122,7 +122,7 @@ void spice_qxl_gl_draw_async(QXLInstance
> *instance,
>   * @instance the QXL instance to set the path to
>   * @device_address the path of the device this QXL instance belongs
> to
>   * @device_display_id_start the starting device display ID of this
> interface,
> - *  i.e. the one monitor ID 0 maps to
> + *  i.e. the device display ID of monitor ID
> 0
>   * @device_display_id_count the total number of device display IDs
> on this
>   *  interface
>   *
> @@ -145,16 +145,28 @@ void spice_qxl_gl_draw_async(QXLInstance
> *instance,
>   *
>   * The device_display_id_{start,count} denotes the sequence of
> device display
>   * IDs that map to the zero-based sequence of monitor IDs provided
> by monitors
> - * config on this interface. For example with
> device_display_id_start = 2 and
> - * device_display_id_count = 3 you get the following mapping:
> - * monitor_id  ->  device_display_id
> - *  0  ->  2
> - *  1  ->  3
> - *  2  ->  4
> + * config on this interface.
>   *
> - * Note this example is unsupported in practice. The only supported
> cases are
> - * either a single device display ID (count = 1) or multiple device
> display IDs
> - * in a sequence starting from 0.
> + * Example 1:
> + *   A QXL graphics device with 3 heads (monitors).
> + *
> + *   device_display_id_start = 0
> + *   device_display_id_count = 3
> + *
> + *   Results in the following mapping of monitor_id  -
> >  device_display_id:
> + *   0  ->  0
> + *   1  ->  1
> + *   2  ->  2
> + *
> + * Example 2:
> + *   A virtio graphics device, multiple monitors, a QXL interface
> for each
> + *   monitor. On the QXL interface for the third monitor:
> + *
> + *   device_display_id_start = 2
> + *   device_display_id_count = 1
> + *
> + *   Results in the following mapping of monitor_id  -
> >  device_display_id:
> + *   0  ->  2
>   */
>  void spice_qxl_set_device_info(QXLInstance *instance,
> const char *device_address,

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice v4 2/6] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-28 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Mon, 2019-01-28 at 15:09 +0100, Lukáš Hrázký wrote:
> Receives the GraphicsDeviceInfo message from the streaming agent and
> stores the data in a list on the streaming device.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/display-limits.h|  3 ++
>  server/red-qxl.c   |  2 +-
>  server/red-stream-device.c | 78
> +-
>  server/red-stream-device.h |  8 
>  4 files changed, 88 insertions(+), 3 deletions(-)
> 
> diff --git a/server/display-limits.h b/server/display-limits.h
> index e875149b..d79d3211 100644
> --- a/server/display-limits.h
> +++ b/server/display-limits.h
> @@ -25,4 +25,7 @@
>  /** Maximum number of streams created by spice-server */
>  #define NUM_STREAMS 50
>  
> +/** Maximum length of the device address string */
> +#define MAX_DEVICE_ADDRESS_LEN 256
> +
>  #endif /* DISPLAY_LIMITS_H_ */
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 7f8ac35d..37f3d9c8 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -37,11 +37,11 @@
>  #include "dispatcher.h"
>  #include "red-parse-qxl.h"
>  #include "red-channel-client.h"
> +#include "display-limits.h"
>  
>  #include "red-qxl.h"
>  
>  
> -#define MAX_DEVICE_ADDRESS_LEN 256
>  #define MAX_MONITORS_COUNT 16
>  
>  struct QXLState {
> diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> index 3b553510..38df8e4c 100644
> --- a/server/red-stream-device.c
> +++ b/server/red-stream-device.c
> @@ -39,6 +39,7 @@ struct StreamDevice {
>  StreamMsgCapabilities capabilities;
>  StreamMsgCursorSet cursor_set;
>  StreamMsgCursorMove cursor_move;
> +StreamMsgDeviceDisplayInfo device_display_info;
>  uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
>  } *msg;
>  uint32_t msg_pos;
> @@ -51,6 +52,7 @@ struct StreamDevice {
>  CursorChannel *cursor_channel;
>  SpiceTimer *close_timer;
>  uint32_t frame_mmtime;
> +StreamDeviceDisplayInfo device_display_info;
>  };
>  
>  struct StreamDeviceClass {
> @@ -66,8 +68,8 @@ static void char_device_set_state(RedCharDevice
> *char_dev, int state);
>  typedef bool StreamMsgHandler(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  SPICE_GNUC_WARN_UNUSED_RESULT;
>  
> -static StreamMsgHandler handle_msg_format, handle_msg_data,
> handle_msg_cursor_set,
> -handle_msg_cursor_move, handle_msg_capabilities;
> +static StreamMsgHandler handle_msg_format,
> handle_msg_device_display_info, handle_msg_data,
> +handle_msg_cursor_set, handle_msg_cursor_move,
> handle_msg_capabilities;
>  
>  static bool handle_msg_invalid(StreamDevice *dev,
> SpiceCharDeviceInstance *sin,
> const char *error_msg)
> SPICE_GNUC_WARN_UNUSED_RESULT;
> @@ -150,6 +152,13 @@ stream_device_partial_read(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  handled = handle_msg_format(dev, sin);
>  }
>  break;
> +case STREAM_TYPE_DEVICE_DISPLAY_INFO:
> +if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) +
> MAX_DEVICE_ADDRESS_LEN) {
> +handled = handle_msg_invalid(dev, sin,
> "StreamMsgDeviceDisplayInfo too large");
> +} else {
> +handled = handle_msg_device_display_info(dev, sin);
> +}
> +break;
>  case STREAM_TYPE_DATA:
>  if (dev->hdr.size > 32*1024*1024) {
>  handled = handle_msg_invalid(dev, sin, "STREAM_DATA too
> large");
> @@ -275,6 +284,71 @@ handle_msg_format(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  return true;
>  }
>  
> +static bool
> +handle_msg_device_display_info(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
> +{
> +SpiceCharDeviceInterface *sif =
> spice_char_device_get_interface(sin);
> +
> +if (spice_extra_checks) {
> +spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
> +spice_assert(dev->hdr.type ==
> STREAM_TYPE_DEVICE_DISPLAY_INFO);
> +}
> +
> +if (dev->msg_len < dev->hdr.size) {
> +dev->msg = g_realloc(dev->msg, dev->hdr.size);
> +dev->msg_len = dev->hdr.size;
> +}
> +
> +/* read from device */
> +ssize_t n = sif->read(sin, dev->msg->buf + dev->msg_pos, dev-
> >hdr.size - dev->msg_pos);
> +if (n <= 0) {
> +return dev->msg_pos == dev->hdr.size;
> +}
> +
> +dev->msg_pos += n;
> +if (dev->msg_pos != dev->hdr.size) { /* some bytes are s

[Spice-devel] [PATCH linux vdagent v5 1/7] Add lookup_xrand_output_for_device_info()

2019-01-23 Thread Jonathon Jongsma
Add a function to look up an xrandr output for a given device display
id. This uses sysfs and the drm subsystem to lookup information about a
graphics device output. It then compares the drm output name to xrandr
output names to try to match that device output to an xrandr output.
This is necesary for guests that have multiple graphics devices.
---
 Makefile.am   |  14 ++
 configure.ac  |   1 +
 src/vdagent/device-info.c | 506 ++
 src/vdagent/device-info.h |  30 +++
 tests/test-device-info.c  | 262 
 5 files changed, 813 insertions(+)
 create mode 100644 src/vdagent/device-info.c
 create mode 100644 src/vdagent/device-info.h
 create mode 100644 tests/test-device-info.c

diff --git a/Makefile.am b/Makefile.am
index 97b8bf0..c2e9668 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ common_sources =  \
$(NULL)
 
 src_spice_vdagent_CFLAGS = \
+   $(DRM_CFLAGS)   \
$(X_CFLAGS) \
$(SPICE_CFLAGS) \
$(GLIB2_CFLAGS) \
@@ -24,6 +25,7 @@ src_spice_vdagent_CFLAGS =\
$(NULL)
 
 src_spice_vdagent_LDADD =  \
+   $(DRM_LIBS) \
$(X_LIBS)   \
$(SPICE_LIBS)   \
$(GLIB2_LIBS)   \
@@ -37,6 +39,8 @@ src_spice_vdagent_SOURCES =   \
src/vdagent/audio.h \
src/vdagent/clipboard.c \
src/vdagent/clipboard.h \
+   src/vdagent/device-info.c   \
+   src/vdagent/device-info.h   \
src/vdagent/file-xfers.c\
src/vdagent/file-xfers.h\
src/vdagent/x11-priv.h  \
@@ -159,3 +163,13 @@ EXTRA_DIST =   \
 DISTCHECK_CONFIGURE_FLAGS =\
--with-init-script=redhat   \
$(NULL)
+
+tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD)
+tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS)
+
+check_PROGRAMS =   \
+   tests/test-device-info  \
+   $(NULL)
+
+TESTS = $(check_PROGRAMS)
+
diff --git a/configure.ac b/configure.ac
index 7cb44db..55b031e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
 PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
 PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
 PKG_CHECK_MODULES([DBUS], [dbus-1])
+PKG_CHECK_MODULES([DRM], [libdrm])
 
 if test "$with_session_info" = "auto" || test "$with_session_info" = 
"systemd"; then
 PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
new file mode 100644
index 000..7c0f615
--- /dev/null
+++ b/src/vdagent/device-info.c
@@ -0,0 +1,506 @@
+/*  device-info.c utility function for looking up the xrandr output id for a
+ *  given device address and display id
+ *
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * Red Hat Authors:
+ * Jonathon Jongsma 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "device-info.h"
+
+#define PCI_VENDOR_ID_REDHAT 0x1b36
+#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 // virtio-gpu
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
+#define PCI_DEVICE_ID_QXL 0x0100
+#define PCI_DEVICE_ID_VIRTIO_GPU 0x1050
+
+typedef struct PciDevice {
+int domain;
+uint8_t bus;
+uint8_t slot;
+uint8_t function;
+} PciDevice;
+
+typedef struct PciAddress {
+int domain;
+GList *devices; /* PciDevice */
+} PciAddress;
+
+static PciAddress* pci_address_new()
+{
+return g_new0(PciAddress, 1);
+}
+
+static void pci_address_free(PciAddress *addr)
+{
+g_list_free_full(addr->devices, g_free);
+g_free(addr);
+}
+
+
+static int read_next_hex_number(const char *input, char delim, char

[Spice-devel] [PATCH linux vdagent v5 7/7] Send display_id down to the vdagentd daemon

2019-01-23 Thread Jonathon Jongsma
Add a display_id field to the structure that we use to send down the
list of guest display resolutions to the vdagentd daemon. This allows us
to map the spice display id to the proper X display for determining
mouse locations, etc.

In the case where we have an mjpeg plugin running in the streaming
agent, we have two spice displays representing the same guest display.
In that scenario, the session agent may maintain the following guest
output mapping:
 spice channel 0 (QXL) => X output 0
 spice channel 1 (streaming-agent) => X output 0

While this is not necessarily a supported scenario, it would be nice if
the cursor input worked properly in this case. The root problem is that
when the session agent sends down the guest xorg resolutions to the
system daemon, it simply loops through the list of xorg displays, and
for each X display it looks up the first spice display ID associated
with it and sends that down to the daemon. In the scenario mentioned
above, since there is only a single X display configured (albeit
represented by two different spice displays), we would send down a
single display resolution to the system daemon:
 - { width=1280, height=1024, x=0, y=0, display_id=0 }

Notice that there is no entry for display_id=1. When the agent receives
a cursor input message for display channel 1, that message will get
passed to the systemn daemon, which will attempt to look up display_id 1
in order to convert the event coordinates to global coordinates. Finding
no entry for display_id=1, the mouse events do not work.

In this patch, when we want to send the guest resolutions down to the
system daemon, we still loop through the list of X outputs, but for each
output we also loop through the guest output mapping table and send a
resolution structure down to the daemon for each registered output
mapping.  This means that in the previously mentioned scenario, we would
send down the following information:
 - { width=1280, height=1024, x=0, y=0, display_id=0 }
 - { width=1280, height=1024, x=0, y=0, display_id=1 }

 This means that when the client sends a mouse event for display_id=1,
 the system daemon knows the coordinates of the guest display associated
 with that ID and can process the mouse event properly.
---
 src/vdagent/x11-randr.c | 82 -
 src/vdagentd-proto.h|  1 +
 src/vdagentd/uinput.c   | 23 +---
 3 files changed, 76 insertions(+), 30 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 8ff5a76..88857c8 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -689,7 +689,6 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
-
 // gets monitor information about the specified output index and returns true 
if there was no error
 static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index,
   int *x, int *y, int *width, int 
*height)
@@ -840,6 +839,9 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
 sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
 }
+
+// make sure daemon is up-to-date with (possibly updated) device IDs
+vdagent_x11_send_daemon_guest_xorg_res(x11, 1);
 }
 
 static int get_output_index_for_display_id(struct vdagent_x11 *x11, int 
display_id)
@@ -1067,7 +1069,7 @@ exit:
 
 void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, int 
update)
 {
-struct vdagentd_guest_xorg_resolution *res = NULL;
+GArray *res_array = g_array_new(FALSE, FALSE, sizeof(struct 
vdagentd_guest_xorg_resolution));
 int i, width = 0, height = 0, screen_count = 0;
 
 if (x11->has_xrandr) {
@@ -1075,15 +1077,38 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 update_randr_res(x11, 0);
 
 screen_count = x11->randr.res->noutput;
-res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
 
 for (i = 0; i < screen_count; i++) {
-struct vdagentd_guest_xorg_resolution *curr = [i];
-if (!get_monitor_info_for_output_index(x11, i, >x, >y,
-   >width, 
>height)) {
-g_free(res);
+struct vdagentd_guest_xorg_resolution curr;
+if (!get_monitor_info_for_output_index(x11, i, , ,
+, )) {
+g_array_free(res_array, TRUE);
 goto no_info;
 }
+if (g_hash_table_size(x11->guest_output_map) == 0) {
+syslog(LOG_DEBUG, "No guest output map, using output index as 
display id");
+curr.display_id = i;
+g_array_append_val(res_array, curr);
+} else {
+// There may 

[Spice-devel] [PATCH linux vdagent v5 5/7] Factor a function out of get_current_mon_config()

2019-01-23 Thread Jonathon Jongsma
When sending the guest xorg resolution to the vdagentd daemon, we get
the current resolution with this function, which returns a
VDAgentMonitorsConfig structure that must then be converted to the
structure that we send to the daemon. Rather than re-using this function
that returns the wrong type, factor out most of the functionality into a
separate function. This function can be used by a new function to return
a type appropriate for sending the xorg resolution to the daemon.

This is necessary because in the next few commits I'll be changing the
vdagentd protocol to send an additional display_id parameter to the
daemon.
---
 src/vdagent/x11-randr.c | 74 +
 1 file changed, 53 insertions(+), 21 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 5ac11dd..6265a6d 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -689,38 +689,70 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
+
+// gets monitor information about the specified output index and returns true 
if there was no error
+static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index,
+  int *x, int *y, int *width, int 
*height)
+{
+g_return_val_if_fail (output_index < x11->randr.res->noutput, false);
+g_return_val_if_fail (x != NULL, false);
+g_return_val_if_fail (y != NULL, false);
+g_return_val_if_fail (width != NULL, false);
+g_return_val_if_fail (height != NULL, false);
+
+int j;
+XRRCrtcInfo *crtc = NULL;
+XRRModeInfo *mode;
+
+if (x11->randr.outputs[output_index]->ncrtc == 0)
+goto zeroed; /* Monitor disabled */
+
+for (j = 0; crtc == NULL && j < x11->randr.outputs[output_index]->ncrtc; 
j++) {
+crtc = crtc_from_id(x11, x11->randr.outputs[output_index]->crtcs[j]);
+}
+if (!crtc) {
+// error. stale xrandr info?
+return false;
+}
+
+mode = mode_from_id(x11, crtc->mode);
+if (!mode)
+goto zeroed; /* monitor disabled */
+
+*x = crtc->x;
+*y = crtc->y;
+*width = mode->width;
+*height = mode->height;
+return true;
+
+zeroed:
+*x = 0;
+*y = 0;
+*width = 0;
+*height = 0;
+return true;
+}
+
 static VDAgentMonitorsConfig *get_current_mon_config(struct vdagent_x11 *x11)
 {
 int i, num_of_monitors = 0;
-XRRModeInfo *mode;
 XRRScreenResources *res = x11->randr.res;
 VDAgentMonitorsConfig *mon_config;
 
 mon_config = g_malloc0(config_size(res->noutput));
 
 for (i = 0 ; i < res->noutput; i++) {
-int j;
-XRRCrtcInfo *crtc = NULL;
-
-if (x11->randr.outputs[i]->ncrtc == 0)
-continue; /* Monitor disabled, already zero-ed by calloc */
-if (x11->randr.outputs[i]->crtc == 0)
-continue; /* Monitor disabled */
-
-for (j = 0; crtc == NULL && j < x11->randr.outputs[i]->ncrtc; j++) {
-crtc = crtc_from_id(x11, x11->randr.outputs[i]->crtcs[j]);
-}
-if (!crtc)
+int x, y, width, height;
+if (!get_monitor_info_for_output_index(x11, i, , , , 
)) {
+syslog(LOG_WARNING, "Unable to get monitor info for output id %d", 
i);
 goto error;
+}
 
-mode = mode_from_id(x11, crtc->mode);
-if (!mode)
-continue; /* Monitor disabled, already zero-ed by calloc */
-
-mon_config->monitors[i].x  = crtc->x;
-mon_config->monitors[i].y  = crtc->y;
-mon_config->monitors[i].width  = mode->width;
-mon_config->monitors[i].height = mode->height;
+VDAgentMonConfig *mon = _config->monitors[i];
+mon->x = x;
+mon->y = y;
+mon->width = width;
+mon->height = height;
 num_of_monitors = i + 1;
 }
 mon_config->num_of_monitors = num_of_monitors;
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v5 2/7] Look up and store xrandr output in display map

2019-01-23 Thread Jonathon Jongsma
Instead of storing each device address and device display ID in the hash
table, simply use the lookup_xrandr_output_for_device_info() function to
look up the ID of the xrandr output and store that in the hash table.
---
 src/vdagent/x11-priv.h  |  2 +-
 src/vdagent/x11-randr.c | 58 +++--
 src/vdagent/x11.c   | 20 +-
 3 files changed, 35 insertions(+), 45 deletions(-)

diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index 0e954cf..e487aa2 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,7 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
-GHashTable *graphics_display_infos;
+GHashTable *guest_output_map;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 405fca9..49c7492 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -31,6 +31,7 @@
 
 #include 
 
+#include "device-info.h"
 #include "vdagentd-proto.h"
 #include "x11.h"
 #include "x11-priv.h"
@@ -727,11 +728,6 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
-typedef struct GraphicsDisplayInfo {
-char device_address[256];
-uint32_t device_display_id;
-} GraphicsDisplayInfo;
-
 // handle the device info message from the server. This will allow us to
 // maintain a mapping from spice display id to xrandr output
 void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
@@ -752,39 +748,39 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 break;
 }
 
-GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
-value->device_address[0] = '\0';
-
-size_t device_address_len = device_display_info->device_address_len;
-if (device_address_len > sizeof(value->device_address)) {
-syslog(LOG_ERR, "Received a device address longer than %lu, "
-   "will be truncated!", device_address_len);
-device_address_len = sizeof(value->device_address);
-}
-
-strncpy(value->device_address,
-(char*) device_display_info->device_address,
-device_address_len);
-
-if (device_address_len > 0) {
-value->device_address[device_address_len - 1] = '\0';  // make 
sure the string is terminated
+// make sure the string is terminated:
+if (device_display_info->device_address_len > 0) {
+
device_display_info->device_address[device_display_info->device_address_len - 
1] = '\0';
 } else {
 syslog(LOG_WARNING, "Zero length device_address received for 
channel_id: %u, monitor_id: %u",
device_display_info->channel_id, 
device_display_info->monitor_id);
 }
 
-value->device_display_id = device_display_info->device_display_id;
-
-syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
-   "device_display_id: %u",
-   device_display_info->channel_id,
-   device_display_info->monitor_id,
-   value->device_address,
-   value->device_display_id);
-
-g_hash_table_insert(x11->graphics_display_infos,
+RROutput x_output;
+if (lookup_xrandr_output_for_device_info(device_display_info, 
x11->display,
+ x11->randr.res, _output)) {
+gint64 *value = g_new(gint64, 1);
+*value = x_output;
+
+syslog(LOG_INFO, "Adding graphics device info: channel_id: %u 
monitor_id: "
+   "%u device_address: %s, device_display_id: %u xrandr output 
ID: %lu",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   device_display_info->device_address,
+   device_display_info->device_display_id,
+   x_output);
+
+g_hash_table_insert(x11->guest_output_map,
 GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
 value);
+} else {
+syslog(LOG_INFO, "channel_id: %u monitor_id: %u device_address: 
%s, "
+   "device_display_id: %u xrandr output ID NOT FOUND",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   device_display_info->device_address,
+   device_display_info->device_display_id);
+}
 
 device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
 sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index ab822f8..484be5e 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ 

[Spice-devel] [PATCH linux vdagent v5 4/7] Use guest output map to determine xrandr output

2019-01-23 Thread Jonathon Jongsma
instead of using the spice display id directly as the xrandr output,
look it up using our new guest output map
---
 src/vdagent/x11-randr.c | 81 -
 1 file changed, 72 insertions(+), 9 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 21a2890..5ac11dd 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -399,6 +399,29 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, int 
output_index, int x,
 return 1;
 }
 
+// Looks up the xrandr output id associated with the given spice display id
+static RROutput get_xrandr_output_for_display_id(struct vdagent_x11 *x11, int 
display_id)
+{
+guint map_size = g_hash_table_size(x11->guest_output_map);
+if (map_size == 0) {
+// we never got a device info message from the server, so just use old
+// assumptions that the spice display id is equal to the index into the
+// array of xrandr outputs
+if (display_id < x11->randr.res->noutput) {
+return x11->randr.res->outputs[display_id];
+}
+} else {
+gpointer value;
+if (g_hash_table_lookup_extended(x11->guest_output_map, 
GINT_TO_POINTER(display_id),
+ NULL, )) {
+return *(gint64*)value;
+}
+}
+
+// unable to find a valid output id
+return -1;
+}
+
 static void xrandr_disable_nth_output(struct vdagent_x11 *x11, int 
output_index)
 {
 Status s;
@@ -787,6 +810,16 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 }
 }
 
+static int get_output_index_for_display_id(struct vdagent_x11 *x11, int 
display_id)
+{
+RROutput oid = get_xrandr_output_for_display_id(x11, display_id);
+for (int i = 0; i < x11->randr.res->noutput; i++) {
+if (oid == x11->randr.res->outputs[i]) {
+return i;
+}
+}
+return -1;
+}
 
 /*
  * Set monitor configuration according to client request.
@@ -863,13 +896,33 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
*x11,
 g_unlink(config);
 g_free(config);
 
-for (i = mon_config->num_of_monitors; i < x11->randr.res->noutput; i++)
-xrandr_disable_nth_output(x11, i);
+// disable all outputs that don't have associated entries in the 
MonitorConfig
+for (i = 0; i < x11->randr.res->noutput; i++) {
+bool disable = true;
+// check if this xrandr output is represented by an item in mon_config
+for (int j = 0; j < mon_config->num_of_monitors; j++) {
+// j represents the display id of an enabled monitor. Check whether
+// an enabled xrandr output is represented by this id.
+RROutput oid = get_xrandr_output_for_display_id(x11, j);
+if (oid == x11->randr.res->outputs[i]) {
+disable = false;
+}
+}
+if (disable) {
+xrandr_disable_nth_output(x11, i);
+}
+}
 
-/* First, disable disabled CRTCs... */
+/* disable CRTCs that are present but explicitly disabled in the
+ * MonitorConfig */
 for (i = 0; i < mon_config->num_of_monitors; ++i) {
 if (!monitor_enabled(_config->monitors[i])) {
-xrandr_disable_nth_output(x11, i);
+int output_index = get_output_index_for_display_id(x11, i);
+if (output_index != -1) {
+xrandr_disable_nth_output(x11, output_index);
+} else {
+syslog(LOG_WARNING, "Unable to find a guest output index for 
spice display %i", i);
+}
 }
 }
 
@@ -892,7 +945,12 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
*x11,
 syslog(LOG_DEBUG, "Disabling monitor %d: %dx%d+%d+%d > 
(%d,%d)",
i, width, height, x, y, primary_w, primary_h);
 
-xrandr_disable_nth_output(x11, i);
+int output_index = get_output_index_for_display_id(x11, i);
+if (output_index != -1) {
+xrandr_disable_nth_output(x11, output_index);
+} else {
+syslog(LOG_WARNING, "Unable to find a guest output index for 
spice display %i", i);
+}
 }
 }
 
@@ -944,11 +1002,16 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
*x11,
i, width, height, x, y);
 }
 
-if (!xrandr_add_and_set(x11, i, x, y, width, height) &&
+int output_index = get_output_index_for_display_id(x11, i);
+if (output_index != -1) {
+if (!xrandr_add_and_set(x11, output_index, x, y, width, height) &&
 enabled_monitors(mon_config) == 1) {
-set_screen_to_best_size(x11, width, height,
-_w, _h);
-break;
+set_screen_to_best_size(x11, width, height,
+_w, _h);
+break;
+}
+} else {
+   

[Spice-devel] [PATCH linux vdagent v5 3/7] Make clearer distinctions between output ids

2019-01-23 Thread Jonathon Jongsma
There are basically three ways to refer to an output within vdagent:
  - The index of the array of MonitorConfig message. This is essentially
a "spice display id"
  - the index of the array of xrandr outputs. This is the "output index"
  - the xrandr output id. This is the "output ID"

Previously, the "spice display id" and the "output index" were treated
as synonymous. But in order to support more complciated setups with
multiple display devices, etc, we need to differentiate these ideas more
clearly. This patch simply renames some variables and a function so that
we can tell more easily which one of these concepts we are dealing with.

Acked-by: Lukáš Hrázký 
---
 src/vdagent/x11-randr.c | 50 -
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 49c7492..21a2890 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -188,14 +188,14 @@ find_mode_by_name (struct vdagent_x11 *x11, char *name)
 }
 
 static XRRModeInfo *
-find_mode_by_size (struct vdagent_x11 *x11, int output, int width, int height)
+find_mode_by_size (struct vdagent_x11 *x11, int output_index, int width, int 
height)
 {
 intm;
 XRRModeInfo*ret = NULL;
 
-for (m = 0; m < x11->randr.outputs[output]->nmode; m++) {
+for (m = 0; m < x11->randr.outputs[output_index]->nmode; m++) {
 XRRModeInfo *mode = mode_from_id(x11,
- x11->randr.outputs[output]->modes[m]);
+ 
x11->randr.outputs[output_index]->modes[m]);
 if (mode && mode->width == width && mode->height == height) {
 ret = mode;
 break;
@@ -342,7 +342,7 @@ static XRRModeInfo *create_new_mode(struct vdagent_x11 
*x11, int output_index,
 return find_mode_by_name(x11, modename);
 }
 
-static int xrandr_add_and_set(struct vdagent_x11 *x11, int output, int x, int 
y,
+static int xrandr_add_and_set(struct vdagent_x11 *x11, int output_index, int 
x, int y,
   int width, int height)
 {
 XRRModeInfo *mode;
@@ -357,33 +357,33 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, 
int output, int x, int y,
 return 0;
 }
 
-if (output < 0 || output >= x11->randr.res->noutput) {
+if (output_index < 0 || output_index >= x11->randr.res->noutput) {
 syslog(LOG_ERR, "%s: program error: bad output", __FUNCTION__);
 return 0;
 }
 
-old_width  = x11->randr.monitor_sizes[output].width;
-old_height = x11->randr.monitor_sizes[output].height;
+old_width  = x11->randr.monitor_sizes[output_index].width;
+old_height = x11->randr.monitor_sizes[output_index].height;
 
 if (x11->set_crtc_config_not_functional) {
 /* fail, set_best_mode will find something close. */
 return 0;
 }
-xid = x11->randr.res->outputs[output];
-mode = find_mode_by_size(x11, output, width, height);
+xid = x11->randr.res->outputs[output_index];
+mode = find_mode_by_size(x11, output_index, width, height);
 if (!mode) {
-mode = create_new_mode(x11, output, width, height);
+mode = create_new_mode(x11, output_index, width, height);
 }
 if (!mode) {
 syslog(LOG_ERR, "failed to add a new mode");
 return 0;
 }
 XRRAddOutputMode(x11->display, xid, mode->id);
-x11->randr.monitor_sizes[output].width = width;
-x11->randr.monitor_sizes[output].height = height;
+x11->randr.monitor_sizes[output_index].width = width;
+x11->randr.monitor_sizes[output_index].height = height;
 outputs[0] = xid;
 vdagent_x11_set_error_handler(x11, ignore_error_handler);
-s = XRRSetCrtcConfig(x11->display, x11->randr.res, 
x11->randr.res->crtcs[output],
+s = XRRSetCrtcConfig(x11->display, x11->randr.res, 
x11->randr.res->crtcs[output_index],
  CurrentTime, x, y, mode->id, RR_Rotate_0, outputs,
  1);
 if (vdagent_x11_restore_error_handler(x11) || (s != RRSetConfigSuccess)) {
@@ -394,24 +394,24 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, 
int output, int x, int y,
 
 /* clean the previous name, if any */
 if (width != old_width || height != old_height)
-delete_mode(x11, output, old_width, old_height);
+delete_mode(x11, output_index, old_width, old_height);
 
 return 1;
 }
 
-static void xrandr_disable_output(struct vdagent_x11 *x11, int output)
+static void xrandr_disable_nth_output(struct vdagent_x11 *x11, int 
output_index)
 {
 Status s;
 
-if (!x11->randr.res || output >= x11->randr.res->noutput || output < 0) {
+if (!x11->randr.res || output_index >= x11->randr.res->noutput || 
output_index < 0) {
 syslog(LOG_ERR, "%s: program error: missing RANDR or bad output",
__FUNCTION__);
 return;
 }
 
-XRROutputInfo *oinfo = x11->randr.outputs[output];
+ 

[Spice-devel] [PATCH linux vdagent v5 6/7] Use new function in vdagent_x11_send_daemon_guest_xorg_res()

2019-01-23 Thread Jonathon Jongsma
Rather than getting the current guest resolution in a
VDAgentMonitorsConfig struct and then translating it to a new struct
type for sending down to the daemon, simply use the new function that
was factored out in a previous commit and populate the message struct
directly.
---
 src/vdagent/x11-randr.c | 19 +++
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 6265a6d..8ff5a76 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -1071,25 +1071,20 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 int i, width = 0, height = 0, screen_count = 0;
 
 if (x11->has_xrandr) {
-VDAgentMonitorsConfig *curr;
-
 if (update)
 update_randr_res(x11, 0);
 
-curr = get_current_mon_config(x11);
-if (!curr)
-goto no_info;
-
-screen_count = curr->num_of_monitors;
+screen_count = x11->randr.res->noutput;
 res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
 
 for (i = 0; i < screen_count; i++) {
-res[i].width  = curr->monitors[i].width;
-res[i].height = curr->monitors[i].height;
-res[i].x = curr->monitors[i].x;
-res[i].y = curr->monitors[i].y;
+struct vdagentd_guest_xorg_resolution *curr = [i];
+if (!get_monitor_info_for_output_index(x11, i, >x, >y,
+   >width, 
>height)) {
+g_free(res);
+goto no_info;
+}
 }
-g_free(curr);
 width  = x11->width[0];
 height = x11->height[0];
 } else if (x11->has_xinerama) {
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v5 0/7] Use the PCI addr and display ID

2019-01-23 Thread Jonathon Jongsma
This is a patch set that handles the PCI address and device dispay ID
sent down to the agent by the server, and uses that to maintain a map
for looking up a particular xrandr output for a given spice display id.

This patch series builds on the patch from Lukas titled "Receive the
graphics_device_info message".

Changes in v5:
 - more line length changes
 - squashed last several patches into one

Changes in v4:
 - rebased on Lukas's latest patch
 - Added a new commit that fixes the cursor when using with mjpeg streaming.
 - various small fixes from previous reviews (e.g. line length, etc)

Changes in v3:
 - Fixed a bug where the X Display was not set properly and caused a
   crash
 - moved call to vdagent_x11_send_daemon_guest_xorg_res() to outside the
   loop to avoid sending multiple times when more than one device is
   received. (Patch 9)

Changes in v2:
 - Removed some ACKed and merged patches
   - Fix typo in comment
   - Fix confusion between output index and crtc index
 - added a patch to send new display IDs when device info changes
 - multiple changes from review
   - factored out function find_device_at_pci_address()
   - No more initializing X/XRandr
   - removed goto
   - improved logging
   - etc.


Jonathon Jongsma (7):
  Add lookup_xrand_output_for_device_info()
  Look up and store xrandr output in display map
  Make clearer distinctions between output ids
  Use guest output map to determine xrandr output
  Factor a function out of get_current_mon_config()
  Use new function in vdagent_x11_send_daemon_guest_xorg_res()
  Send display_id down to the vdagentd daemon

 Makefile.am   |  14 ++
 configure.ac  |   1 +
 src/vdagent/device-info.c | 506 ++
 src/vdagent/device-info.h |  30 +++
 src/vdagent/x11-priv.h|   2 +-
 src/vdagent/x11-randr.c   | 348 +-
 src/vdagent/x11.c |  20 +-
 src/vdagentd-proto.h  |   1 +
 src/vdagentd/uinput.c |  23 +-
 tests/test-device-info.c  | 262 
 10 files changed, 1073 insertions(+), 134 deletions(-)
 create mode 100644 src/vdagent/device-info.c
 create mode 100644 src/vdagent/device-info.h
 create mode 100644 tests/test-device-info.c

-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-gtk 04/12] Drop autotools

2019-01-22 Thread Jonathon Jongsma
On Fri, 2019-01-18 at 15:56 +0400, Marc-André Lureau wrote:
> Hi
> 
> On Fri, Jan 18, 2019 at 3:47 PM Frediano Ziglio 
> wrote:
> > 
> > > 
> > > From: Marc-André Lureau 
> > > 
> > > Maintaining 1 build system is hard. Maintaining 2 is even harder.
> > > 
> > > It seems the meson build system is now in good shape to replace
> > > autotools. Like many desktop projects, let's move entirely to
> > > meson
> > > and drop autotools support.
> > > 
> > > Known changes:
> > > - no git version: a following patch will add it back in a limited
> > > form
> > > - generating changelog & thanks files in the dist tarball. This
> > > is not
> > >   strictly required, and can be added back later.
> > > - generated files are not included in the dist tarball. In some
> > > ways,
> > >   this can be considered a good thing. Since code generation is
> > > done
> > >   with python, and meson requires python anyway, this is not an
> > > issue.
> > > 
> > > Signed-off-by: Marc-André Lureau 
> > 
> > Patience.
> > 
> > It's IMO too early, we are still fixing bugs on Meson build,
> > distros
> > we support still hasn't the version we need packaged and we are
> > already removing it?
> > 
> > Christophe already mentioned that we should have not bumped Meson
> > requirements that much.
> > 
> > Keep it in some branch but for the moment I would say no.
> 
> Given that some pretty conservative core desktop projects (including
> mesa, glib, gtk+) have already made the move upstream, I think it's
> the right time for spice-gtk too.
> 
> The question is which distro we want to support with upstream and
> upcoming versions. I would say we should target current Fedora
> release.
> 
> Anything else can be backported to previous releases, and we can
> maintain older version branches upstream.
> 
> 

I do not always update my laptop to the latest release immediately. For
example, I'm still running Fedora 28 on my laptop at the moment, which
as far as I know does not have a new enough version of meson to build
git master. 'Backporting' doesn't solve that problem.

Jonathon

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v4 1/9] Add lookup_xrand_output_for_device_info()

2019-01-17 Thread Jonathon Jongsma
Add a function to look up an xrandr output for a given device display
id. This uses sysfs and the drm subsystem to lookup information about a
graphics device output. It then compares the drm output name to xrandr
output names to try to match that device output to an xrandr output.
This is necesary for guests that have multiple graphics devices.
---
 Makefile.am   |  14 ++
 configure.ac  |   1 +
 src/vdagent/device-info.c | 499 ++
 src/vdagent/device-info.h |  27 +++
 tests/test-device-info.c  | 262 
 5 files changed, 803 insertions(+)
 create mode 100644 src/vdagent/device-info.c
 create mode 100644 src/vdagent/device-info.h
 create mode 100644 tests/test-device-info.c

diff --git a/Makefile.am b/Makefile.am
index 97b8bf0..c2e9668 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -14,6 +14,7 @@ common_sources =  \
$(NULL)
 
 src_spice_vdagent_CFLAGS = \
+   $(DRM_CFLAGS)   \
$(X_CFLAGS) \
$(SPICE_CFLAGS) \
$(GLIB2_CFLAGS) \
@@ -24,6 +25,7 @@ src_spice_vdagent_CFLAGS =\
$(NULL)
 
 src_spice_vdagent_LDADD =  \
+   $(DRM_LIBS) \
$(X_LIBS)   \
$(SPICE_LIBS)   \
$(GLIB2_LIBS)   \
@@ -37,6 +39,8 @@ src_spice_vdagent_SOURCES =   \
src/vdagent/audio.h \
src/vdagent/clipboard.c \
src/vdagent/clipboard.h \
+   src/vdagent/device-info.c   \
+   src/vdagent/device-info.h   \
src/vdagent/file-xfers.c\
src/vdagent/file-xfers.h\
src/vdagent/x11-priv.h  \
@@ -159,3 +163,13 @@ EXTRA_DIST =   \
 DISTCHECK_CONFIGURE_FLAGS =\
--with-init-script=redhat   \
$(NULL)
+
+tests_test_device_info_LDADD = $(src_spice_vdagent_LDADD)
+tests_test_device_info_CFLAGS = $(src_spice_vdagent_CFLAGS)
+
+check_PROGRAMS =   \
+   tests/test-device-info  \
+   $(NULL)
+
+TESTS = $(check_PROGRAMS)
+
diff --git a/configure.ac b/configure.ac
index 7cb44db..55b031e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -105,6 +105,7 @@ PKG_CHECK_MODULES(X, [xfixes xrandr >= 1.3 xinerama x11])
 PKG_CHECK_MODULES(SPICE, [spice-protocol >= 0.12.13])
 PKG_CHECK_MODULES(ALSA, [alsa >= 1.0.22])
 PKG_CHECK_MODULES([DBUS], [dbus-1])
+PKG_CHECK_MODULES([DRM], [libdrm])
 
 if test "$with_session_info" = "auto" || test "$with_session_info" = 
"systemd"; then
 PKG_CHECK_MODULES([LIBSYSTEMD_LOGIN],
diff --git a/src/vdagent/device-info.c b/src/vdagent/device-info.c
new file mode 100644
index 000..09ba579
--- /dev/null
+++ b/src/vdagent/device-info.c
@@ -0,0 +1,499 @@
+/*  device-info.c utility function for looking up the xrandr output id for a
+ *  given device address and display id
+ *
+ * Copyright 2018 Red Hat, Inc.
+ *
+ * Red Hat Authors:
+ * Jonathon Jongsma 
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "device-info.h"
+
+#define PCI_VENDOR_ID_REDHAT 0x1b36
+#define PCI_VENDOR_ID_REDHAT_QUMRANET 0x1af4 // virtio-gpu
+#define PCI_VENDOR_ID_INTEL 0x8086
+#define PCI_VENDOR_ID_NVIDIA 0x10de
+
+#define PCI_DEVICE_ID_QXL 0x0100
+#define PCI_DEVICE_ID_VIRTIO_GPU 0x1050
+
+typedef struct PciDevice {
+int domain;
+uint8_t bus;
+uint8_t slot;
+uint8_t function;
+} PciDevice;
+
+typedef struct PciAddress {
+int domain;
+GList *devices; /* PciDevice */
+} PciAddress;
+
+static PciAddress* pci_address_new()
+{
+return g_new0(PciAddress, 1);
+}
+
+static void pci_address_free(PciAddress *addr)
+{
+g_list_free_full(addr->devices, g_free);
+g_free(addr);
+}
+
+
+static int read_next_hex_number(const char *input, char delim, char

[Spice-devel] [PATCH linux vdagent v4 6/9] Use new function in vdagent_x11_send_daemon_guest_xorg_res()

2019-01-17 Thread Jonathon Jongsma
Rather than getting the current guest resolution in a
VDAgentMonitorsConfig struct and then translating it to a new struct
type for sending down to the daemon, simply use the new function that
was factored out in a previous commit and populate the message struct
directly.
---
 src/vdagent/x11-randr.c | 20 
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 05a001e..f3972c8 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -1066,25 +1066,21 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 int i, width = 0, height = 0, screen_count = 0;
 
 if (x11->has_xrandr) {
-VDAgentMonitorsConfig *curr;
-
 if (update)
 update_randr_res(x11, 0);
 
-curr = get_current_mon_config(x11);
-if (!curr)
-goto no_info;
-
-screen_count = curr->num_of_monitors;
+screen_count = x11->randr.res->noutput;
 res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
 
 for (i = 0; i < screen_count; i++) {
-res[i].width  = curr->monitors[i].width;
-res[i].height = curr->monitors[i].height;
-res[i].x = curr->monitors[i].x;
-res[i].y = curr->monitors[i].y;
+struct vdagentd_guest_xorg_resolution *curr = [i];
+if (!get_monitor_info_for_output_index(x11, i, >x, >y,
+   >width, >height)
+{
+g_free(res);
+goto no_info;
+}
 }
-g_free(curr);
 width  = x11->width[0];
 height = x11->height[0];
 } else if (x11->has_xinerama) {
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v4 3/9] Make clearer distinctions between output ids

2019-01-17 Thread Jonathon Jongsma
There are basically three ways to refer to an output within vdagent:
  - The index of the array of MonitorConfig message. This is essentially
a "spice display id"
  - the index of the array of xrandr outputs. This is the "output index"
  - the xrandr output id. This is the "output ID"

Previously, the "spice display id" and the "output index" were treated
as synonymous. But in order to support more complciated setups with
multiple display devices, etc, we need to differentiate these ideas more
clearly. This patch simply renames some variables and a function so that
we can tell more easily which one of these concepts we are dealing with.

Acked-by: Lukáš Hrázký 
---
 src/vdagent/x11-randr.c | 50 -
 1 file changed, 25 insertions(+), 25 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index e65d8d0..10a1325 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -188,14 +188,14 @@ find_mode_by_name (struct vdagent_x11 *x11, char *name)
 }
 
 static XRRModeInfo *
-find_mode_by_size (struct vdagent_x11 *x11, int output, int width, int height)
+find_mode_by_size (struct vdagent_x11 *x11, int output_index, int width, int 
height)
 {
 intm;
 XRRModeInfo*ret = NULL;
 
-for (m = 0; m < x11->randr.outputs[output]->nmode; m++) {
+for (m = 0; m < x11->randr.outputs[output_index]->nmode; m++) {
 XRRModeInfo *mode = mode_from_id(x11,
- x11->randr.outputs[output]->modes[m]);
+ 
x11->randr.outputs[output_index]->modes[m]);
 if (mode && mode->width == width && mode->height == height) {
 ret = mode;
 break;
@@ -342,7 +342,7 @@ static XRRModeInfo *create_new_mode(struct vdagent_x11 
*x11, int output_index,
 return find_mode_by_name(x11, modename);
 }
 
-static int xrandr_add_and_set(struct vdagent_x11 *x11, int output, int x, int 
y,
+static int xrandr_add_and_set(struct vdagent_x11 *x11, int output_index, int 
x, int y,
   int width, int height)
 {
 XRRModeInfo *mode;
@@ -357,33 +357,33 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, 
int output, int x, int y,
 return 0;
 }
 
-if (output < 0 || output >= x11->randr.res->noutput) {
+if (output_index < 0 || output_index >= x11->randr.res->noutput) {
 syslog(LOG_ERR, "%s: program error: bad output", __FUNCTION__);
 return 0;
 }
 
-old_width  = x11->randr.monitor_sizes[output].width;
-old_height = x11->randr.monitor_sizes[output].height;
+old_width  = x11->randr.monitor_sizes[output_index].width;
+old_height = x11->randr.monitor_sizes[output_index].height;
 
 if (x11->set_crtc_config_not_functional) {
 /* fail, set_best_mode will find something close. */
 return 0;
 }
-xid = x11->randr.res->outputs[output];
-mode = find_mode_by_size(x11, output, width, height);
+xid = x11->randr.res->outputs[output_index];
+mode = find_mode_by_size(x11, output_index, width, height);
 if (!mode) {
-mode = create_new_mode(x11, output, width, height);
+mode = create_new_mode(x11, output_index, width, height);
 }
 if (!mode) {
 syslog(LOG_ERR, "failed to add a new mode");
 return 0;
 }
 XRRAddOutputMode(x11->display, xid, mode->id);
-x11->randr.monitor_sizes[output].width = width;
-x11->randr.monitor_sizes[output].height = height;
+x11->randr.monitor_sizes[output_index].width = width;
+x11->randr.monitor_sizes[output_index].height = height;
 outputs[0] = xid;
 vdagent_x11_set_error_handler(x11, ignore_error_handler);
-s = XRRSetCrtcConfig(x11->display, x11->randr.res, 
x11->randr.res->crtcs[output],
+s = XRRSetCrtcConfig(x11->display, x11->randr.res, 
x11->randr.res->crtcs[output_index],
  CurrentTime, x, y, mode->id, RR_Rotate_0, outputs,
  1);
 if (vdagent_x11_restore_error_handler(x11) || (s != RRSetConfigSuccess)) {
@@ -394,24 +394,24 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, 
int output, int x, int y,
 
 /* clean the previous name, if any */
 if (width != old_width || height != old_height)
-delete_mode(x11, output, old_width, old_height);
+delete_mode(x11, output_index, old_width, old_height);
 
 return 1;
 }
 
-static void xrandr_disable_output(struct vdagent_x11 *x11, int output)
+static void xrandr_disable_nth_output(struct vdagent_x11 *x11, int 
output_index)
 {
 Status s;
 
-if (!x11->randr.res || output >= x11->randr.res->noutput || output < 0) {
+if (!x11->randr.res || output_index >= x11->randr.res->noutput || 
output_index < 0) {
 syslog(LOG_ERR, "%s: program error: missing RANDR or bad output",
__FUNCTION__);
 return;
 }
 
-XRROutputInfo *oinfo = x11->randr.outputs[output];
+ 

[Spice-devel] [PATCH linux vdagent v4 5/9] Factor a function out of get_current_mon_config()

2019-01-17 Thread Jonathon Jongsma
When sending the guest xorg resolution to the vdagentd daemon, we get
the current resolution with this function, which returns a
VDAgentMonitorsConfig structure that must then be converted to the
structure that we send to the daemon. Rather than re-using this function
that returns the wrong type, factor out most of the functionality into a
separate function. This function can be used by a new function to return
a type appropriate for sending the xorg resolution to the daemon.

This is necessary because in the next few commits I'll be changing the
vdagentd protocol to send an additional display_id parameter to the
daemon.
---
 src/vdagent/x11-randr.c | 73 +
 1 file changed, 52 insertions(+), 21 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 5eff225..05a001e 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -688,38 +688,69 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
+
+// gets monitor information about the specified output index and returns true 
if there was no error
+static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index, int *x, int *y, int *width, int *height)
+{
+g_return_val_if_fail (output_index < x11->randr.res->noutput, false);
+g_return_val_if_fail (x != NULL, false);
+g_return_val_if_fail (y != NULL, false);
+g_return_val_if_fail (width != NULL, false);
+g_return_val_if_fail (height != NULL, false);
+
+int j;
+XRRCrtcInfo *crtc = NULL;
+XRRModeInfo *mode;
+
+if (x11->randr.outputs[output_index]->ncrtc == 0)
+goto zeroed; /* Monitor disabled */
+
+for (j = 0; crtc == NULL && j < x11->randr.outputs[output_index]->ncrtc; 
j++) {
+crtc = crtc_from_id(x11, x11->randr.outputs[output_index]->crtcs[j]);
+}
+if (!crtc) {
+// error. stale xrandr info?
+return false;
+}
+
+mode = mode_from_id(x11, crtc->mode);
+if (!mode)
+goto zeroed; /* monitor disabled */
+
+*x = crtc->x;
+*y = crtc->y;
+*width = mode->width;
+*height = mode->height;
+return true;
+
+zeroed:
+*x = 0;
+*y = 0;
+*width = 0;
+*height = 0;
+return true;
+}
+
 static VDAgentMonitorsConfig *get_current_mon_config(struct vdagent_x11 *x11)
 {
 int i, num_of_monitors = 0;
-XRRModeInfo *mode;
 XRRScreenResources *res = x11->randr.res;
 VDAgentMonitorsConfig *mon_config;
 
 mon_config = g_malloc0(config_size(res->noutput));
 
 for (i = 0 ; i < res->noutput; i++) {
-int j;
-XRRCrtcInfo *crtc = NULL;
-
-if (x11->randr.outputs[i]->ncrtc == 0)
-continue; /* Monitor disabled, already zero-ed by calloc */
-if (x11->randr.outputs[i]->crtc == 0)
-continue; /* Monitor disabled */
-
-for (j = 0; crtc == NULL && j < x11->randr.outputs[i]->ncrtc; j++) {
-crtc = crtc_from_id(x11, x11->randr.outputs[i]->crtcs[j]);
-}
-if (!crtc)
+int x, y, width, height;
+if (!get_monitor_info_for_output_index(x11, i, , , , 
)) {
+syslog(LOG_WARNING, "Unable to get monitor info for output id %d", 
i);
 goto error;
+}
 
-mode = mode_from_id(x11, crtc->mode);
-if (!mode)
-continue; /* Monitor disabled, already zero-ed by calloc */
-
-mon_config->monitors[i].x  = crtc->x;
-mon_config->monitors[i].y  = crtc->y;
-mon_config->monitors[i].width  = mode->width;
-mon_config->monitors[i].height = mode->height;
+VDAgentMonConfig *mon = _config->monitors[i];
+mon->x = x;
+mon->y = y;
+mon->width = width;
+mon->height = height;
 num_of_monitors = i + 1;
 }
 mon_config->num_of_monitors = num_of_monitors;
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v4 7/9] Send display_id down to the vdagentd daemon

2019-01-17 Thread Jonathon Jongsma
Add a display_id field to the structure that we use to send down the
list of guest display resolutions to the vdagentd daemon. This allows us
to map the spice display id to the proper X display for determining
mouse locations, etc.
---
 src/vdagent/x11-randr.c | 35 ---
 src/vdagentd-proto.h|  1 +
 src/vdagentd/uinput.c   | 23 ++-
 3 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index f3972c8..5749ae7 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -688,6 +688,34 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
+static int get_display_id_for_output_index(struct vdagent_x11 *x11, int 
output_index)
+{
+// invalid output index
+if (output_index >= x11->randr.res->noutput) {
+syslog(LOG_WARNING, "Invalid output index %d (>%d)", output_index, 
x11->randr.res->noutput);
+return -1;
+}
+
+if (g_hash_table_size(x11->guest_output_map) == 0) {
+syslog(LOG_DEBUG, "No guest output map, using output index as display 
id");
+return output_index;
+}
+
+int display_id = -1;
+RROutput output_id = x11->randr.res->outputs[output_index];
+GHashTableIter iter;
+gpointer key, value;
+g_hash_table_iter_init(, x11->guest_output_map);
+while (g_hash_table_iter_next(, , )) {
+gint64 *other_id = value;
+if (*other_id == output_id) {
+return GPOINTER_TO_INT(key);
+}
+}
+
+syslog(LOG_WARNING, "Unable to find a display id for output index %d)", 
output_index);
+return display_id;
+}
 
 // gets monitor information about the specified output index and returns true 
if there was no error
 static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index, int *x, int *y, int *width, int *height)
@@ -1075,11 +1103,12 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 for (i = 0; i < screen_count; i++) {
 struct vdagentd_guest_xorg_resolution *curr = [i];
 if (!get_monitor_info_for_output_index(x11, i, >x, >y,
-   >width, >height)
+   >width, 
>height))
 {
 g_free(res);
 goto no_info;
 }
+curr->display_id = get_display_id_for_output_index(x11, i);
 }
 width  = x11->width[0];
 height = x11->height[0];
@@ -1131,8 +1160,8 @@ no_info:
 if (x11->debug) {
 syslog(LOG_DEBUG, "Sending guest screen resolutions to vdagentd:");
 for (i = 0; i < screen_count; i++) {
-syslog(LOG_DEBUG, "   screen %d %dx%d%+d%+d", i,
-   res[i].width, res[i].height, res[i].x, res[i].y);
+syslog(LOG_DEBUG, "   screen %d %dx%d%+d%+d, id=%d", i,
+   res[i].width, res[i].height, res[i].x, res[i].y, 
res[i].display_id);
 }
 }
 
diff --git a/src/vdagentd-proto.h b/src/vdagentd-proto.h
index 243a9c6..7eff71d 100644
--- a/src/vdagentd-proto.h
+++ b/src/vdagentd-proto.h
@@ -53,6 +53,7 @@ struct vdagentd_guest_xorg_resolution {
 int height;
 int x;
 int y;
+int display_id;
 };
 
 #endif
diff --git a/src/vdagentd/uinput.c b/src/vdagentd/uinput.c
index 4f854bf..ff37e1e 100644
--- a/src/vdagentd/uinput.c
+++ b/src/vdagentd/uinput.c
@@ -175,6 +175,18 @@ static void uinput_send_event(struct vdagentd_uinput 
**uinputp,
 }
 }
 
+static struct vdagentd_guest_xorg_resolution* lookup_screen_info(struct 
vdagentd_uinput *uinput, int display_id)
+{
+int i;
+for (i = 0; i < uinput->screen_count; i++) {
+if (uinput->screen_info[i].display_id == display_id) {
+return >screen_info[i];
+}
+}
+syslog(LOG_WARNING, "Unable to find output index for display id %d", 
display_id);
+return NULL;
+}
+
 void vdagentd_uinput_do_mouse(struct vdagentd_uinput **uinputp,
 VDAgentMouseState *mouse)
 {
@@ -196,16 +208,17 @@ void vdagentd_uinput_do_mouse(struct vdagentd_uinput 
**uinputp,
 int i, down;
 
 if (*uinputp) {
-if (mouse->display_id >= uinput->screen_count) {
-syslog(LOG_WARNING, "mouse event for unknown monitor (%d >= %d)",
-   mouse->display_id, uinput->screen_count);
+struct vdagentd_guest_xorg_resolution *screen_info = 
lookup_screen_info(uinput, mouse->display_id);
+if (screen_info == NULL) {
+syslog(LOG_WARNING, "mouse event for unknown monitor %d",
+   mouse->display_id);
 return;
 }
 if (uinput->debug)
 syslog(LOG_DEBUG, "mouse-event: mon %d %dx%d", mouse->display_id,
mouse->x, mouse->y);
-mouse->x += uinput->screen_info[mouse->display_id].x;
-mouse->y += 

[Spice-devel] [PATCH linux vdagent v4 8/9] Send display IDs to daemon when device info changes

2019-01-17 Thread Jonathon Jongsma
When the agent gets a new device info message (from the daemon), we need
to re-calculate the guest output map and send that information back down
to the daemon so that it can handle mouse input events correctly.
---
 src/vdagent/x11-randr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 5749ae7..283dbc8 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -865,6 +865,9 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
 sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
 }
+
+// make sure daemon is up-to-date with (possibly updated) device IDs
+vdagent_x11_send_daemon_guest_xorg_res(x11, 1);
 }
 
 static int get_output_index_for_display_id(struct vdagent_x11 *x11, int 
display_id)
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v4 0/9] Use the PCI addr and display ID

2019-01-17 Thread Jonathon Jongsma
This is a patch set that handles the PCI address and device dispay ID
sent down to the agent by the server, and uses that to maintain a map
for looking up a particular xrandr output for a given spice display id.

This patch series builds on the patch from Lukas titled "Receive the
graphics_device_info message". 

Changes in v4:
 - rebased on Lukas's latest patch
 - Added a new commit that fixes the cursor when using with mjpeg streaming.
 - various small fixes from previous reviews (e.g. line length, etc)

Changes in v3:
 - Fixed a bug where the X Display was not set properly and caused a
   crash
 - moved call to vdagent_x11_send_daemon_guest_xorg_res() to outside the
   loop to avoid sending multiple times when more than one device is
   received. (Patch 9)

Changes in v2:
 - Removed some ACKed and merged patches
   - Fix typo in comment
   - Fix confusion between output index and crtc index
 - added a patch to send new display IDs when device info changes
 - multiple changes from review
   - factored out function find_device_at_pci_address()
   - No more initializing X/XRandr
   - removed goto
   - improved logging
   - etc.

Jonathon Jongsma (9):
  Add lookup_xrand_output_for_device_info()
  Look up and store xrandr output in display map
  Make clearer distinctions between output ids
  Use guest output map to determine xrandr output
  Factor a function out of get_current_mon_config()
  Use new function in vdagent_x11_send_daemon_guest_xorg_res()
  Send display_id down to the vdagentd daemon
  Send display IDs to daemon when device info changes
  Make cursor work with mjpeg streaming

 Makefile.am   |  14 ++
 configure.ac  |   1 +
 src/vdagent/device-info.c | 499 ++
 src/vdagent/device-info.h |  27 +++
 src/vdagent/x11-priv.h|   2 +-
 src/vdagent/x11-randr.c   | 340 +-
 src/vdagent/x11.c |  20 +-
 src/vdagentd-proto.h  |   1 +
 src/vdagentd/uinput.c |  23 +-
 tests/test-device-info.c  | 262 
 10 files changed, 1057 insertions(+), 132 deletions(-)
 create mode 100644 src/vdagent/device-info.c
 create mode 100644 src/vdagent/device-info.h
 create mode 100644 tests/test-device-info.c

-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v4 2/9] Look up and store xrandr output in display map

2019-01-17 Thread Jonathon Jongsma
Instead of storing each device address and device display ID in the hash
table, simply use the lookup_xrandr_output_for_device_info() function to
look up the ID of the xrandr output and store that in the hash table.
---
 src/vdagent/x11-priv.h  |  2 +-
 src/vdagent/x11-randr.c | 53 +++--
 src/vdagent/x11.c   | 20 ++--
 3 files changed, 32 insertions(+), 43 deletions(-)

diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index 0e954cf..e487aa2 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,7 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
-GHashTable *graphics_display_infos;
+GHashTable *guest_output_map;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 405fca9..e65d8d0 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -31,6 +31,7 @@
 
 #include 
 
+#include "device-info.h"
 #include "vdagentd-proto.h"
 #include "x11.h"
 #include "x11-priv.h"
@@ -727,11 +728,6 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
-typedef struct GraphicsDisplayInfo {
-char device_address[256];
-uint32_t device_display_id;
-} GraphicsDisplayInfo;
-
 // handle the device info message from the server. This will allow us to
 // maintain a mapping from spice display id to xrandr output
 void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
@@ -752,39 +748,38 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 break;
 }
 
-GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
-value->device_address[0] = '\0';
-
-size_t device_address_len = device_display_info->device_address_len;
-if (device_address_len > sizeof(value->device_address)) {
-syslog(LOG_ERR, "Received a device address longer than %lu, "
-   "will be truncated!", device_address_len);
-device_address_len = sizeof(value->device_address);
-}
-
-strncpy(value->device_address,
-(char*) device_display_info->device_address,
-device_address_len);
-
-if (device_address_len > 0) {
-value->device_address[device_address_len - 1] = '\0';  // make 
sure the string is terminated
+// make sure the string is terminated:
+if (device_display_info->device_address_len > 0) {
+
device_display_info->device_address[device_display_info->device_address_len - 
1] = '\0';
 } else {
 syslog(LOG_WARNING, "Zero length device_address received for 
channel_id: %u, monitor_id: %u",
device_display_info->channel_id, 
device_display_info->monitor_id);
 }
 
-value->device_display_id = device_display_info->device_display_id;
+RROutput x_output;
+if (lookup_xrandr_output_for_device_info(device_display_info, 
x11->display, x11->randr.res, _output)) {
+gint64 *value = g_new(gint64, 1);
+*value = x_output;
 
-syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
-   "device_display_id: %u",
-   device_display_info->channel_id,
-   device_display_info->monitor_id,
-   value->device_address,
-   value->device_display_id);
+syslog(LOG_INFO, "channel_id: %u monitor_id: %u device_address: 
%s, "
+   "device_display_id: %u xrandr output ID: %lu",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   device_display_info->device_address,
+   device_display_info->device_display_id,
+   x_output);
 
-g_hash_table_insert(x11->graphics_display_infos,
+g_hash_table_insert(x11->guest_output_map,
 GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
 value);
+} else {
+syslog(LOG_INFO, "channel_id: %u monitor_id: %u device_address: 
%s, "
+   "device_display_id: %u xrandr output ID NOT FOUND",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   device_display_info->device_address,
+   device_display_info->device_display_id);
+}
 
 device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
 sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index ab822f8..484be5e 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -196,12 +196,6 @@ static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 
*x11)
 

[Spice-devel] [PATCH linux vdagent v4 4/9] Use guest output map to determine xrandr output

2019-01-17 Thread Jonathon Jongsma
instead of using the spice display id directly as the xrandr output,
look it up using our new guest output map
---
 src/vdagent/x11-randr.c | 78 -
 1 file changed, 69 insertions(+), 9 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 10a1325..5eff225 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -399,6 +399,28 @@ static int xrandr_add_and_set(struct vdagent_x11 *x11, int 
output_index, int x,
 return 1;
 }
 
+// Looks up the xrandr output id associated with the given spice display id
+static RROutput get_xrandr_output_for_display_id(struct vdagent_x11 *x11, int 
display_id)
+{
+guint map_size = g_hash_table_size(x11->guest_output_map);
+if (map_size == 0) {
+// we never got a device info message from the server, so just use old
+// assumptions that the spice display id is equal to the index into the
+// array of xrandr outputs
+if (display_id < x11->randr.res->noutput) {
+return x11->randr.res->outputs[display_id];
+}
+} else {
+gpointer value;
+if (g_hash_table_lookup_extended(x11->guest_output_map, 
GINT_TO_POINTER(display_id), NULL, )) {
+return *(gint64*)value;
+}
+}
+
+// unable to find a valid output id
+return -1;
+}
+
 static void xrandr_disable_nth_output(struct vdagent_x11 *x11, int 
output_index)
 {
 Status s;
@@ -786,6 +808,16 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 }
 }
 
+static int get_output_index_for_display_id(struct vdagent_x11 *x11, int 
display_id)
+{
+RROutput oid = get_xrandr_output_for_display_id(x11, display_id);
+for (int i = 0; i < x11->randr.res->noutput; i++) {
+if (oid == x11->randr.res->outputs[i]) {
+return i;
+}
+}
+return -1;
+}
 
 /*
  * Set monitor configuration according to client request.
@@ -862,13 +894,32 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
*x11,
 g_unlink(config);
 g_free(config);
 
-for (i = mon_config->num_of_monitors; i < x11->randr.res->noutput; i++)
-xrandr_disable_nth_output(x11, i);
+// disable all outputs that don't have associated entries in the 
MonitorConfig
+for (i = 0; i < x11->randr.res->noutput; i++) {
+bool disable = true;
+// check if this xrandr output is represented by an item in mon_config
+for (int j = 0; j < mon_config->num_of_monitors; j++) {
+// j represents the display id of an enabled monitor. Check whether
+// an enabled xrandr output is represented by this id.
+RROutput oid = get_xrandr_output_for_display_id(x11, j);
+if (oid == x11->randr.res->outputs[i]) {
+disable = false;
+}
+}
+if (disable) {
+xrandr_disable_nth_output(x11, i);
+}
+}
 
-/* First, disable disabled CRTCs... */
+/* disable CRTCs that are present but explicitly disabled in the
+ * MonitorConfig */
 for (i = 0; i < mon_config->num_of_monitors; ++i) {
 if (!monitor_enabled(_config->monitors[i])) {
-xrandr_disable_nth_output(x11, i);
+int output_index = get_output_index_for_display_id(x11, i);
+if (output_index != -1)
+xrandr_disable_nth_output(x11, output_index);
+else
+syslog(LOG_WARNING, "Unable to find a guest output index for 
spice display %i", i);
 }
 }
 
@@ -891,7 +942,11 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
*x11,
 syslog(LOG_DEBUG, "Disabling monitor %d: %dx%d+%d+%d > 
(%d,%d)",
i, width, height, x, y, primary_w, primary_h);
 
-xrandr_disable_nth_output(x11, i);
+int output_index = get_output_index_for_display_id(x11, i);
+if (output_index != -1)
+xrandr_disable_nth_output(x11, output_index);
+else
+syslog(LOG_WARNING, "Unable to find a guest output index for 
spice display %i", i);
 }
 }
 
@@ -943,11 +998,16 @@ void vdagent_x11_set_monitor_config(struct vdagent_x11 
*x11,
i, width, height, x, y);
 }
 
-if (!xrandr_add_and_set(x11, i, x, y, width, height) &&
+int output_index = get_output_index_for_display_id(x11, i);
+if (output_index != -1) {
+if (!xrandr_add_and_set(x11, output_index, x, y, width, height) &&
 enabled_monitors(mon_config) == 1) {
-set_screen_to_best_size(x11, width, height,
-_w, _h);
-break;
+set_screen_to_best_size(x11, width, height,
+_w, _h);
+break;
+}
+} else {
+syslog(LOG_WARNING, "Unable to find a guest output index for spice 
display %i", 

[Spice-devel] [PATCH linux vdagent v4 9/9] Make cursor work with mjpeg streaming

2019-01-17 Thread Jonathon Jongsma
In the case where we have an mjpeg plugin running in the streaming
agent, we have two spice displays representing the same guest display.
In that scenario, the session agent may maintain the following guest
output mapping:
 spice channel 0 (QXL) => X output 0
 spice channel 1 (streaming-agent) => X output 0

While this is not necessarily a supported scenario, it would be nice if
the cursor input worked properly in this case. The root problem is that
when the session agent sends down the guest xorg resolutions to the
system daemon, it simply loops through the list of xorg displays, and
for each X display it looks up the first spice display ID associated
with it and sends that down to the daemon. In the scenario mentioned
above, since there is only a single X display configured (albeit
represented by two different spice displays), we would send down a
single display resolution to the system daemon:
 - { width=1280, height=1024, x=0, y=0, display_id=0 }

Notice that there is no entry for display_id=1. When the agent receives
a cursor input message for display channel 1, that message will get
passed to the systemn daemon, which will attempt to look up display_id 1
in order to convert the event coordinates to global coordinates. Finding
no entry for display_id=1, the mouse events do not work.

In this patch, when we want to send the guest resolutions down to the
system daemon, we still loop through the list of X outputs, but for each
output we also loop through the guest output mapping table and send a
resolution structure down to the daemon for each registered output
mapping.  This means that in the previously mentioned scenario, we would
send down the following information:
 - { width=1280, height=1024, x=0, y=0, display_id=0 }
 - { width=1280, height=1024, x=0, y=0, display_id=1 }

 This means that when the client sends a mouse event for display_id=1,
 the system daemon knows the coordinates of the guest display associated
 with that ID and can process the mouse event properly.
---
 src/vdagent/x11-randr.c | 106 
 1 file changed, 53 insertions(+), 53 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 283dbc8..fe48c46 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -688,35 +688,6 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
-static int get_display_id_for_output_index(struct vdagent_x11 *x11, int 
output_index)
-{
-// invalid output index
-if (output_index >= x11->randr.res->noutput) {
-syslog(LOG_WARNING, "Invalid output index %d (>%d)", output_index, 
x11->randr.res->noutput);
-return -1;
-}
-
-if (g_hash_table_size(x11->guest_output_map) == 0) {
-syslog(LOG_DEBUG, "No guest output map, using output index as display 
id");
-return output_index;
-}
-
-int display_id = -1;
-RROutput output_id = x11->randr.res->outputs[output_index];
-GHashTableIter iter;
-gpointer key, value;
-g_hash_table_iter_init(, x11->guest_output_map);
-while (g_hash_table_iter_next(, , )) {
-gint64 *other_id = value;
-if (*other_id == output_id) {
-return GPOINTER_TO_INT(key);
-}
-}
-
-syslog(LOG_WARNING, "Unable to find a display id for output index %d)", 
output_index);
-return display_id;
-}
-
 // gets monitor information about the specified output index and returns true 
if there was no error
 static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index, int *x, int *y, int *width, int *height)
 {
@@ -1093,7 +1064,7 @@ exit:
 
 void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, int 
update)
 {
-struct vdagentd_guest_xorg_resolution *res = NULL;
+GArray *res_array = g_array_new(FALSE, FALSE, sizeof(struct 
vdagentd_guest_xorg_resolution));
 int i, width = 0, height = 0, screen_count = 0;
 
 if (x11->has_xrandr) {
@@ -1101,17 +1072,39 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 update_randr_res(x11, 0);
 
 screen_count = x11->randr.res->noutput;
-res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
 
 for (i = 0; i < screen_count; i++) {
-struct vdagentd_guest_xorg_resolution *curr = [i];
-if (!get_monitor_info_for_output_index(x11, i, >x, >y,
-   >width, 
>height))
+struct vdagentd_guest_xorg_resolution curr;
+if (!get_monitor_info_for_output_index(x11, i, , ,
+, ))
 {
-g_free(res);
+g_array_free(res_array, TRUE);
 goto no_info;
 }
-curr->display_id = get_display_id_for_output_index(x11, i);
+if (g_hash_table_size(x11->guest_output_map) == 0) {
+syslog(LOG_DEBUG, 

Re: [Spice-devel] [PATCH vd_agent 8/8 v3] Receive the graphics_device_info message

2019-01-17 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> The graphics_device_info message contains the device display ID
> information (device address and device display ID). Stores the data
> in a
> hash table in vdagent.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  src/vdagent/vdagent.c|  3 ++
>  src/vdagent/x11-priv.h   |  1 +
>  src/vdagent/x11-randr.c  | 65
> 
>  src/vdagent/x11.c| 13 
>  src/vdagent/x11.h|  1 +
>  src/vdagentd-proto-strings.h |  1 +
>  src/vdagentd-proto.h |  1 +
>  src/vdagentd/vdagentd.c  | 16 +
>  8 files changed, 101 insertions(+)
> 
> diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
> index 9642a30..aa52ee9 100644
> --- a/src/vdagent/vdagent.c
> +++ b/src/vdagent/vdagent.c
> @@ -240,6 +240,9 @@ static void daemon_read_complete(struct
> udscs_connection **connp,
>((VDAgentFileXferDataM
> essage *)data)->id);
>  }
>  break;
> +case VDAGENTD_GRAPHICS_DEVICE_INFO:
> +vdagent_x11_handle_graphics_device_info(agent->x11, data,
> header->size);
> +break;
>  case VDAGENTD_CLIENT_DISCONNECTED:
>  vdagent_clipboards_release_all(agent->clipboards);
>  if (vdagent_finalize_file_xfer(agent)) {
> diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
> index b31b0a5..0e954cf 100644
> --- a/src/vdagent/x11-priv.h
> +++ b/src/vdagent/x11-priv.h
> @@ -139,6 +139,7 @@ struct vdagent_x11 {
>  int xrandr_minor;
>  int has_xinerama;
>  int dont_send_guest_xorg_res;
> +GHashTable *graphics_display_infos;
>  };
>  
>  extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent
> *);
> diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
> index 192b888..405fca9 100644
> --- a/src/vdagent/x11-randr.c
> +++ b/src/vdagent/x11-randr.c
> @@ -727,6 +727,71 @@ static void dump_monitors_config(struct
> vdagent_x11 *x11,
>  }
>  }
>  
> +typedef struct GraphicsDisplayInfo {
> +char device_address[256];
> +uint32_t device_display_id;
> +} GraphicsDisplayInfo;
> +
> +// handle the device info message from the server. This will allow
> us to
> +// maintain a mapping from spice display id to xrandr output
> +void vdagent_x11_handle_graphics_device_info(struct vdagent_x11
> *x11, uint8_t *data, size_t size)
> +{
> +VDAgentGraphicsDeviceInfo *graphics_device_info =
> (VDAgentGraphicsDeviceInfo *)data;
> +VDAgentDeviceDisplayInfo *device_display_info =
> graphics_device_info->display_info;
> +
> +void *buffer_end = data + size;
> +
> +syslog(LOG_INFO, "Received Graphics Device Info:");
> +
> +for (size_t i = 0; i < graphics_device_info->count; ++i) {
> +if ((void*) device_display_info > buffer_end ||
> +(void*) (_display_info->device_address +
> +device_display_info->device_address_len) >
> buffer_end) {
> +syslog(LOG_ERR, "Malformed graphics_display_info
> message, "
> +   "extends beyond the end of the buffer");
> +break;
> +}
> +
> +GraphicsDisplayInfo *value =
> g_malloc(sizeof(GraphicsDisplayInfo));
> +value->device_address[0] = '\0';
> +
> +size_t device_address_len = device_display_info-
> >device_address_len;
> +if (device_address_len > sizeof(value->device_address)) {
> +syslog(LOG_ERR, "Received a device address longer than
> %lu, "
> +   "will be truncated!", device_address_len);
> +device_address_len = sizeof(value->device_address);
> +}
> +
> +strncpy(value->device_address,
> +(char*) device_display_info->device_address,
> +device_address_len);
> +
> +if (device_address_len > 0) {
> +value->device_address[device_address_len - 1] =
> '\0';  // make sure the string is terminated
> +} else {
> +syslog(LOG_WARNING, "Zero length device_address received
> for channel_id: %u, monitor_id: %u",
> +   device_display_info->channel_id,
> device_display_info->monitor_id);
> +}
> +
> +value->device_display_id = device_display_info-
> >device_display_id;
> +
> +syslog(LOG_INFO, "   channel_id: %u monitor_id: %u
> device_address: %s, "
> +   "device_display_id: %u",
> +   device_display_i

Re: [Spice-devel] [PATCH spice-streaming-agent 6/8 v3] Interface + implementation of getting device display info

2019-01-17 Thread Jonathon Jongsma
rm_fd);
> +throw Error(std::string("Unable to get DRM resources for
> card ") + card_path);
> +}
> +}
> +
> +~DrmOutputGetter()
> +{
> +drmModeFreeResources(drm_resources);
> +close(drm_fd);
> +}
> +
> +std::vector get_output_names(const
> std::map _map,
> +  bool decrement =
> false)
> +{
> +std::vector result;
> +
> +for (size_t i = 0; i < drm_resources->count_connectors; ++i)
> {
> +drmModeConnectorPtr conn = drmModeGetConnector(drm_fd,
> drm_resources->connectors[i]);
> +
> +if (conn == nullptr) {
> +throw Error(std::string("Unable to get DRM
> connector: ") + strerror(errno));
> +}
> +
> +uint32_t cti = conn->connector_type_id;
> +if (decrement) {
> +cti--;
> +}
> +result.push_back(get_drm_name(names_map, conn-
> >connector_type, cti));
> +}
> +
> +return result;
> +}
> +
> +private:
> +int drm_fd = -1;
> +drmModeResPtr drm_resources = nullptr;
> +};
> +
> +std::vector get_outputs()
> +{
> +std::vector result;
> +
> +for (uint8_t card_id = 0; card_id < 10; ++card_id) {
> +std::string card_name = "card" + std::to_string(card_id);
> +
> +char drm_path[64];
> +snprintf(drm_path, sizeof(drm_path), DRM_DEV_NAME,
> DRM_DIR_NAME, card_id);
> +
> +struct stat stat_buf;
> +if (stat(drm_path, _buf) != 0) {
> +if (errno == ENOENT) {
> +// we're done searching
> +break;
> +}
> +throw Error(std::string("Error accessing DRM node for
> card ") + drm_path);
> +}
> +
> +std::string sys_path = "/sys/class/drm/" + card_name;
> +
> +uint32_t vendor_id = read_hex_number_from_file(sys_path +
> "/device/vendor");
> +uint32_t device_id = read_hex_number_from_file(sys_path +
> "/device/device");
> +
> +std::vector outputs;
> +
> +if (vendor_id == pci_vendor_id_redhat && device_id ==
> pci_device_id_qxl) {
> +// to find out whether QXL output names need
> decrementing, look for
> +// an output called Virtual-0 in /sys/class/drm and if
> we find one,
> +// decrement the number in the output names
> +const auto globs = utils::glob("/sys/class/drm/card*-
> Virtual-0");
> +outputs =
> DrmOutputGetter(drm_path).get_output_names(qxl_output_names,
> globs.size() > 0);
> +} else {
> +outputs =
> DrmOutputGetter(drm_path).get_output_names(modesetting_output_names);
> +}
> +
> +for (uint32_t i = 0; i < outputs.size(); ++i) {
> +result.push_back({outputs[i],
> +  sys_path,
> +  vendor_id,
> +  device_id,
> +  i});
> +}
> +}
> +
> +return result;
> +}
> +
> +} // namespace
> +
> +std::vector get_xrandr_outputs(Display *display, Window
> window)
> +{
> +XRRScreenResources *screen_resources =
> XRRGetScreenResources(display, window);
> +std::vector result;
> +for (int i = 0; i < screen_resources->noutput; ++i) {
> +XRROutputInfo *output_info = XRRGetOutputInfo(display,
> +  screen_resourc
> es,
> +  screen_resourc
> es->outputs[i]);
> +
> +result.emplace_back(output_info->name);
> +
> +XRRFreeOutputInfo(output_info);
> +}
> +
> +XRRFreeScreenResources(screen_resources);
> +return result;
> +}
> +
> +std::vector get_device_display_info_drm(Display
> *display)
> +{
> +auto outputs = get_outputs();
> +
> +// sorting by output name, may not be necessary (the list should
> be sorted out of glob)
> +std::sort(outputs.begin(), outputs.end(), [](const OutputInfo
> , const OutputInfo ) {
> +return oi1.output_name > oi2.output_name;
> +}
> +);
> +
> +// Check if the output names of QXL cards start at Virtual-1 and
> if so,
> +// subtract one from each of them
> +for (auto  : outputs) {
> +// if we find a QXL card
> +if (output.card_vendor_id == pci_vendor_id_redhat &&
> +output.card_device_id == pci_device_id_qxl)
> +{
> +// if the first name is Virtual-0, we know we are good,
> quit the loop
> +if (output.output_name == "Virtual-0") {
> +break;
> +}
> +
> +// if the name starts with "Virtual-"
> +if (!output.output_name.compare(0, 8, "Virtual-")) {

I strongly prefer "foo.compare() == 0" over "!foo.compare()"

> +// decrement the last digit by one
> +// fails if the number at the end is more than one
> digit,
> +// which would imply multiple QXL devices, an
> unsupported case
> +output.output_name[output.output_name.length() - 1]-
> -;
> +}
> +}
> +}
> +
> +std::map output_map;
> +for (const auto  : outputs) {
> +output_map[output.output_name] = output;
> +}
> +
> +auto xrandr_outputs = get_xrandr_outputs(display,
> RootWindow(display, XDefaultScreen(display)));
> +
> +std::vector result;
> +
> +for (uint32_t i = 0; i < xrandr_outputs.size(); ++i) {
> +const auto  = xrandr_outputs[i];

Since you have variables named 'outputs' and 'xrandr_outputs' in this
function, I'd personally prefer to name this variable something like
'xoutput' instead of simply 'output' for clarity. 

> +const auto it = output_map.find(output);
> +if (it == output_map.end()) {
> +throw Error("Could not find card for output " + output);
> +}
> +
> +std::string device_address = get_device_address(it-
> >second.card_path);
> +
> +result.push_back({i, device_address, it-
> >second.device_display_id});
> +}
> +
> +return result;
> +}
> +
> +std::vector
> get_device_display_info_no_drm(Display *display)
> +{
> +// look for the first card that doesn't list its outputs (and
> therefore
> +// doesn't support DRM), that's the best we can do...
> +const auto globs = utils::glob("/sys/class/drm/card*");
> +
> +std::string found_card_path;
> +for (const auto  : globs) {
> +std::string card_output = path.substr(path.rfind("/") + 1,
> path.npos);
> +auto dash_it = card_output.find("-");
> +// if this file is a card (and not an output)
> +if (dash_it == card_output.npos) {
> +// if we already have a found card, this means it
> doesn't have any outputs,
> +// we have found our card
> +if (!found_card_path.empty()) {
> +break;
> +}
> +found_card_path = card_output;
> +} else {
> +found_card_path = "";
> +}
> +}
> +
> +std::string device_address =
> get_device_address(found_card_path);
> +
> +auto xrandr_outputs = get_xrandr_outputs(display,
> RootWindow(display, XDefaultScreen(display)));
> +
> +std::vector result;
> +
> +for (uint32_t i = 0; i < xrandr_outputs.size(); ++i) {
> +result.push_back({i, device_address, i});
> +}
> +
> +return result;
> +}
> +
> +}} // namespace spice::streaming_agent


Acked-by: Jonathon Jongsma 


___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 5/8 v3] Send the graphics device info from streaming agent to the vd_agent

2019-01-17 Thread Jonathon Jongsma
On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> Adds the graphics device info from the streaming device(s) to the
> VDAgentGraphicsDeviceInfo message sent to the vd_agent.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-stream-device.c | 18 +++
>  server/red-stream-device.h |  7 +
>  server/reds.c  | 63
> --
>  3 files changed, 86 insertions(+), 2 deletions(-)
> 
> diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> index 6c90d77d..e7ed9f76 100644
> --- a/server/red-stream-device.c
> +++ b/server/red-stream-device.c
> @@ -342,6 +342,8 @@ handle_msg_device_display_info(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  dev->device_display_info.device_address,
>  dev->device_display_info.device_display_id);
>  
> +reds_send_device_display_info(red_char_device_get_server(RED_CHA
> R_DEVICE(dev)));
> +
>  return true;
>  }
>  
> @@ -799,6 +801,22 @@ stream_device_init(StreamDevice *dev)
>  dev->msg_len = sizeof(*dev->msg);
>  }
>  
> +StreamDeviceDisplayInfo
> *stream_device_get_device_display_info(StreamDevice *dev)
> +{
> +return >device_display_info;
> +}
> +
> +int32_t stream_device_get_stream_channel_id(StreamDevice *dev)
> +{
> +if (dev->stream_channel == NULL) {
> +return -1;
> +}
> +
> +int32_t channel_id;
> +g_object_get(dev->stream_channel, "id", _id, NULL);
> +return channel_id;
> +}
> +

Did you consider using a similar interface to the one used for the QXL
displays? e.g. _get_device_address() / _get_device_display_ids() / etc?

I know that the stream device currently (and probably always) only has
a single display per channel, but part of me wishes the interfaces had
some consistency.  Not a big issue, just curious.

Acked-by: Jonathon Jongsma 


>  static StreamDevice *
>  stream_device_new(SpiceCharDeviceInstance *sin, RedsState *reds)
>  {
> diff --git a/server/red-stream-device.h b/server/red-stream-device.h
> index 996be016..d7ab5e41 100644
> --- a/server/red-stream-device.h
> +++ b/server/red-stream-device.h
> @@ -56,6 +56,13 @@ StreamDevice *stream_device_connect(RedsState
> *reds, SpiceCharDeviceInstance *si
>   */
>  void stream_device_create_channel(StreamDevice *dev);
>  
> +StreamDeviceDisplayInfo
> *stream_device_get_device_display_info(StreamDevice *dev);
> +
> +/**
> + * Returns -1 if the StreamDevice doesn't have a channel yet.
> + */
> +int32_t stream_device_get_stream_channel_id(StreamDevice *dev);
> +
>  G_END_DECLS
>  
>  #endif /* STREAM_DEVICE_H */
> diff --git a/server/reds.c b/server/reds.c
> index 88a82419..22e81d73 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -902,14 +902,33 @@ void reds_send_device_display_info(RedsState
> *reds)
>  }
>  g_debug("Sending device display info to the agent:");
>  
> -size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
>  QXLInstance *qxl;
> +RedCharDevice *dev;
> +
> +size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> +
> +// size for the qxl device info
>  FOREACH_QXL_INSTANCE(reds, qxl) {
>  message_size +=
>  (sizeof(VDAgentDeviceDisplayInfo) +
> strlen(red_qxl_get_device_address(qxl)) + 1) *
>  red_qxl_get_monitors_count(qxl);
>  }
>  
> +// size for the stream device info
> +GLIST_FOREACH(reds->char_devices, RedCharDevice, dev) {
> +if (IS_STREAM_DEVICE(dev)) {
> +size_t device_address_len =
> +strlen(stream_device_get_device_display_info(STREAM_
> DEVICE(dev))->device_address);
> +
> +if (device_address_len == 0) {
> +// the device info wasn't set (yet), don't send it
> +continue;
> +}
> +
> +message_size += (sizeof(VDAgentDeviceDisplayInfo) +
> device_address_len + 1);
> +}
> +}
> +
>  RedCharDeviceWriteBuffer *char_dev_buf =
> vdagent_new_write_buffer(reds->agent_dev,
>   VD_AGENT_GRAPHICS_DEVICE_IN
> FO,
>   message_size,
> @@ -925,6 +944,8 @@ void reds_send_device_display_info(RedsState
> *reds)
>  graphics_device_info->count = 0;
>  
>  VDAgentDeviceDisplayInfo *device_display_info =
> graphics_device_info->display_info;
> +
> +// add the qxl devices to the message
>  FOREACH_QXL_INSTANCE(reds, qxl) {
>  for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i)
> {
>  device_display_info->channel_i

Re: [Spice-devel] [PATCH spice 3/8 v3] Send the graphics device info to the vd_agent

2019-01-17 Thread Jonathon Jongsma
re-sending on the correct patch series.

Acked-by: Jonathon Jongsma 


On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> Sends the device address and device display IDs to the vdagent. The
> message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
> message or when the graphics device info changes.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-qxl.c  | 20 +
>  server/red-qxl.h  |  3 ++
>  server/reds-private.h |  1 +
>  server/reds.c | 67
> +++
>  server/reds.h |  1 +
>  5 files changed, 92 insertions(+)
> 
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 291fd803..a56d9a52 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance
> *instance,
>  
>  instance->st->monitors_count = device_display_id_count;
>  instance->st->max_monitors = device_display_id_count;
> +
> +reds_send_device_display_info(red_qxl_get_server(instance->st));
> +}
> +
> +const char* red_qxl_get_device_address(const QXLInstance *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->device_address;
> +}
> +
> +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->device_display_ids;
> +}
> +
> +size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->monitors_count;
>  }
>  
>  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> diff --git a/server/red-qxl.h b/server/red-qxl.h
> index 6014d32a..94753948 100644
> --- a/server/red-qxl.h
> +++ b/server/red-qxl.h
> @@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl,
> SpiceMsgDisplayGlScanoutUnix *scan
>  void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
>  int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int
> minor);
>  SpiceServer* red_qxl_get_server(QXLState *qxl);
> +const char* red_qxl_get_device_address(const QXLInstance *qxl);
> +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl);
> +size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
>  
>  /* Wrappers around QXLInterface vfuncs */
>  void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
> diff --git a/server/reds-private.h b/server/reds-private.h
> index 920edc5c..9dbc7fa9 100644
> --- a/server/reds-private.h
> +++ b/server/reds-private.h
> @@ -81,6 +81,7 @@ struct RedsState {
>  SpiceWatch *secure_listen_watch;
>  RedCharDeviceVDIPort *agent_dev;
>  int pending_mouse_event;
> +bool pending_device_display_info_message;
>  GList *clients;
>  MainChannel *main_channel;
>  InputsChannel *inputs_channel;
> diff --git a/server/reds.c b/server/reds.c
> index cdbb94cb..88a82419 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__))
> VDInternalBuf {
>  VDAgentMessage header;
>  union {
>  VDAgentMouseState mouse_state;
> +VDAgentGraphicsDeviceInfo graphics_device_info;
>  }
>  u;
>  } VDInternalBuf;
> @@ -894,6 +895,65 @@ static RedPipeItem
> *vdi_port_read_one_msg_from_device(RedCharDevice *self,
>  return NULL;
>  }
>  
> +void reds_send_device_display_info(RedsState *reds)
> +{
> +if (!reds->agent_dev->priv->agent_attached) {
> +return;
> +}
> +g_debug("Sending device display info to the agent:");
> +
> +size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> +QXLInstance *qxl;
> +FOREACH_QXL_INSTANCE(reds, qxl) {
> +message_size +=
> +(sizeof(VDAgentDeviceDisplayInfo) +
> strlen(red_qxl_get_device_address(qxl)) + 1) *
> +red_qxl_get_monitors_count(qxl);
> +}
> +
> +RedCharDeviceWriteBuffer *char_dev_buf =
> vdagent_new_write_buffer(reds->agent_dev,
> + VD_AGENT_GRAPHICS_DEVICE_IN
> FO,
> + message_size,
> + true);
> +
> +if (!char_dev_buf) {
> +reds->pending_device_display_info_message = true;
> +return;
> +}
> +
> +VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf-
> >buf;
> +VDAgentGraphicsDeviceInfo *graphics_device_info = _buf-
> >u.graphics_device_info;
> +graphics_device_info->count = 0;
> +
> +VDAgentDeviceDisplayInfo *device_display_info =
> graphic

Re: [Spice-devel] [PATCH spice-protocol 2/8 v3] Add the StreamMsgGraphicsDeviceInfo message

2019-01-17 Thread Jonathon Jongsma
Accidentally sent this on the v2 series, but I'll repeat it here:

Commit subject mentions the wrong type name?
StreamMsgGraphicsDeviceInfo != StreamMsgDeviceDisplayInfo


On Wed, 2019-01-16 at 13:52 +0100, Lukáš Hrázký wrote:
> The message contains information about the graphics device and
> monitor
> belonging to a particular video stream (which maps to a channel) from
> the streaming agent.
> 
> Signed-off-by: Lukáš Hrázký 
> Acked-by: Frediano Ziglio 
> ---
>  spice/stream-device.h | 31 +++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/spice/stream-device.h b/spice/stream-device.h
> index 6add42b..c70690a 100644
> --- a/spice/stream-device.h
> +++ b/spice/stream-device.h
> @@ -90,6 +90,8 @@ typedef enum StreamMsgType {
>  STREAM_TYPE_CURSOR_SET,
>  /* guest cursor position */
>  STREAM_TYPE_CURSOR_MOVE,
> +/* the graphics device display information message (device
> address and display id) */
> +STREAM_TYPE_DEVICE_DISPLAY_INFO,
>  } StreamMsgType;
>  
>  typedef enum StreamCapabilities {
> @@ -140,6 +142,35 @@ typedef struct StreamMsgData {
>  uint8_t data[0];
>  } StreamMsgData;
>  
> +/* This message contains information about the graphics device and
> monitor
> + * belonging to a particular video stream (which maps to a channel)
> from
> + * the streaming agent.
> + *
> + * The device_address is the hardware address of the device (e.g.
> PCI),
> + * device_display_id is the id of the monitor on the device.
> + *
> + * The supported device address format is:
> + * "pci//./.../."
> + *
> + * The "pci" identifies the rest of the string as a PCI address. It
> is the only
> + * supported address at the moment, other identifiers can be
> introduced later.
> + *  is the PCI domain, followed by . of any
> PCI bridges
> + * in the chain leading to the device. The last . is
> the
> + * graphics device. All of , ,  are
> hexadecimal numbers
> + * with the following number of digits:
> + *   : 4
> + *   : 2
> + *   : 1
> + *
> + * Sent from the streaming agent to the server.
> + */
> +typedef struct StreamMsgDeviceDisplayInfo {
> +uint32_t stream_id;
> +uint32_t device_display_id;
> +uint32_t device_address_len;
> +uint8_t device_address[0];  // a zero-terminated string
> +} StreamMsgDeviceDisplayInfo;
> +
>  /* Tell to stop current stream and possibly start a new one.
>   * This message is sent by the host to the guest.
>   * Allows to communicate the codecs supported by the clients.

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-protocol 2/8 v2] Add the StreamMsgGraphicsDeviceInfo message

2019-01-17 Thread Jonathon Jongsma
Commit subject mentions the wrong type name?
StreamMsgGraphicsDeviceInfo != StreamMsgDeviceDisplayInfo


On Mon, 2019-01-14 at 17:38 +0100, Lukáš Hrázký wrote:
> The message contains information about the graphics device and
> monitor
> belonging to a particular video stream (which maps to a channel) from
> the streaming agent.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  spice/stream-device.h | 31 +++
>  1 file changed, 31 insertions(+)
> 
> diff --git a/spice/stream-device.h b/spice/stream-device.h
> index 6add42b..c70690a 100644
> --- a/spice/stream-device.h
> +++ b/spice/stream-device.h
> @@ -90,6 +90,8 @@ typedef enum StreamMsgType {
>  STREAM_TYPE_CURSOR_SET,
>  /* guest cursor position */
>  STREAM_TYPE_CURSOR_MOVE,
> +/* the graphics device display information message (device
> address and display id) */
> +STREAM_TYPE_DEVICE_DISPLAY_INFO,
>  } StreamMsgType;
>  
>  typedef enum StreamCapabilities {
> @@ -140,6 +142,35 @@ typedef struct StreamMsgData {
>  uint8_t data[0];
>  } StreamMsgData;
>  
> +/* This message contains information about the graphics device and
> monitor
> + * belonging to a particular video stream (which maps to a channel)
> from
> + * the streaming agent.
> + *
> + * The device_address is the hardware address of the device (e.g.
> PCI),
> + * device_display_id is the id of the monitor on the device.
> + *
> + * The supported device address format is:
> + * "pci//./.../."
> + *
> + * The "pci" identifies the rest of the string as a PCI address. It
> is the only
> + * supported address at the moment, other identifiers can be
> introduced later.
> + *  is the PCI domain, followed by . of any
> PCI bridges
> + * in the chain leading to the device. The last . is
> the
> + * graphics device. All of , ,  are
> hexadecimal numbers
> + * with the following number of digits:
> + *   : 4
> + *   : 2
> + *   : 1
> + *
> + * Sent from the streaming agent to the server.
> + */
> +typedef struct StreamMsgDeviceDisplayInfo {
> +uint32_t stream_id;
> +uint32_t device_display_id;
> +uint32_t device_address_len;
> +uint8_t device_address[0];  // a zero-terminated string
> +} StreamMsgDeviceDisplayInfo;
> +
>  /* Tell to stop current stream and possibly start a new one.
>   * This message is sent by the host to the guest.
>   * Allows to communicate the codecs supported by the clients.

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 3/8 v2] Send the graphics device info to the vd_agent

2019-01-17 Thread Jonathon Jongsma
Acked-by: Jonathon Jongmsa 

On Mon, 2019-01-14 at 17:38 +0100, Lukáš Hrázký wrote:
> Sends the device address and device display IDs to the vdagent. The
> message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
> message or when the graphics device info changes.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-qxl.c  | 20 +
>  server/red-qxl.h  |  3 ++
>  server/reds-private.h |  1 +
>  server/reds.c | 67
> +++
>  server/reds.h |  1 +
>  5 files changed, 92 insertions(+)
> 
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 291fd803..a56d9a52 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance
> *instance,
>  
>  instance->st->monitors_count = device_display_id_count;
>  instance->st->max_monitors = device_display_id_count;
> +
> +reds_send_device_display_info(red_qxl_get_server(instance->st));
> +}
> +
> +const char* red_qxl_get_device_address(const QXLInstance *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->device_address;
> +}
> +
> +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->device_display_ids;
> +}
> +
> +size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->monitors_count;
>  }
>  
>  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> diff --git a/server/red-qxl.h b/server/red-qxl.h
> index 6014d32a..94753948 100644
> --- a/server/red-qxl.h
> +++ b/server/red-qxl.h
> @@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl,
> SpiceMsgDisplayGlScanoutUnix *scan
>  void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
>  int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int
> minor);
>  SpiceServer* red_qxl_get_server(QXLState *qxl);
> +const char* red_qxl_get_device_address(const QXLInstance *qxl);
> +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl);
> +size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
>  
>  /* Wrappers around QXLInterface vfuncs */
>  void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
> diff --git a/server/reds-private.h b/server/reds-private.h
> index 920edc5c..9dbc7fa9 100644
> --- a/server/reds-private.h
> +++ b/server/reds-private.h
> @@ -81,6 +81,7 @@ struct RedsState {
>  SpiceWatch *secure_listen_watch;
>  RedCharDeviceVDIPort *agent_dev;
>  int pending_mouse_event;
> +bool pending_device_display_info_message;
>  GList *clients;
>  MainChannel *main_channel;
>  InputsChannel *inputs_channel;
> diff --git a/server/reds.c b/server/reds.c
> index cdbb94cb..88a82419 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__))
> VDInternalBuf {
>  VDAgentMessage header;
>  union {
>  VDAgentMouseState mouse_state;
> +VDAgentGraphicsDeviceInfo graphics_device_info;
>  }
>  u;
>  } VDInternalBuf;
> @@ -894,6 +895,65 @@ static RedPipeItem
> *vdi_port_read_one_msg_from_device(RedCharDevice *self,
>  return NULL;
>  }
>  
> +void reds_send_device_display_info(RedsState *reds)
> +{
> +if (!reds->agent_dev->priv->agent_attached) {
> +return;
> +}
> +g_debug("Sending device display info to the agent:");
> +
> +size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> +QXLInstance *qxl;
> +FOREACH_QXL_INSTANCE(reds, qxl) {
> +message_size +=
> +(sizeof(VDAgentDeviceDisplayInfo) +
> strlen(red_qxl_get_device_address(qxl)) + 1) *
> +red_qxl_get_monitors_count(qxl);
> +}
> +
> +RedCharDeviceWriteBuffer *char_dev_buf =
> vdagent_new_write_buffer(reds->agent_dev,
> + VD_AGENT_GRAPHICS_DEVICE_IN
> FO,
> + message_size,
> + true);
> +
> +if (!char_dev_buf) {
> +reds->pending_device_display_info_message = true;
> +return;
> +}
> +
> +VDInternalBuf *internal_buf = (VDInternalBuf *)char_dev_buf-
> >buf;
> +VDAgentGraphicsDeviceInfo *graphics_device_info = _buf-
> >u.graphics_device_info;
> +graphics_device_info->count = 0;
> +
> +VDAgentDeviceDisplayInfo *device_display_info =
> graphics_device_info->display_info;
> +FOREACH_QXL_INSTANCE(reds, qxl) {
> +for (size_t i = 0; i < red_qxl_get_monitors_count(qxl); ++i)
> {
> +device_display_info->channel_id = qxl->id;
> +device_display_info->monitor_id = i;
> +device_display_info->device_display_id =
> red_qxl_get_device_display_ids(qxl)[i];
> +
> +strcpy((char*) device_display_info->device_address,
> red_qxl_get_device_address(qxl));
> +
> +

Re: [Spice-devel] [PATCH spice 4/8 v2] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-17 Thread Jonathon Jongsma
On Wed, 2019-01-16 at 13:34 +0100, Lukáš Hrázký wrote:
> > > +StreamMsgDeviceDisplayInfo *display_info_msg =
> > > >msg->device_display_info;
> > > +
> > > +size_t device_address_len =
> > > GUINT32_FROM_LE(display_info_msg->device_address_len);
> > > +if (device_address_len > MAX_DEVICE_ADDRESS_LEN) {
> > > +g_error("Received a device address longer than %u (%zu),
> > > "
> > > +"will be truncated!", MAX_DEVICE_ADDRESS_LEN,
> > > device_address_len);
> > 
> > DoS, g_error will abort() Qemu.
> 
> I'll put a warning there, though I think it should be logged as an
> error...


Well, it's an error to send an address that is too long. I don't think
it can be considered an error to *receive* such a message. So I think
warning is perfectly fine here. We need to handle invalid input, after
all.

Jonathon

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-server] Reuse SPICE_UPCAST instead of SPICE_CONTAINEROF where possible

2019-01-17 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 

On Wed, 2019-01-02 at 11:21 +, Frediano Ziglio wrote:
> Signed-off-by: Frediano Ziglio 
> ---
>  server/inputs-channel.c |  8 
>  server/reds.c   | 36 +++-
>  server/reds.h   |  2 +-
>  3 files changed, 24 insertions(+), 22 deletions(-)
> 
> diff --git a/server/inputs-channel.c b/server/inputs-channel.c
> index 20ebd11c..a7df62e2 100644
> --- a/server/inputs-channel.c
> +++ b/server/inputs-channel.c
> @@ -170,7 +170,7 @@ static void kbd_push_scan(SpiceKbdInstance *sin,
> uint8_t scan)
>  if (!sin) {
>  return;
>  }
> -sif = SPICE_CONTAINEROF(sin->base.sif, SpiceKbdInterface, base);
> +sif = SPICE_UPCAST(SpiceKbdInterface, sin->base.sif);
>  
>  /* track XT scan code set 1 key state */
>  if (scan >= 0xe0 && scan <= 0xe2) {
> @@ -193,7 +193,7 @@ static uint8_t kbd_get_leds(SpiceKbdInstance
> *sin)
>  if (!sin) {
>  return 0;
>  }
> -sif = SPICE_CONTAINEROF(sin->base.sif, SpiceKbdInterface, base);
> +sif = SPICE_UPCAST(SpiceKbdInterface, sin->base.sif);
>  return sif->get_leds(sin);
>  }
>  
> @@ -288,7 +288,7 @@ static bool
> inputs_channel_handle_message(RedChannelClient *rcc, uint16_t type,
>  inputs_channel_client_on_mouse_motion(icc);
>  if (mouse && reds_get_mouse_mode(reds) ==
> SPICE_MOUSE_MODE_SERVER) {
>  SpiceMouseInterface *sif;
> -sif = SPICE_CONTAINEROF(mouse->base.sif,
> SpiceMouseInterface, base);
> +sif = SPICE_UPCAST(SpiceMouseInterface, mouse-
> >base.sif);
>  sif->motion(mouse,
>  mouse_motion->dx, mouse_motion->dy, 0,
>  RED_MOUSE_STATE_TO_LOCAL(mouse_motion-
> >buttons_state));
> @@ -306,7 +306,7 @@ static bool
> inputs_channel_handle_message(RedChannelClient *rcc, uint16_t type,
>  spice_assert((reds_config_get_agent_mouse(reds) &&
> reds_has_vdagent(reds)) || tablet);
>  if (!reds_config_get_agent_mouse(reds) ||
> !reds_has_vdagent(reds)) {
>  SpiceTabletInterface *sif;
> -sif = SPICE_CONTAINEROF(tablet->base.sif,
> SpiceTabletInterface, base);
> +sif = SPICE_UPCAST(SpiceTabletInterface, tablet-
> >base.sif);
>  sif->position(tablet, pos->x, pos->y,
> RED_MOUSE_STATE_TO_LOCAL(pos->buttons_state));
>  break;
>  }
> diff --git a/server/reds.c b/server/reds.c
> index cdbb94cb..e95c62d5 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -439,7 +439,7 @@ static void reds_mig_cleanup(RedsState *reds)
>  if (reds->mig_wait_connect || reds->mig_wait_disconnect) {
>  SpiceMigrateInterface *sif;
>  spice_assert(reds->migration_interface);
> -sif = SPICE_CONTAINEROF(reds->migration_interface-
> >base.sif, SpiceMigrateInterface, base);
> +sif = SPICE_UPCAST(SpiceMigrateInterface, reds-
> >migration_interface->base.sif);
>  if (reds->mig_wait_connect) {
>  sif->migrate_connect_complete(reds-
> >migration_interface);
>  } else {
> @@ -3136,7 +3136,7 @@ static int
> spice_server_char_device_add_interface(SpiceServer *reds,
> SpiceBaseInstance *sin)
>  {
>  SpiceCharDeviceInstance* char_device =
> -SPICE_CONTAINEROF(sin, SpiceCharDeviceInstance, base);
> +SPICE_UPCAST(SpiceCharDeviceInstance, sin);
>  RedCharDevice *dev_state = NULL;
>  
>  spice_debug("CHAR_DEVICE %s", char_device->subtype);
> @@ -3193,7 +3193,7 @@ static int
> spice_server_char_device_add_interface(SpiceServer *reds,
>  static int spice_server_char_device_remove_interface(RedsState
> *reds, SpiceBaseInstance *sin)
>  {
>  SpiceCharDeviceInstance* char_device =
> -SPICE_CONTAINEROF(sin, SpiceCharDeviceInstance, base);
> +SPICE_UPCAST(SpiceCharDeviceInstance, sin);
>  
>  spice_debug("remove CHAR_DEVICE %s", char_device->subtype);
>  if (strcmp(char_device->subtype, SUBTYPE_VDAGENT) == 0) {
> @@ -3231,7 +3231,8 @@ SPICE_GNUC_VISIBLE int
> spice_server_add_interface(SpiceServer *reds,
>  spice_warning("unsupported keyboard interface");
>  return -1;
>  }
> -if (inputs_channel_set_keyboard(reds->inputs_channel,
> SPICE_CONTAINEROF(sin, SpiceKbdInstance, base)) != 0) {
> +if (inputs_channel_set_keyboard(reds->inputs_channel,
> +S

Re: [Spice-devel] [PATCH spice 4/8] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-14 Thread Jonathon Jongsma
On Fri, 2019-01-11 at 10:07 +0100, Lukáš Hrázký wrote:
> Hi,
> 
> On Thu, 2019-01-10 at 15:27 -0600, Jonathon Jongsma wrote:
> > On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> > > Receives the GraphicsDeviceInfo message from the streaming agent
> > > and
> > > stores the data in a list on the streaming device.
> > > 
> > > Signed-off-by: Lukáš Hrázký 
> > > ---
> > >  server/red-qxl.c   |  1 -
> > >  server/red-stream-device.c | 66
> > > --
> > >  server/red-stream-device.h |  8 +
> > >  server/reds.h  |  3 ++
> > >  4 files changed, 74 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > > index ebc14a46..e174758f 100644
> > > --- a/server/red-qxl.c
> > > +++ b/server/red-qxl.c
> > > @@ -41,7 +41,6 @@
> > >  #include "red-qxl.h"
> > >  
> > >  
> > > -#define MAX_DEVICE_ADDRESS_LEN 256
> > >  #define MAX_MONITORS_COUNT 16
> > >  
> > >  struct QXLState {
> > > diff --git a/server/red-stream-device.c b/server/red-stream-
> > > device.c
> > > index 215ddbe7..bbd6874f 100644
> > > --- a/server/red-stream-device.c
> > > +++ b/server/red-stream-device.c
> > > @@ -23,7 +23,6 @@
> > >  
> > >  #include "stream-channel.h"
> > >  #include "cursor-channel.h"
> > > -#include "reds.h"
> > 
> > As far as I can see, we're only adding new code in this file while
> > removing an include. That tells me that this include change is
> > unrelated to the other changes?
> 
> That include was actually moved to the header, see also the
> discussion
> with Frediano if interested, I'll be changing it and this won't be
> here
> anymore.
> 
> > >  #define MAX_GUEST_CAPABILITIES_BYTES ((STREAM_CAP_END+7)/8)
> > >  
> > > @@ -37,6 +36,7 @@ struct StreamDevice {
> > >  StreamMsgCapabilities capabilities;
> > >  StreamMsgCursorSet cursor_set;
> > >  StreamMsgCursorMove cursor_move;
> > > +StreamMsgDeviceDisplayInfo device_display_info;
> > >  uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
> > >  } *msg;
> > >  uint32_t msg_pos;
> > > @@ -49,6 +49,7 @@ struct StreamDevice {
> > >  CursorChannel *cursor_channel;
> > >  SpiceTimer *close_timer;
> > >  uint32_t frame_mmtime;
> > > +StreamDeviceDisplayInfo device_display_info;
> > 
> > It strikes me as slightly confusing to have both
> > StreamDevice.device_display_info and
> > StreamDevice.msg.device_display_info
> 
> Well, one is in the message as it's being read from the virtio port,
> the other is the struct that holds the data in memory. They contain
> the
> same thing. I don't think it's confusing given you understand the
> memory structure and how the messages are read and actually kind of
> makes sense... It does tell you it's the same thing, just
> demarshalled
> into memory.
> 
> Any suggestions to improve it?

Not really. It's fine.

Jonathon


> 
> Cheers,
> Lukas
> 
> > >  };
> > >  
> > >  struct StreamDeviceClass {
> > > @@ -64,8 +65,8 @@ static void char_device_set_state(RedCharDevice
> > > *char_dev, int state);
> > >  typedef bool StreamMsgHandler(StreamDevice *dev,
> > > SpiceCharDeviceInstance *sin)
> > >  SPICE_GNUC_WARN_UNUSED_RESULT;
> > >  
> > > -static StreamMsgHandler handle_msg_format, handle_msg_data,
> > > handle_msg_cursor_set,
> > > -handle_msg_cursor_move, handle_msg_capabilities;
> > > +static StreamMsgHandler handle_msg_format,
> > > handle_msg_device_display_info, handle_msg_data,
> > > +handle_msg_cursor_set, handle_msg_cursor_move,
> > > handle_msg_capabilities;
> > >  
> > >  static bool handle_msg_invalid(StreamDevice *dev,
> > > SpiceCharDeviceInstance *sin,
> > > const char *error_msg)
> > > SPICE_GNUC_WARN_UNUSED_RESULT;
> > > @@ -146,6 +147,13 @@ stream_device_partial_read(StreamDevice
> > > *dev,
> > > SpiceCharDeviceInstance *sin)
> > >  handled = handle_msg_format(dev, sin);
> > >  }
> > >  break;
> > > +case STREAM_TYPE_DEVICE_DISPLAY_INFO:
> > > +if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) +
> > 

Re: [Spice-devel] [PATCH spice 1/3] QXL interface: add a function to identify monitors in the guest

2019-01-14 Thread Jonathon Jongsma
On Fri, 2019-01-11 at 11:15 +0100, Lukáš Hrázký wrote:
> On Wed, 2019-01-09 at 11:36 -0600, Jonathon Jongsma wrote:
> > On Tue, 2019-01-08 at 16:26 +0100, Lukáš Hrázký wrote:
> > > Adds a function to let QEMU provide information to identify
> > > graphics
> > > devices and their monitors in the guest. The function
> > > (spice_qxl_set_device_info) sets the device address (e.g. a PCI
> > > path)
> > > and monitor ID -> device display ID mapping of displays exposed
> > > by
> > > given
> > > QXL interface.
> > 
> > 
> > In my previous review, I asked for a slightly more explicit
> > explanation
> > of the phrase "monitor ID" in the commit log. In this case,
> > "monitor
> > ID" is an ID specific to the QXL instance starting at 0 and
> > represents
> > the displays that are associated with that particular QXL instance.
> > 
> > Perhaps it makes sense to rename this "Qxl monitor ID"?
> 
> Sorry, I might have forgotten to incorporate some comments on the old
> series :/
> 
> To reiterate, though, what do you find unclear about the "monitor
> ID"?
> I mean maybe it should be spelled "monitor_id" to make it clearer
> what
> it refers to... Not sure if "Qxl monitor ID" helps, since it is not
> strictly related to QXL, but more to the QXL interface (which is used
> for all graphic cards, which makes it more confusing)...

Well, there are so many somewhat similar phrases being used for
slightly different things here that I'm afraid that I'll get confused
in the future when I come back to look at this stuff. But as you say,
I'm not sure there's a good way to make it clearer. You can just ignore
this bit if you want

> 
> > > Signed-off-by: Lukáš Hrázký 
> > > ---
> > >  server/red-qxl.c | 44
> > > ++
> > >  server/spice-qxl.h   | 46
> > > 
> > >  server/spice-server.syms |  5 +
> > >  3 files changed, 95 insertions(+)
> > > 
> > > diff --git a/server/red-qxl.c b/server/red-qxl.c
> > > index 97940611..0ea424cd 100644
> > > --- a/server/red-qxl.c
> > > +++ b/server/red-qxl.c
> > > @@ -41,6 +41,9 @@
> > >  #include "red-qxl.h"
> > >  
> > >  
> > > +#define MAX_DEVICE_ADDRESS_LEN 256
> > > +#define MAX_MONITORS_COUNT 16
> > > +
> > >  struct QXLState {
> > >  QXLWorker qxl_worker;
> > >  QXLInstance *qxl;
> > > @@ -53,6 +56,9 @@ struct QXLState {
> > >  unsigned int max_monitors;
> > >  RedsState *reds;
> > >  RedWorker *worker;
> > > +char device_address[MAX_DEVICE_ADDRESS_LEN];
> > > +uint32_t device_display_ids[MAX_MONITORS_COUNT];
> > > +size_t monitors_count;  // length of ^^^
> > >  
> > >  pthread_mutex_t scanout_mutex;
> > >  SpiceMsgDisplayGlScanoutUnix scanout;
> > > @@ -846,6 +852,44 @@ void
> > > red_qxl_gl_draw_async_complete(QXLInstance
> > > *qxl)
> > >  red_qxl_async_complete(qxl, cookie);
> > >  }
> > >  
> > > +SPICE_GNUC_VISIBLE
> > > +void spice_qxl_set_device_info(QXLInstance *instance,
> > > +   const char *device_address,
> > > +   uint32_t device_display_id_start,
> > > +   uint32_t device_display_id_count)
> > > +{
> > > +g_return_if_fail(device_address != NULL);
> > 
> > Just a thought: what if qemu calls this function twice for the same
> > instance. In theory this shouldn't happen, but should we be
> > defensive
> > and handle it somehow? Print a warning? Just overwrite the previous
> > mapping? Right now it looks like we would just overwrite.
> 
> I'm pretty sure overwriting is the correct behavior here, no logging
> needed? There may be a situation where the info changes in the
> future,
> for whatever reasons. At least this part of the code should be fine
> with it (though I'm not sure atm. if e.g. the client would cope
> well).

At the moment, it seems more likely that if this function was called
twice, it would be due to a bug somewhere. Which is why I wondered
about printing a warning or something. I can't really imagine a
scenario where we'd want to change the device info after it was set.
Anyway, like I said, it's mostly a theoretical issue at this point.

Jonathon

> 
> > > +
> > > +size_t da_len = strnlen(device_a

Re: [Spice-devel] [PATCH spice 4/8] Receive the GraphicsDeviceInfo message from the streaming agent

2019-01-10 Thread Jonathon Jongsma
On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> Receives the GraphicsDeviceInfo message from the streaming agent and
> stores the data in a list on the streaming device.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-qxl.c   |  1 -
>  server/red-stream-device.c | 66
> --
>  server/red-stream-device.h |  8 +
>  server/reds.h  |  3 ++
>  4 files changed, 74 insertions(+), 4 deletions(-)
> 
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index ebc14a46..e174758f 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -41,7 +41,6 @@
>  #include "red-qxl.h"
>  
>  
> -#define MAX_DEVICE_ADDRESS_LEN 256
>  #define MAX_MONITORS_COUNT 16
>  
>  struct QXLState {
> diff --git a/server/red-stream-device.c b/server/red-stream-device.c
> index 215ddbe7..bbd6874f 100644
> --- a/server/red-stream-device.c
> +++ b/server/red-stream-device.c
> @@ -23,7 +23,6 @@
>  
>  #include "stream-channel.h"
>  #include "cursor-channel.h"
> -#include "reds.h"

As far as I can see, we're only adding new code in this file while
removing an include. That tells me that this include change is
unrelated to the other changes?

>  
>  #define MAX_GUEST_CAPABILITIES_BYTES ((STREAM_CAP_END+7)/8)
>  
> @@ -37,6 +36,7 @@ struct StreamDevice {
>  StreamMsgCapabilities capabilities;
>  StreamMsgCursorSet cursor_set;
>  StreamMsgCursorMove cursor_move;
> +StreamMsgDeviceDisplayInfo device_display_info;
>  uint8_t buf[STREAM_MSG_CAPABILITIES_MAX_BYTES];
>  } *msg;
>  uint32_t msg_pos;
> @@ -49,6 +49,7 @@ struct StreamDevice {
>  CursorChannel *cursor_channel;
>  SpiceTimer *close_timer;
>  uint32_t frame_mmtime;
> +StreamDeviceDisplayInfo device_display_info;

It strikes me as slightly confusing to have both
StreamDevice.device_display_info and
StreamDevice.msg.device_display_info

>  };
>  
>  struct StreamDeviceClass {
> @@ -64,8 +65,8 @@ static void char_device_set_state(RedCharDevice
> *char_dev, int state);
>  typedef bool StreamMsgHandler(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  SPICE_GNUC_WARN_UNUSED_RESULT;
>  
> -static StreamMsgHandler handle_msg_format, handle_msg_data,
> handle_msg_cursor_set,
> -handle_msg_cursor_move, handle_msg_capabilities;
> +static StreamMsgHandler handle_msg_format,
> handle_msg_device_display_info, handle_msg_data,
> +handle_msg_cursor_set, handle_msg_cursor_move,
> handle_msg_capabilities;
>  
>  static bool handle_msg_invalid(StreamDevice *dev,
> SpiceCharDeviceInstance *sin,
> const char *error_msg)
> SPICE_GNUC_WARN_UNUSED_RESULT;
> @@ -146,6 +147,13 @@ stream_device_partial_read(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  handled = handle_msg_format(dev, sin);
>  }
>  break;
> +case STREAM_TYPE_DEVICE_DISPLAY_INFO:
> +if (dev->hdr.size > sizeof(StreamMsgDeviceDisplayInfo) +
> MAX_DEVICE_ADDRESS_LEN) {
> +handled = handle_msg_invalid(dev, sin,
> "StreamMsgDeviceDisplayInfo too large");
> +} else {
> +handled = handle_msg_device_display_info(dev, sin);
> +}
> +break;
>  case STREAM_TYPE_DATA:
>  if (dev->hdr.size > 32*1024*1024) {
>  handled = handle_msg_invalid(dev, sin, "STREAM_DATA too
> large");
> @@ -271,6 +279,58 @@ handle_msg_format(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
>  return true;
>  }
>  
> +static bool
> +handle_msg_device_display_info(StreamDevice *dev,
> SpiceCharDeviceInstance *sin)
> +{
> +SpiceCharDeviceInterface *sif =
> spice_char_device_get_interface(sin);
> +
> +if (spice_extra_checks) {
> +spice_assert(dev->hdr_pos >= sizeof(StreamDevHeader));
> +spice_assert(dev->hdr.type ==
> STREAM_TYPE_DEVICE_DISPLAY_INFO);
> +}
> +
> +if (dev->msg_len < dev->hdr.size) {
> +dev->msg = g_realloc(dev->msg, dev->hdr.size);
> +dev->msg_len = dev->hdr.size;
> +}
> +
> +/* read from device */
> +ssize_t n = sif->read(sin, dev->msg->buf + dev->msg_pos, dev-
> >hdr.size - dev->msg_pos);
> +if (n <= 0) {
> +return dev->msg_pos == dev->hdr.size;
> +}
> +
> +dev->msg_pos += n;
> +if (dev->msg_pos != dev->hdr.size) { /* some bytes are still
> missing */
> +return false;
> +}
> +
> +StreamMsgDeviceDisplayInfo *display_info_msg = >msg-
> >device_display_info;
> +
> +size_t device_address_len = display_info_msg-
> >device_address_len;
> +if (device_address_len > MAX_DEVICE_ADDRESS_LEN) {
> +g_error("Received a device address longer than %u (%lu), "
> +"will be truncated!", MAX_DEVICE_ADDRESS_LEN,
> device_address_len);
> +device_address_len = sizeof(dev-
> >device_display_info.device_address);
> +}
> +
> +strncpy(dev->device_display_info.device_address,
> +(char*) display_info_msg->device_address,
> +

Re: [Spice-devel] [PATCH spice 3/8] Send the graphics device info to the vd_agent

2019-01-10 Thread Jonathon Jongsma
On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> Sends the device address and device display IDs to the vdagent. The
> message is sent either in reaction to the SPICE_MSGC_MAIN_AGENT_START
> message or when the graphics device info changes.
> 
> TODO: doesn't resend the message on agent reconnect, FIXIT.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-qxl.c  | 20 +
>  server/red-qxl.h  |  3 ++
>  server/reds-private.h |  1 +
>  server/reds.c | 67
> +++
>  server/reds.h |  1 +
>  5 files changed, 92 insertions(+)
> 
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 6ffd8286..ebc14a46 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -889,6 +889,26 @@ void spice_qxl_set_device_info(QXLInstance
> *instance,
>  
>  instance->st->monitors_count = device_display_id_count;
>  instance->st->max_monitors = device_display_id_count;
> +
> +reds_send_device_display_info(red_qxl_get_server(instance->st));
> +}
> +
> +const char* red_qxl_get_device_address(const QXLInstance *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->device_address;
> +}
> +
> +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->device_display_ids;
> +}
> +
> +size_t red_qxl_get_monitors_count(const QXLInstance *qxl)
> +{
> +const QXLState *qxl_state = qxl->st;
> +return qxl_state->monitors_count;
>  }
>  
>  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> diff --git a/server/red-qxl.h b/server/red-qxl.h
> index 6014d32a..94753948 100644
> --- a/server/red-qxl.h
> +++ b/server/red-qxl.h
> @@ -40,6 +40,9 @@ void red_qxl_put_gl_scanout(QXLInstance *qxl,
> SpiceMsgDisplayGlScanoutUnix *scan
>  void red_qxl_gl_draw_async_complete(QXLInstance *qxl);
>  int red_qxl_check_qxl_version(QXLInstance *qxl, int major, int
> minor);
>  SpiceServer* red_qxl_get_server(QXLState *qxl);
> +const char* red_qxl_get_device_address(const QXLInstance *qxl);
> +const uint32_t* red_qxl_get_device_display_ids(const QXLInstance
> *qxl);
> +size_t red_qxl_get_monitors_count(const QXLInstance *qxl);
>  
>  /* Wrappers around QXLInterface vfuncs */
>  void red_qxl_get_init_info(QXLInstance *qxl, QXLDevInitInfo *info);
> diff --git a/server/reds-private.h b/server/reds-private.h
> index 920edc5c..9dbc7fa9 100644
> --- a/server/reds-private.h
> +++ b/server/reds-private.h
> @@ -81,6 +81,7 @@ struct RedsState {
>  SpiceWatch *secure_listen_watch;
>  RedCharDeviceVDIPort *agent_dev;
>  int pending_mouse_event;
> +bool pending_device_display_info_message;
>  GList *clients;
>  MainChannel *main_channel;
>  InputsChannel *inputs_channel;
> diff --git a/server/reds.c b/server/reds.c
> index cdbb94cb..b85758b6 100644
> --- a/server/reds.c
> +++ b/server/reds.c
> @@ -257,6 +257,7 @@ typedef struct __attribute__ ((__packed__))
> VDInternalBuf {
>  VDAgentMessage header;
>  union {
>  VDAgentMouseState mouse_state;
> +VDAgentGraphicsDeviceInfo graphics_device_info;
>  }
>  u;
>  } VDInternalBuf;
> @@ -894,6 +895,65 @@ static RedPipeItem
> *vdi_port_read_one_msg_from_device(RedCharDevice *self,
>  return NULL;
>  }
>  
> +void reds_send_device_display_info(RedsState *reds)

Personally I think a more consistent name would be better here. When I
see a function called reds_send_*(), my assumption is that it sends a
message to the client (cf. reds_send_mm_time()). But this function
sends to to the agent. The other functions in this file that send
messages to the agent are all named something like reds_handle_* (e.g.
reds_handle_agent_mouse_event()) or reds_on_* (e.g.
reds_on_main_agent_data()). Granted, those functions are responding to
incoming events/messages from the client, so the on_/handle_ names may
make more sense. But I don't think it would be terrible to name this
function something like reds_handle_device_display_info() or
reds_on_new_device_display_info(). Or if you want to keep 'send' in the
name, maybe be more explicit about where it's being sent?
reds_send_device_display_info_to_agent()?

Otherwise seems fine to me.

> +{
> +if (!reds->agent_dev->priv->agent_attached) {
> +return;
> +}
> +g_debug("Sending device display info to the agent:");
> +
> +size_t message_size = sizeof(VDAgentGraphicsDeviceInfo);
> +QXLInstance *qxl;
> +FOREACH_QXL_INSTANCE(reds, qxl) {
> +message_size +=
> +(sizeof(VDAgentDeviceDisplayInfo) +
> strlen(red_qxl_get_device_address(qxl)) + 1) *
> +red_qxl_get_monitors_count(qxl);
> +}
> +
> +RedCharDeviceWriteBuffer *char_dev_buf =
> vdagent_new_write_buffer(reds->agent_dev,
> + VD_AGENT_GRAPHICS_DEVICE_IN
> FO,
> + message_size,
> + true);
> +
> 

Re: [Spice-devel] [PATCH spice-protocol 2/8] Add the StreamMsgGraphicsDeviceInfo message

2019-01-10 Thread Jonathon Jongsma
On Wed, 2019-01-09 at 12:43 +0100, Lukáš Hrázký wrote:
> On Wed, 2019-01-09 at 02:38 -0500, Frediano Ziglio wrote:
> > > 
> > > The message contains information about the graphics device and
> > > monitor
> > > belonging to a particular video stream (which maps to a channel)
> > > from
> > > the streaming agent.
> > > 
> > > Signed-off-by: Lukáš Hrázký 
> > > ---
> > >  spice/stream-device.h | 9 +
> > >  1 file changed, 9 insertions(+)
> > > 
> > > diff --git a/spice/stream-device.h b/spice/stream-device.h
> > > index 6add42b..77d76af 100644
> > > --- a/spice/stream-device.h
> > > +++ b/spice/stream-device.h
> > > @@ -90,6 +90,8 @@ typedef enum StreamMsgType {
> > >  STREAM_TYPE_CURSOR_SET,
> > >  /* guest cursor position */
> > >  STREAM_TYPE_CURSOR_MOVE,
> > > +/* the graphics device display information message (device
> > > address and
> > > display id) */
> > > +STREAM_TYPE_DEVICE_DISPLAY_INFO,
> > >  } StreamMsgType;
> > >  
> > >  typedef enum StreamCapabilities {
> > > @@ -140,6 +142,13 @@ typedef struct StreamMsgData {
> > >  uint8_t data[0];
> > >  } StreamMsgData;
> > >  
> > > +typedef struct StreamMsgDeviceDisplayInfo {
> > 
> > No much documentation, when it is supposed to be sent?
> > In which state?
> > From the agent, from the server or both?
> 
> I'll add some documentation.
> 
> > No capabilities for a new message?
> 
> No, the streaming agent protocol is not stable yet. Better to not add
> a
> capability and make the code more complex if it's not necessary.
> We've
> discussed this before...
> 
> > > +uint32_t id;
> > 
> > I suppose is not the same "device_display_id", not clear what is
> > it.
> 
> Right, this is basically the equivalent of monitor_id, here it is
> kind
> of the ID of the stream to which the display info belongs. It's
> basically just a sequence of 0, 1, 2, ... and since only a single
> stream/monitor is supported at the moment, only a single message of
> this type is sent and it has id = 0.
> 
> Suggestions how to name it? monitor_id? stream_id?

I think stream_id may be ok.

> 
> > > +uint32_t device_display_id;
> > > +uint32_t device_address_len;
> > 
> > No limit? Is 4gb fine? I suppose you want a length to be able to
> > extend the message in the future, otherwise you can use the size
> > of the message.
> 
> How do you want me to set a limit here? In a comment?
> 
> I initially had these wrapped in a message that contained an array of
> these, hence the length. It is still unclear how this will exactly
> work
> with multi-monitor support. This message is likely going to change
> with
> that... Should I change it now?

Personally I would not try to accomodate multimonitor until we know
what we need.

> 
> > > +uint8_t device_address[0];  // a zero-terminated string
> > 
> > Encoding? Utf-8?
> 
> The contents are the address of the device, I don't think utf really
> matters here.

Well, the address format is defined as 

"pci//./.../."

So, aside from the string "pci/", the rest is just hex numbers and
dots. So we don't need to encode a bunch of special characters, just
characters within the ASCII range. But I don't suppose it would hurt to
document it as utf-8...


> 
> > I suppose by "zero-terminated" you mean if not terminated is a
> > protocol violation.
> 
> Yes. Do you prefer something else?
> 
> Cheers,
> Lukas
> 
> > > +} StreamMsgDeviceDisplayInfo;
> > > +
> > >  /* Tell to stop current stream and possibly start a new one.
> > >   * This message is sent by the host to the guest.
> > >   * Allows to communicate the codecs supported by the clients.
> > 
> > Frediano
> 
> ___
> Spice-devel mailing list
> Spice-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice-protocol 1/8] Add the VDAgentGraphicsDeviceInfo message

2019-01-10 Thread Jonathon Jongsma
On Tue, 2019-01-08 at 16:28 +0100, Lukáš Hrázký wrote:
> The message serves for passing the device address and device display
> ID
> information for all display channels from SPICE server to the
> vd_agent.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  spice/vd_agent.h | 15 +++
>  1 file changed, 15 insertions(+)
> 
> diff --git a/spice/vd_agent.h b/spice/vd_agent.h
> index dda7044..5e618b7 100644
> --- a/spice/vd_agent.h
> +++ b/spice/vd_agent.h
> @@ -91,6 +91,7 @@ enum {
>  VD_AGENT_CLIENT_DISCONNECTED,
>  VD_AGENT_MAX_CLIPBOARD,
>  VD_AGENT_AUDIO_VOLUME_SYNC,
> +VD_AGENT_GRAPHICS_DEVICE_INFO,
>  VD_AGENT_END_MESSAGE,
>  };
>  
> @@ -248,6 +249,19 @@ typedef struct SPICE_ATTR_PACKED
> VDAgentAudioVolumeSync {
>  uint16_t volume[0];
>  } VDAgentAudioVolumeSync;
>  
> +typedef struct SPICE_ATTR_PACKED VDAgentDeviceDisplayInfo {
> +uint32_t channel_id;
> +uint32_t monitor_id;
> +uint32_t device_display_id;
> +uint32_t device_address_len;
> +uint8_t device_address[0];  // a zero-terminated string
> +} VDAgentDeviceDisplayInfo;
> +
> +typedef struct SPICE_ATTR_PACKED VDAgentGraphicsDeviceInfo {
> +uint32_t count;
> +VDAgentDeviceDisplayInfo device_info[0];

Just had a thought. I wonder if we should change this member name.
Given that the type VDAgentGraphicsDeviceInfo ends with the phrase
"DeviceInfo", a variable of this type is fairly likely to be named
something like "device_info". In that case, we'd have code like
device_info.device_info[0], which is a little awkward. 

Since the type of the member ends with "DisplayInfo", maybe it could be
something like this instead?

 VDAgentDeviceDisplayInfo display_info[0]

Or device_display_info? though that gets a bit too long. If you prefer
to keep it device_info, I won't argue.

Jonathon

> +} VDAgentGraphicsDeviceInfo;
> +
>  enum {
>  VD_AGENT_CAP_MOUSE_STATE = 0,
>  VD_AGENT_CAP_MONITORS_CONFIG,
> @@ -264,6 +278,7 @@ enum {
>  VD_AGENT_CAP_MONITORS_CONFIG_POSITION,
>  VD_AGENT_CAP_FILE_XFER_DISABLED,
>  VD_AGENT_CAP_FILE_XFER_DETAILED_ERRORS,
> +VD_AGENT_CAP_GRAPHICS_DEVICE_INFO,
>  VD_AGENT_END_CAP,
>  };
>  

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [spice-gtk] gtk-session: prefer early check to agent connectivity

2019-01-10 Thread Jonathon Jongsma
This patch looks reasonable to me, but I wonder if you could expand the
commit log to indicate the steps required to trigger the warning?  In
what situation is this function (clipboard_get()) being called when the
agent is not connected? 

Jonathon




On Thu, 2019-01-10 at 16:39 +0100, Victor Toso wrote:
> From: Victor Toso 
> 
> In case the agent is disconnected, we we don't need to create the
> struct RunInfo, GMainLoop and add handlers to some signals.
> 
> Before this patch, spice_main_channel_clipboard_selection_request()
> was always called even if agent was not connected, which would log
> a critical message in agent_clipboard_request() and unnecessary call
> to spice_channel_wakeup().
> 
> This patch also removes one goto and related cleanup label.
> 
> Signed-off-by: Victor Toso 
> ---
>  src/spice-gtk-session.c | 14 ++
>  1 file changed, 6 insertions(+), 8 deletions(-)
> 
> diff --git a/src/spice-gtk-session.c b/src/spice-gtk-session.c
> index 1ccae07..373d11e 100644
> --- a/src/spice-gtk-session.c
> +++ b/src/spice-gtk-session.c
> @@ -728,6 +728,12 @@ static void clipboard_get(GtkClipboard
> *clipboard,
>  g_return_if_fail(info < SPICE_N_ELEMENTS(atom2agent));
>  g_return_if_fail(s->main != NULL);
>  
> +g_object_get(s->main, "agent-connected", _connected,
> NULL);
> +if (!agent_connected) {
> +SPICE_DEBUG("Request to guest failed as agent is not
> running");
> +return;
> +}
> +
>  ri.selection_data = selection_data;
>  ri.info = info;
>  ri.loop = g_main_loop_new(NULL, FALSE);
> @@ -744,13 +750,6 @@ static void clipboard_get(GtkClipboard
> *clipboard,
>  spice_main_channel_clipboard_selection_request(s->main,
> selection,
> atom2agent[info].
> vdagent);
>  
> -
> -g_object_get(s->main, "agent-connected", _connected,
> NULL);
> -if (!agent_connected) {
> -SPICE_DEBUG("canceled clipboard_get, before running loop");
> -goto cleanup;
> -}
> -
>  /* This is modeled on the implementation of gtk_dialog_run()
> even though
>   * these thread functions are deprecated and appears to be
> needed to avoid
>   * dead-lock from gtk_dialog_run().
> @@ -761,7 +760,6 @@ static void clipboard_get(GtkClipboard
> *clipboard,
>  gdk_threads_enter();
>  G_GNUC_END_IGNORE_DEPRECATIONS
>  
> -cleanup:
>  g_clear_pointer(, g_main_loop_unref);
>  g_signal_handler_disconnect(s->main, clipboard_handler);
>  g_signal_handler_disconnect(s->main, agent_handler);

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 2/3] QXL interface: deprecate spice_qxl_set_max_monitors

2019-01-09 Thread Jonathon Jongsma
Acked-by: Jonathon Jongsma 


On Tue, 2019-01-08 at 16:26 +0100, Lukáš Hrázký wrote:
> Replace it by spice_qxl_set_device_info. Note we can't use
> monitors_count for what's stored in max_monitors, because
> monitors_count
> denotes the length of the device_display_ids array, which
> spice_qxl_set_max_monitors doesn't touch.
> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-qxl.c   | 1 +
>  server/spice-qxl.h | 4 ++--
>  2 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 0ea424cd..6ffd8286 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -888,6 +888,7 @@ void spice_qxl_set_device_info(QXLInstance
> *instance,
>  }
>  
>  instance->st->monitors_count = device_display_id_count;
> +instance->st->max_monitors = device_display_id_count;
>  }
>  
>  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
> diff --git a/server/spice-qxl.h b/server/spice-qxl.h
> index 547d3d93..e7af5e5e 100644
> --- a/server/spice-qxl.h
> +++ b/server/spice-qxl.h
> @@ -101,9 +101,9 @@ void spice_qxl_monitors_config_async(QXLInstance
> *instance, QXLPHYSICAL monitors
>   int group_id, uint64_t cookie);
>  /* since spice 0.12.3 */
>  void spice_qxl_driver_unload(QXLInstance *instance);
> -/* since spice 0.12.6 */
> +/* since spice 0.12.6, deprecated since 0.14.2,
> spice_qxl_set_device_info replaces it */
>  void spice_qxl_set_max_monitors(QXLInstance *instance,
> -unsigned int max_monitors);
> +unsigned int max_monitors)
> SPICE_GNUC_DEPRECATED;
>  /* since spice 0.13.1 */
>  void spice_qxl_gl_scanout(QXLInstance *instance,
>int fd,

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


Re: [Spice-devel] [PATCH spice 1/3] QXL interface: add a function to identify monitors in the guest

2019-01-09 Thread Jonathon Jongsma
On Tue, 2019-01-08 at 16:26 +0100, Lukáš Hrázký wrote:
> Adds a function to let QEMU provide information to identify graphics
> devices and their monitors in the guest. The function
> (spice_qxl_set_device_info) sets the device address (e.g. a PCI path)
> and monitor ID -> device display ID mapping of displays exposed by
> given
> QXL interface.


In my previous review, I asked for a slightly more explicit explanation
of the phrase "monitor ID" in the commit log. In this case, "monitor
ID" is an ID specific to the QXL instance starting at 0 and represents
the displays that are associated with that particular QXL instance.

Perhaps it makes sense to rename this "Qxl monitor ID"?

> 
> Signed-off-by: Lukáš Hrázký 
> ---
>  server/red-qxl.c | 44 ++
>  server/spice-qxl.h   | 46
> 
>  server/spice-server.syms |  5 +
>  3 files changed, 95 insertions(+)
> 
> diff --git a/server/red-qxl.c b/server/red-qxl.c
> index 97940611..0ea424cd 100644
> --- a/server/red-qxl.c
> +++ b/server/red-qxl.c
> @@ -41,6 +41,9 @@
>  #include "red-qxl.h"
>  
>  
> +#define MAX_DEVICE_ADDRESS_LEN 256
> +#define MAX_MONITORS_COUNT 16
> +
>  struct QXLState {
>  QXLWorker qxl_worker;
>  QXLInstance *qxl;
> @@ -53,6 +56,9 @@ struct QXLState {
>  unsigned int max_monitors;
>  RedsState *reds;
>  RedWorker *worker;
> +char device_address[MAX_DEVICE_ADDRESS_LEN];
> +uint32_t device_display_ids[MAX_MONITORS_COUNT];
> +size_t monitors_count;  // length of ^^^
>  
>  pthread_mutex_t scanout_mutex;
>  SpiceMsgDisplayGlScanoutUnix scanout;
> @@ -846,6 +852,44 @@ void red_qxl_gl_draw_async_complete(QXLInstance
> *qxl)
>  red_qxl_async_complete(qxl, cookie);
>  }
>  
> +SPICE_GNUC_VISIBLE
> +void spice_qxl_set_device_info(QXLInstance *instance,
> +   const char *device_address,
> +   uint32_t device_display_id_start,
> +   uint32_t device_display_id_count)
> +{
> +g_return_if_fail(device_address != NULL);

Just a thought: what if qemu calls this function twice for the same
instance. In theory this shouldn't happen, but should we be defensive
and handle it somehow? Print a warning? Just overwrite the previous
mapping? Right now it looks like we would just overwrite.

> +
> +size_t da_len = strnlen(device_address, MAX_DEVICE_ADDRESS_LEN);
> +if (da_len >= MAX_DEVICE_ADDRESS_LEN) {
> +spice_error("Device address too long: %lu > %u", da_len,
> MAX_DEVICE_ADDRESS_LEN);

Technically, I think the format string for a size_t variable is %zu,
not %lu

> +return;
> +}
> +
> +if (device_display_id_count > MAX_MONITORS_COUNT) {
> +spice_error("Device display ID count (%u) is greater than
> limit %u",
> +device_display_id_count,
> +MAX_MONITORS_COUNT);
> +return;
> +}
> +
> +strncpy(instance->st->device_address, device_address,
> MAX_DEVICE_ADDRESS_LEN);
> +
> +g_debug("QXL Instance %d setting device address \"%s\" and
> monitor -> device display mapping:",
> +instance->id,
> +device_address);
> +
> +// store the mapping monitor_id -> device_display_id
> +for (uint32_t monitor_id = 0; monitor_id <
> device_display_id_count; ++monitor_id) {
> +uint32_t device_display_id = device_display_id_start +
> monitor_id;
> +instance->st->device_display_ids[monitor_id] =
> device_display_id;
> +g_debug("   monitor ID %u -> device display ID %u",
> +monitor_id, device_display_id);
> +}
> +
> +instance->st->monitors_count = device_display_id_count;
> +}
> +
>  void red_qxl_init(RedsState *reds, QXLInstance *qxl)
>  {
>  QXLState *qxl_state;
> diff --git a/server/spice-qxl.h b/server/spice-qxl.h
> index 0c4e75fc..547d3d93 100644
> --- a/server/spice-qxl.h
> +++ b/server/spice-qxl.h
> @@ -115,6 +115,52 @@ void spice_qxl_gl_draw_async(QXLInstance
> *instance,
>   uint32_t w, uint32_t h,
>   uint64_t cookie);
>  
> +/* since spice 0.14.2 */
> +
> +/**
> + * spice_qxl_set_device_info:
> + * @instance the QXL instance to set the path to
> + * @device_address the path of the device this QXL instance belongs
> to
> + * @device_display_id_start the starting device display ID of this
> interface,
> + *  i.e. the one monitor ID 0 maps to

perhaps reword this last line:
i.e. the device display ID of monitor ID 0

> + * @device_display_id_count the total number of device display IDs
> on this
> + *  interface
> + *
> + * Sets the device information for this QXL interface, i.e. the
> hardware
> + * address (e.g. PCI) of the graphics device and the IDs of the
> displays of the
> + * graphics device that are exposed by this interface (device
> display IDs).
> + *
> + * The supported 

[Spice-devel] [PATCH linux vdagent v3 9/9] Send display IDs to daemon when device info changes

2019-01-07 Thread Jonathon Jongsma
When the agent gets a new device info message (from the daemon), we need
to re-calculate the guest output map and send that information back down
to the daemon so that it can handle mouse input events correctly.
---
 src/vdagent/x11-randr.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 0fe2056..ed30b44 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -860,6 +860,9 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
 sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
 }
+
+// make sure daemon is up-to-date with (possibly updated) device IDs
+vdagent_x11_send_daemon_guest_xorg_res(x11, 1);
 }
 
 static int get_output_index_for_display_id(struct vdagent_x11 *x11, int 
display_id)
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v3 7/9] Use new function in vdagent_x11_send_daemon_guest_xorg_res()

2019-01-07 Thread Jonathon Jongsma
Rather than getting the current guest resolution in a
VDAgentMonitorsConfig struct and then translating it to a new struct
type for sending down to the daemon, simply use the new function that
was factored out in a previous commit and populate the message struct
directly.
---
 src/vdagent/x11-randr.c | 20 
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index fc7c30f..09b27c7 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -1061,25 +1061,21 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 int i, width = 0, height = 0, screen_count = 0;
 
 if (x11->has_xrandr) {
-VDAgentMonitorsConfig *curr;
-
 if (update)
 update_randr_res(x11, 0);
 
-curr = get_current_mon_config(x11);
-if (!curr)
-goto no_info;
-
-screen_count = curr->num_of_monitors;
+screen_count = x11->randr.res->noutput;
 res = g_new(struct vdagentd_guest_xorg_resolution, screen_count);
 
 for (i = 0; i < screen_count; i++) {
-res[i].width  = curr->monitors[i].width;
-res[i].height = curr->monitors[i].height;
-res[i].x = curr->monitors[i].x;
-res[i].y = curr->monitors[i].y;
+struct vdagentd_guest_xorg_resolution *curr = [i];
+if (!get_monitor_info_for_output_index(x11, i, >x, >y,
+   >width, >height)
+{
+g_free(res);
+goto no_info;
+}
 }
-g_free(curr);
 width  = x11->width[0];
 height = x11->height[0];
 } else if (x11->has_xinerama) {
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v3 6/9] Factor a function out of get_current_mon_config()

2019-01-07 Thread Jonathon Jongsma
When sending the guest xorg resolution to the vdagentd daemon, we get
the current resolution with this function, which returns a
VDAgentMonitorsConfig structure that must then be converted to the
structure that we send to the daemon. Rather than re-using this function
that returns the wrong type, factor out most of the functionality into a
separate function. This function can be used by a new function to return
a type appropriate for sending the xorg resolution to the daemon.

This is necessary because in the next few commits I'll be changing the
vdagentd protocol to send an additional display_id parameter to the
daemon.
---
 src/vdagent/x11-randr.c | 73 +
 1 file changed, 52 insertions(+), 21 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 747dd9d..fc7c30f 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -688,38 +688,69 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
+
+// gets monitor information about the specified output index and returns true 
if there was no error
+static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index, int *x, int *y, int *width, int *height)
+{
+g_return_val_if_fail (output_index < x11->randr.res->noutput, false);
+g_return_val_if_fail (x != NULL, false);
+g_return_val_if_fail (y != NULL, false);
+g_return_val_if_fail (width != NULL, false);
+g_return_val_if_fail (height != NULL, false);
+
+int j;
+XRRCrtcInfo *crtc = NULL;
+XRRModeInfo *mode;
+
+if (x11->randr.outputs[output_index]->ncrtc == 0)
+goto zeroed; /* Monitor disabled */
+
+for (j = 0; crtc == NULL && j < x11->randr.outputs[output_index]->ncrtc; 
j++) {
+crtc = crtc_from_id(x11, x11->randr.outputs[output_index]->crtcs[j]);
+}
+if (!crtc) {
+// error. stale xrandr info?
+return false;
+}
+
+mode = mode_from_id(x11, crtc->mode);
+if (!mode)
+goto zeroed; /* monitor disabled */
+
+*x = crtc->x;
+*y = crtc->y;
+*width = mode->width;
+*height = mode->height;
+return true;
+
+zeroed:
+*x = 0;
+*y = 0;
+*width = 0;
+*height = 0;
+return true;
+}
+
 static VDAgentMonitorsConfig *get_current_mon_config(struct vdagent_x11 *x11)
 {
 int i, num_of_monitors = 0;
-XRRModeInfo *mode;
 XRRScreenResources *res = x11->randr.res;
 VDAgentMonitorsConfig *mon_config;
 
 mon_config = g_malloc0(config_size(res->noutput));
 
 for (i = 0 ; i < res->noutput; i++) {
-int j;
-XRRCrtcInfo *crtc = NULL;
-
-if (x11->randr.outputs[i]->ncrtc == 0)
-continue; /* Monitor disabled, already zero-ed by calloc */
-if (x11->randr.outputs[i]->crtc == 0)
-continue; /* Monitor disabled */
-
-for (j = 0; crtc == NULL && j < x11->randr.outputs[i]->ncrtc; j++) {
-crtc = crtc_from_id(x11, x11->randr.outputs[i]->crtcs[j]);
-}
-if (!crtc)
+int x, y, width, height;
+if (!get_monitor_info_for_output_index(x11, i, , , , 
)) {
+syslog(LOG_WARNING, "Unable to get monitor info for output id %d", 
i);
 goto error;
+}
 
-mode = mode_from_id(x11, crtc->mode);
-if (!mode)
-continue; /* Monitor disabled, already zero-ed by calloc */
-
-mon_config->monitors[i].x  = crtc->x;
-mon_config->monitors[i].y  = crtc->y;
-mon_config->monitors[i].width  = mode->width;
-mon_config->monitors[i].height = mode->height;
+VDAgentMonConfig *mon = _config->monitors[i];
+mon->x = x;
+mon->y = y;
+mon->width = width;
+mon->height = height;
 num_of_monitors = i + 1;
 }
 mon_config->num_of_monitors = num_of_monitors;
-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v3 8/9] Send display_id down to the vdagentd daemon

2019-01-07 Thread Jonathon Jongsma
Add a display_id field to the structure that we use to send down the
list of guest display resolutions to the vdagentd daemon. This allows us
to map the spice display id to the proper X display for determining
mouse locations, etc.
---
 src/vdagent/x11-randr.c | 35 ---
 src/vdagentd-proto.h|  1 +
 src/vdagentd/uinput.c   | 23 ++-
 3 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 09b27c7..0fe2056 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -688,6 +688,34 @@ static int config_size(int num_of_monitors)
num_of_monitors * sizeof(VDAgentMonConfig);
 }
 
+static int get_display_id_for_output_index(struct vdagent_x11 *x11, int 
output_index)
+{
+// invalid output index
+if (output_index >= x11->randr.res->noutput) {
+syslog(LOG_WARNING, "Invalid output index %d (>%d)", output_index, 
x11->randr.res->noutput);
+return -1;
+}
+
+if (g_hash_table_size(x11->guest_output_map) == 0) {
+syslog(LOG_DEBUG, "No guest output map, using output index as display 
id");
+return output_index;
+}
+
+int display_id = -1;
+RROutput output_id = x11->randr.res->outputs[output_index];
+GHashTableIter iter;
+gpointer key, value;
+g_hash_table_iter_init(, x11->guest_output_map);
+while (g_hash_table_iter_next(, , )) {
+gint64 *other_id = value;
+if (*other_id == output_id) {
+return GPOINTER_TO_INT(key);
+}
+}
+
+syslog(LOG_WARNING, "Unable to find a display id for output index %d)", 
output_index);
+return display_id;
+}
 
 // gets monitor information about the specified output index and returns true 
if there was no error
 static bool get_monitor_info_for_output_index(struct vdagent_x11 *x11, int 
output_index, int *x, int *y, int *width, int *height)
@@ -1070,11 +1098,12 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct 
vdagent_x11 *x11, int update)
 for (i = 0; i < screen_count; i++) {
 struct vdagentd_guest_xorg_resolution *curr = [i];
 if (!get_monitor_info_for_output_index(x11, i, >x, >y,
-   >width, >height)
+   >width, 
>height))
 {
 g_free(res);
 goto no_info;
 }
+curr->display_id = get_display_id_for_output_index(x11, i);
 }
 width  = x11->width[0];
 height = x11->height[0];
@@ -1126,8 +1155,8 @@ no_info:
 if (x11->debug) {
 syslog(LOG_DEBUG, "Sending guest screen resolutions to vdagentd:");
 for (i = 0; i < screen_count; i++) {
-syslog(LOG_DEBUG, "   screen %d %dx%d%+d%+d", i,
-   res[i].width, res[i].height, res[i].x, res[i].y);
+syslog(LOG_DEBUG, "   screen %d %dx%d%+d%+d, id=%d", i,
+   res[i].width, res[i].height, res[i].x, res[i].y, 
res[i].display_id);
 }
 }
 
diff --git a/src/vdagentd-proto.h b/src/vdagentd-proto.h
index 243a9c6..7eff71d 100644
--- a/src/vdagentd-proto.h
+++ b/src/vdagentd-proto.h
@@ -53,6 +53,7 @@ struct vdagentd_guest_xorg_resolution {
 int height;
 int x;
 int y;
+int display_id;
 };
 
 #endif
diff --git a/src/vdagentd/uinput.c b/src/vdagentd/uinput.c
index 4f854bf..ff37e1e 100644
--- a/src/vdagentd/uinput.c
+++ b/src/vdagentd/uinput.c
@@ -175,6 +175,18 @@ static void uinput_send_event(struct vdagentd_uinput 
**uinputp,
 }
 }
 
+static struct vdagentd_guest_xorg_resolution* lookup_screen_info(struct 
vdagentd_uinput *uinput, int display_id)
+{
+int i;
+for (i = 0; i < uinput->screen_count; i++) {
+if (uinput->screen_info[i].display_id == display_id) {
+return >screen_info[i];
+}
+}
+syslog(LOG_WARNING, "Unable to find output index for display id %d", 
display_id);
+return NULL;
+}
+
 void vdagentd_uinput_do_mouse(struct vdagentd_uinput **uinputp,
 VDAgentMouseState *mouse)
 {
@@ -196,16 +208,17 @@ void vdagentd_uinput_do_mouse(struct vdagentd_uinput 
**uinputp,
 int i, down;
 
 if (*uinputp) {
-if (mouse->display_id >= uinput->screen_count) {
-syslog(LOG_WARNING, "mouse event for unknown monitor (%d >= %d)",
-   mouse->display_id, uinput->screen_count);
+struct vdagentd_guest_xorg_resolution *screen_info = 
lookup_screen_info(uinput, mouse->display_id);
+if (screen_info == NULL) {
+syslog(LOG_WARNING, "mouse event for unknown monitor %d",
+   mouse->display_id);
 return;
 }
 if (uinput->debug)
 syslog(LOG_DEBUG, "mouse-event: mon %d %dx%d", mouse->display_id,
mouse->x, mouse->y);
-mouse->x += uinput->screen_info[mouse->display_id].x;
-mouse->y += 

[Spice-devel] [PATCH linux vdagent v3 3/9] Look up and store xrandr output in display map

2019-01-07 Thread Jonathon Jongsma
Instead of storing each device address and device display ID in the hash
table, simply use the lookup_xrandr_output_for_device_info() function to
look up the ID of the xrandr output and store that in the hash table.
---
 src/vdagent/x11-priv.h  |  2 +-
 src/vdagent/x11-randr.c | 47 +++--
 src/vdagent/x11.c   | 20 ++
 3 files changed, 30 insertions(+), 39 deletions(-)

diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index 0e954cf..e487aa2 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,7 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
-GHashTable *graphics_display_infos;
+GHashTable *guest_output_map;
 };
 
 extern int (*vdagent_x11_prev_error_handler)(Display *, XErrorEvent *);
diff --git a/src/vdagent/x11-randr.c b/src/vdagent/x11-randr.c
index 4fed458..4daacc6 100644
--- a/src/vdagent/x11-randr.c
+++ b/src/vdagent/x11-randr.c
@@ -728,11 +728,6 @@ static void dump_monitors_config(struct vdagent_x11 *x11,
 }
 }
 
-typedef struct GraphicsDisplayInfo {
-char device_address[256];
-uint32_t device_display_id;
-} GraphicsDisplayInfo;
-
 // handle the device info message from the server. This will allow us to
 // maintain a mapping from spice display id to xrandr output
 void vdagent_x11_handle_graphics_device_info(struct vdagent_x11 *x11, uint8_t 
*data, size_t size)
@@ -753,31 +748,33 @@ void vdagent_x11_handle_graphics_device_info(struct 
vdagent_x11 *x11, uint8_t *d
 break;
 }
 
-GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
-
-size_t device_address_len = device_display_info->device_address_len;
-if (device_address_len > sizeof(value->device_address)) {
-syslog(LOG_ERR, "Received a device address longer than %lu, "
-   "will be truncated!", device_address_len);
-device_address_len = sizeof(value->device_address);
-}
+// make sure the string is terminated:
+
device_display_info->device_address[device_display_info->device_address_len] = 
'\0';
 
-strncpy(value->device_address,
-(char*) device_display_info->device_address,
-device_address_len);
-value->device_address[device_address_len] = '\0';  // make sure the 
string is terminated
-value->device_display_id = device_display_info->device_display_id;
+RROutput x_output;
+if (lookup_xrandr_output_for_device_info(device_display_info, 
x11->display, x11->randr.res, _output)) {
+gint64 *value = g_new(gint64, 1);
+*value = x_output;
 
-syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
-   "device_display_id: %u",
-   device_display_info->channel_id,
-   device_display_info->monitor_id,
-   value->device_address,
-   value->device_display_id);
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: 
%s, "
+   "device_display_id: %u xrandr output ID: %lu",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   device_display_info->device_address,
+   device_display_info->device_display_id,
+   x_output);
 
-g_hash_table_insert(x11->graphics_display_infos,
+g_hash_table_insert(x11->guest_output_map,
 GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
 value);
+} else {
+syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: 
%s, "
+   "device_display_id: %u xrandr output ID NOT FOUND",
+   device_display_info->channel_id,
+   device_display_info->monitor_id,
+   device_display_info->device_address,
+   device_display_info->device_display_id);
+}
 
 device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
 sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
diff --git a/src/vdagent/x11.c b/src/vdagent/x11.c
index 2473383..a456678 100644
--- a/src/vdagent/x11.c
+++ b/src/vdagent/x11.c
@@ -196,12 +196,6 @@ static gchar *vdagent_x11_get_wm_name(struct vdagent_x11 
*x11)
 #endif
 }
 
-static void graphics_display_info_destroy(gpointer gdi)
-{
-g_free(gdi);
-}
-
-
 struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
 int debug, int sync)
 {
@@ -218,6 +212,12 @@ struct vdagent_x11 *vdagent_x11_create(struct 
udscs_connection *vdagentd,
 x11->vdagentd = vdagentd;
 x11->debug = debug;
 
+x11->guest_output_map = g_hash_table_new_full(_direct_hash,
+  _direct_equal,
+ 

[Spice-devel] [PATCH linux vdagent v3 0/9] Use the PCI addr and display ID

2019-01-07 Thread Jonathon Jongsma
This is a patch set that handles the PCI address and device dispay ID
sent down to the agent by the server, and uses that to maintain a map
for looking up a particular xrandr output for a given spice display id.

This patch series builds on the patch from Lukas titled "Receive the
graphics_device_info message". It incorporates a lot of the code from my
previous POC patch series but reorganizes and restructures it.

Several of the patches in the series are semi-related cleanups that I
ran across while working on the feature.

Changes in v3:
 - Fixed a bug where the X Display was not set properly and caused a
   crash
 - moved call to vdagent_x11_send_daemon_guest_xorg_res() to outside the
   loop to avoid sending multiple times when more than one device is
   received. (Patch 9)

Changes in v2:
 - Removed some ACKed and merged patches
   - Fix typo in comment
   - Fix confusion between output index and crtc index
 - added a patch to send new display IDs when device info changes
 - multiple changes from review
   - factored out function find_device_at_pci_address()
   - No more initializing X/XRandr
   - removed goto
   - improved logging
   - etc.

Jonathon Jongsma (9):
  Add lookup_xrand_output_for_device_info()
  Move handling of DeviceInfo to vdagent_x11
  Look up and store xrandr output in display map
  Make clearer distinctions between output ids
  Use guest output map to determine xrandr output
  Factor a function out of get_current_mon_config()
  Use new function in vdagent_x11_send_daemon_guest_xorg_res()
  Send display_id down to the vdagentd daemon
  Send display IDs to daemon when device info changes

 Makefile.am   |  14 ++
 configure.ac  |   1 +
 src/vdagent/device-info.c | 490 ++
 src/vdagent/device-info.h |  27 +++
 src/vdagent/vdagent.c |  68 +-
 src/vdagent/x11-priv.h|   1 +
 src/vdagent/x11-randr.c   | 306 +++-
 src/vdagent/x11.c |   7 +
 src/vdagent/x11.h |   1 +
 src/vdagentd-proto.h  |   1 +
 src/vdagentd/uinput.c |  23 +-
 tests/test-device-info.c  | 262 
 12 files changed, 1063 insertions(+), 138 deletions(-)
 create mode 100644 src/vdagent/device-info.c
 create mode 100644 src/vdagent/device-info.h
 create mode 100644 tests/test-device-info.c

-- 
2.17.2

___
Spice-devel mailing list
Spice-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/spice-devel


[Spice-devel] [PATCH linux vdagent v3 2/9] Move handling of DeviceInfo to vdagent_x11

2019-01-07 Thread Jonathon Jongsma
---
 src/vdagent/vdagent.c   | 68 +
 src/vdagent/x11-priv.h  |  1 +
 src/vdagent/x11-randr.c | 58 +++
 src/vdagent/x11.c   | 13 
 src/vdagent/x11.h   |  1 +
 5 files changed, 74 insertions(+), 67 deletions(-)

diff --git a/src/vdagent/vdagent.c b/src/vdagent/vdagent.c
index e982a1f..aa52ee9 100644
--- a/src/vdagent/vdagent.c
+++ b/src/vdagent/vdagent.c
@@ -50,7 +50,6 @@ typedef struct VDAgent {
 struct vdagent_file_xfers *xfers;
 struct udscs_connection *conn;
 GIOChannel *x11_channel;
-GHashTable *graphics_display_infos;
 
 GMainLoop *loop;
 } VDAgent;
@@ -93,16 +92,6 @@ static GOptionEntry entries[] = {
 { NULL }
 };
 
-typedef struct GraphicsDisplayInfo {
-char device_address[256];
-uint32_t device_display_id;
-} GraphicsDisplayInfo;
-
-static void graphics_display_info_destroy(gpointer gdi)
-{
-g_free(gdi);
-}
-
 /**
  * xfer_get_download_directory
  *
@@ -167,55 +156,6 @@ static gboolean vdagent_finalize_file_xfer(VDAgent *agent)
 return TRUE;
 }
 
-static void vdagent_handle_graphics_device_info(VDAgent *agent, uint8_t *data, 
size_t size)
-{
-VDAgentGraphicsDeviceInfo *graphics_device_info = 
(VDAgentGraphicsDeviceInfo *)data;
-VDAgentDeviceDisplayInfo *device_display_info = 
graphics_device_info->device_info;
-
-void *buffer_end = data + size;
-
-syslog(LOG_INFO, "Received Graphics Device Info:");
-
-for (size_t i = 0; i < graphics_device_info->count; ++i) {
-if ((void*) device_display_info > buffer_end ||
-(void*) (_display_info->device_address +
-device_display_info->device_address_len) > buffer_end) {
-syslog(LOG_ERR, "Malformed graphics_display_info message, "
-   "extends beyond the end of the buffer");
-break;
-}
-
-GraphicsDisplayInfo *value = g_malloc(sizeof(GraphicsDisplayInfo));
-
-size_t device_address_len = device_display_info->device_address_len;
-if (device_address_len > sizeof(value->device_address)) {
-syslog(LOG_ERR, "Received a device address longer than %lu, "
-   "will be truncated!", device_address_len);
-device_address_len = sizeof(value->device_address);
-}
-
-strncpy(value->device_address,
-(char*) device_display_info->device_address,
-device_address_len);
-value->device_address[device_address_len] = '\0';  // make sure the 
string is terminated
-value->device_display_id = device_display_info->device_display_id;
-
-syslog(LOG_INFO, "   channel_id: %u monitor_id: %u device_address: %s, 
"
-   "device_display_id: %u",
-   device_display_info->channel_id,
-   device_display_info->monitor_id,
-   value->device_address,
-   value->device_display_id);
-
-g_hash_table_insert(agent->graphics_display_infos,
-GUINT_TO_POINTER(device_display_info->channel_id + 
device_display_info->monitor_id),
-value);
-
-device_display_info = (VDAgentDeviceDisplayInfo*) ((char*) 
device_display_info +
-sizeof(VDAgentDeviceDisplayInfo) + 
device_display_info->device_address_len);
-}
-}
-
 static void vdagent_quit_loop(VDAgent *agent)
 {
 /* other GMainLoop(s) might be running, quit them before agent->loop */
@@ -301,7 +241,7 @@ static void daemon_read_complete(struct udscs_connection 
**connp,
 }
 break;
 case VDAGENTD_GRAPHICS_DEVICE_INFO:
-vdagent_handle_graphics_device_info(agent, data, header->size);
+vdagent_x11_handle_graphics_device_info(agent->x11, data, 
header->size);
 break;
 case VDAGENTD_CLIENT_DISCONNECTED:
 vdagent_clipboards_release_all(agent->clipboards);
@@ -409,11 +349,6 @@ static VDAgent *vdagent_new(void)
 g_unix_signal_add(SIGHUP, vdagent_signal_handler, agent);
 g_unix_signal_add(SIGTERM, vdagent_signal_handler, agent);
 
-agent->graphics_display_infos = g_hash_table_new_full(_direct_hash,
-  _direct_equal,
-  NULL,
-  
_display_info_destroy);
-
 return agent;
 }
 
@@ -428,7 +363,6 @@ static void vdagent_destroy(VDAgent *agent)
 
 g_clear_pointer(>x11_channel, g_io_channel_unref);
 g_clear_pointer(>loop, g_main_loop_unref);
-g_hash_table_destroy(agent->graphics_display_infos);
 g_free(agent);
 }
 
diff --git a/src/vdagent/x11-priv.h b/src/vdagent/x11-priv.h
index b31b0a5..0e954cf 100644
--- a/src/vdagent/x11-priv.h
+++ b/src/vdagent/x11-priv.h
@@ -139,6 +139,7 @@ struct vdagent_x11 {
 int xrandr_minor;
 int has_xinerama;
 int dont_send_guest_xorg_res;
+GHashTable *graphics_display_infos;
 };
 
 extern int 

  1   2   3   4   5   6   7   8   9   10   >