[gtk+/wip/alexl/broadway4: 5/5] broadway: Add support for uploading textures to daemon
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk+/wip/alexl/broadway4: 5/5] broadway: Add support for uploading textures to daemon
- Date: Sat, 18 Nov 2017 11:22:51 +0000 (UTC)
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]