[gtk+/wip/alexl/broadway4: 5/5] broadway: Add support for uploading textures to daemon



commit e973ee2e0eb7d18d566aa598cb437483a35cbfc7
Author: Alexander Larsson <alexl redhat com>
Date:   Fri Nov 17 16:40:06 2017 +0100

    broadway: Add support for uploading textures to daemon

 gdk/broadway/broadway-protocol.h  |   18 +++++-
 gdk/broadway/broadwayd.c          |   53 ++++++++++++++++
 gdk/broadway/gdkbroadway-server.c |  121 ++++++++++++++++++++++++++++++++++++-
 gdk/broadway/gdkbroadway-server.h |    4 +
 4 files changed, 194 insertions(+), 2 deletions(-)
---
diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h
index 0e82e94..58e6434 100644
--- a/gdk/broadway/broadway-protocol.h
+++ b/gdk/broadway/broadway-protocol.h
@@ -157,7 +157,9 @@ typedef enum {
   BROADWAY_REQUEST_GRAB_POINTER,
   BROADWAY_REQUEST_UNGRAB_POINTER,
   BROADWAY_REQUEST_FOCUS_WINDOW,
-  BROADWAY_REQUEST_SET_SHOW_KEYBOARD
+  BROADWAY_REQUEST_SET_SHOW_KEYBOARD,
+  BROADWAY_REQUEST_UPLOAD_TEXTURE,
+  BROADWAY_REQUEST_RELEASE_TEXTURE,
 } BroadwayRequestType;
 
 typedef struct {
@@ -197,6 +199,18 @@ typedef struct {
 typedef struct {
   BroadwayRequestBase base;
   guint32 id;
+  guint32 offset;
+  guint32 size;
+} BroadwayRequestUploadTexture;
+
+typedef struct {
+  BroadwayRequestBase base;
+  guint32 id;
+} BroadwayRequestReleaseTexture;
+
+typedef struct {
+  BroadwayRequestBase base;
+  guint32 id;
   guint32 owner_events;
   guint32 event_mask;
   guint32 time_;
@@ -248,6 +262,8 @@ typedef union {
   BroadwayRequestTranslate translate;
   BroadwayRequestFocusWindow focus_window;
   BroadwayRequestSetShowKeyboard set_show_keyboard;
+  BroadwayRequestUploadTexture upload_texture;
+  BroadwayRequestReleaseTexture release_texture;
 } BroadwayRequest;
 
 typedef enum {
diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c
index f29eb77..d26c5dc 100644
--- a/gdk/broadway/broadwayd.c
+++ b/gdk/broadway/broadwayd.c
@@ -8,6 +8,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <locale.h>
+#include <errno.h>
 
 #include <glib.h>
 #include <gio/gio.h>
@@ -56,6 +57,7 @@ typedef struct  {
   GList *windows;
   guint disconnect_idle;
   GList *fds;
+  GHashTable *textures;
 } BroadwayClient;
 
 static void
@@ -75,6 +77,7 @@ client_free (BroadwayClient *client)
   g_string_free (client->buffer, TRUE);
   g_slist_free_full (client->serial_mappings, g_free);
   g_list_free_full (client->fds, close_fd);
+  g_hash_table_destroy (client->textures);
   g_free (client);
 }
 
@@ -218,6 +221,7 @@ client_handle_request (BroadwayClient *client,
   BroadwayReplyUngrabPointer reply_ungrab_pointer;
   cairo_surface_t *surface;
   guint32 before_serial, now_serial;
+  int fd;
 
   before_serial = broadway_server_get_next_serial (server);
 
@@ -286,6 +290,54 @@ client_handle_request (BroadwayClient *client,
          cairo_surface_destroy (surface);
        }
       break;
+    case BROADWAY_REQUEST_UPLOAD_TEXTURE:
+      if (client->fds == NULL)
+        g_warning ("FD passing mismatch");
+      else
+        {
+          char *data, *p;
+          gsize to_read;
+          gssize num_read;
+          GBytes *texture;
+
+          fd = GPOINTER_TO_INT (client->fds->data);
+          client->fds = g_list_delete_link (client->fds, client->fds);
+
+          data = g_malloc (request->upload_texture.size);
+          to_read = request->upload_texture.size;
+          lseek (fd, request->upload_texture.offset, SEEK_SET);
+
+          p = data;
+          do
+            {
+              num_read = read (fd, p, to_read);
+              if (num_read == -1 && errno == EAGAIN)
+                continue;
+
+              if (num_read > 0)
+                {
+                  p += num_read;
+                  to_read -= num_read;
+                }
+              else
+                {
+                  g_warning ("Unexpected short read of texture");
+                  break;
+                }
+            }
+          while (to_read > 0);
+          close (fd);
+
+          texture = g_bytes_new_take (data, request->upload_texture.size);
+          g_hash_table_replace (client->textures,
+                                GINT_TO_POINTER (request->release_texture.id),
+                                texture);
+        }
+      break;
+    case BROADWAY_REQUEST_RELEASE_TEXTURE:
+      g_hash_table_remove (client->textures, GINT_TO_POINTER (request->release_texture.id));
+
+      break;
     case BROADWAY_REQUEST_MOVE_RESIZE:
       broadway_server_window_move_resize (server,
                                          request->move_resize.id,
@@ -429,6 +481,7 @@ incoming_client (GSocketService    *service,
   client = g_new0 (BroadwayClient, 1);
   client->id = client_id_count++;
   client->connection = g_object_ref (connection);
+  client->textures = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, 
(GDestroyNotify)g_bytes_unref);
 
   input = g_io_stream_get_input_stream (G_IO_STREAM (client->connection));
   client->in = input;
diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c
index 57cb48d..2ee75ab 100644
--- a/gdk/broadway/gdkbroadway-server.c
+++ b/gdk/broadway/gdkbroadway-server.c
@@ -1,5 +1,9 @@
 #include "config.h"
 
+#ifdef HAVE_LINUX_MEMFD_H
+#include <linux/memfd.h>
+#endif
+
 #ifdef HAVE_SYS_MMAN_H
 #include <sys/mman.h>
 #endif
@@ -9,6 +13,7 @@
 #include "gdkbroadway-server.h"
 
 #include "gdkprivate-broadway.h"
+#include <gdk/gdktextureprivate.h>
 
 #include <glib.h>
 #include <glib/gprintf.h>
@@ -35,6 +40,7 @@ struct _GdkBroadwayServer {
   GObject parent_instance;
 
   guint32 next_serial;
+  guint32 next_texture_id;
   GSocketConnection *connection;
 
   guint32 recv_buffer_size;
@@ -197,7 +203,6 @@ gdk_broadway_server_send_message_with_size (GdkBroadwayServer *server, BroadwayR
           exit (1);
         }
 
-      g_print ("socket send message wrote %d of %d\n", (int)bytes_written, (int)size);
       buf += bytes_written;
       size -= bytes_written;
 
@@ -775,6 +780,120 @@ _gdk_broadway_server_window_update (GdkBroadwayServer *server,
                                    BROADWAY_REQUEST_UPDATE);
 }
 
+static int
+open_shared_memory (void)
+{
+  static gboolean force_shm_open = FALSE;
+  int ret = -1;
+
+#if !defined (__NR_memfd_create)
+  force_shm_open = TRUE;
+#endif
+
+  do
+    {
+#if defined (__NR_memfd_create)
+      if (!force_shm_open)
+        {
+          ret = syscall (__NR_memfd_create, "gdk-broadway", MFD_CLOEXEC);
+
+          /* fall back to shm_open until debian stops shipping 3.16 kernel
+           * See bug 766341
+           */
+          if (ret < 0 && errno == ENOSYS)
+            force_shm_open = TRUE;
+        }
+#endif
+
+      if (force_shm_open)
+        {
+          char name[NAME_MAX - 1] = "";
+
+          sprintf (name, "/gdk-broadway-%x", g_random_int ());
+
+          ret = shm_open (name, O_CREAT | O_EXCL | O_RDWR | O_CLOEXEC, 0600);
+
+          if (ret >= 0)
+            shm_unlink (name);
+          else if (errno == EEXIST)
+            continue;
+        }
+    }
+  while (ret < 0 && errno == EINTR);
+
+  if (ret < 0)
+    g_critical (G_STRLOC ": creating shared memory file (using %s) failed: %m",
+                force_shm_open? "shm_open" : "memfd_create");
+
+  return ret;
+}
+
+typedef struct {
+  int fd;
+  gsize size;
+} PngData;
+
+static cairo_status_t
+write_png_cb (void         *closure,
+              const guchar *data,
+              unsigned int  length)
+{
+  PngData *png_data = closure;
+  int fd = png_data->fd;
+
+  while (length)
+    {
+      gssize ret = write (fd, data, length);
+
+      if (ret <= 0)
+        return CAIRO_STATUS_WRITE_ERROR;
+
+      png_data->size += ret;
+      length -= ret;
+      data += ret;
+    }
+
+  return CAIRO_STATUS_SUCCESS;
+}
+
+guint32
+gdk_broadway_server_upload_texture (GdkBroadwayServer *server,
+                                    GdkTexture        *texture)
+{
+  guint32 id;
+  cairo_surface_t *surface = gdk_texture_download_surface (texture);
+  BroadwayRequestUploadTexture msg;
+  PngData data;
+
+  id = ++server->next_texture_id;
+
+  data.fd = open_shared_memory ();
+  data.size = 0;
+  cairo_surface_write_to_png_stream (surface, write_png_cb, &data);
+
+  msg.id = id;
+  msg.offset = 0;
+  msg.size = data.size;
+
+  /* This passes ownership of fd */
+  gdk_broadway_server_send_fd_message (server, msg,
+                                       BROADWAY_REQUEST_UPLOAD_TEXTURE, data.fd);
+
+  return id;
+}
+
+void
+gdk_broadway_server_release_texture (GdkBroadwayServer *server,
+                                     guint32            id)
+{
+  BroadwayRequestReleaseTexture msg;
+
+  msg.id = id;
+
+  gdk_broadway_server_send_message (server, msg,
+                                    BROADWAY_REQUEST_RELEASE_TEXTURE);
+}
+
 gboolean
 _gdk_broadway_server_window_move_resize (GdkBroadwayServer *server,
                                         gint id,
diff --git a/gdk/broadway/gdkbroadway-server.h b/gdk/broadway/gdkbroadway-server.h
index 89a3076..ea16e55 100644
--- a/gdk/broadway/gdkbroadway-server.h
+++ b/gdk/broadway/gdkbroadway-server.h
@@ -59,6 +59,10 @@ gboolean           _gdk_broadway_server_window_translate         (GdkBroadwaySer
                                                                  cairo_region_t     *area,
                                                                  gint                dx,
                                                                  gint                dy);
+guint32             gdk_broadway_server_upload_texture           (GdkBroadwayServer  *server,
+                                                                  GdkTexture         *texture);
+void                gdk_broadway_server_release_texture          (GdkBroadwayServer  *server,
+                                                                  guint32             id);
 cairo_surface_t   *_gdk_broadway_server_create_surface           (int                 width,
                                                                  int                 height);
 void               _gdk_broadway_server_window_update            (GdkBroadwayServer  *server,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]