mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-13 14:00:09 +00:00
broadway: Add support for uploading textures to daemon
This commit is contained in:
parent
f31d7e1f91
commit
48d587d255
@ -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 {
|
||||
@ -194,6 +196,18 @@ typedef struct {
|
||||
guint32 height;
|
||||
} BroadwayRequestUpdate;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
guint32 offset;
|
||||
guint32 size;
|
||||
} BroadwayRequestUploadTexture;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
} BroadwayRequestReleaseTexture;
|
||||
|
||||
typedef struct {
|
||||
BroadwayRequestBase base;
|
||||
guint32 id;
|
||||
@ -248,6 +262,8 @@ typedef union {
|
||||
BroadwayRequestTranslate translate;
|
||||
BroadwayRequestFocusWindow focus_window;
|
||||
BroadwayRequestSetShowKeyboard set_show_keyboard;
|
||||
BroadwayRequestUploadTexture upload_texture;
|
||||
BroadwayRequestReleaseTexture release_texture;
|
||||
} BroadwayRequest;
|
||||
|
||||
typedef enum {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user