[RFC wayland 18/18] protocol: Add hooks for network transparency

Derek Foreman derekf at osg.samsung.com
Tue Feb 9 16:56:05 UTC 2016


Add hooks to all the wl_buffer protocol and code to track damage in the
client side library for uploading data that needs to pass over the
network.

Signed-off-by: Derek Foreman <derekf at osg.samsung.com>
---
 Makefile.am          |   1 +
 protocol/wayland.xml |  20 ++--
 src/network-client.c | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 280 insertions(+), 10 deletions(-)
 create mode 100644 src/network-client.c

diff --git a/Makefile.am b/Makefile.am
index f180c17..63d2bcc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -85,6 +85,7 @@ libwayland_client_la_CFLAGS = $(FFI_CFLAGS) $(AM_CFLAGS) -pthread
 libwayland_client_la_LIBADD = $(FFI_LIBS) libwayland-private.la libwayland-util.la -lrt -lm
 libwayland_client_la_LDFLAGS = -version-info 3:0:3
 libwayland_client_la_SOURCES =			\
+	src/network-client.c			\
 	src/wayland-client.c
 
 nodist_libwayland_client_la_SOURCES =		\
diff --git a/protocol/wayland.xml b/protocol/wayland.xml
index c683df8..9d0d682 100644
--- a/protocol/wayland.xml
+++ b/protocol/wayland.xml
@@ -183,7 +183,7 @@
       surfaces into one displayable output.
     </description>
 
-    <request name="create_surface">
+    <request name="create_surface" hooked="true">
       <description summary="create new surface">
 	Ask the compositor to create a new surface.
       </description>
@@ -209,7 +209,7 @@
       a surface or for many small buffers.
     </description>
 
-    <request name="create_buffer">
+    <request name="create_buffer" hooked="true">
       <description summary="create a buffer from the pool">
 	Create a wl_buffer object from the pool.
 
@@ -232,7 +232,7 @@
       <arg name="format" type="uint"/>
     </request>
 
-    <request name="destroy" type="destructor">
+    <request name="destroy" type="destructor" hooked="true">
       <description summary="destroy the pool">
 	Destroy the shared memory pool.
 
@@ -242,7 +242,7 @@
       </description>
     </request>
 
-    <request name="resize">
+    <request name="resize" hooked="true">
       <description summary="change the size of the pool mapping">
 	This request will cause the server to remap the backing memory
 	for the pool from the file descriptor passed when the pool was
@@ -347,7 +347,7 @@
       <entry name="yvu444" value="0x34325659"/>
     </enum>
 
-    <request name="create_pool">
+    <request name="create_pool" hooked="true">
       <description summary="create a shm pool">
 	Create a new wl_shm_pool object.
 
@@ -380,7 +380,7 @@
       updates the contents is defined by the buffer factory interface.
     </description>
 
-    <request name="destroy" type="destructor">
+    <request name="destroy" type="destructor" hooked="true">
       <description summary="destroy a buffer">
 	Destroy a buffer. If and how you need to release the backing
 	storage is defined by the buffer factory interface.
@@ -1342,7 +1342,7 @@
       </description>
     </request>
 
-    <request name="attach">
+    <request name="attach" hooked="true">
       <description summary="set the surface contents">
 	Set a buffer as the content of this surface.
 
@@ -1390,7 +1390,7 @@
       <arg name="y" type="int"/>
     </request>
 
-    <request name="damage">
+    <request name="damage" hooked="true">
       <description summary="mark part of the surface damaged">
 	This request is used to describe the regions where the pending
 	buffer is different from the current surface contents, and where
@@ -1519,7 +1519,7 @@
       <arg name="region" type="object" interface="wl_region" allow-null="true"/>
     </request>
 
-    <request name="commit">
+    <request name="commit" hooked="true">
       <description summary="commit pending surface state">
 	Surface state (input, opaque, and damage regions, attached buffers,
 	etc.) is double-buffered. Protocol requests modify the pending
@@ -1630,7 +1630,7 @@
     </request>
 
     <!-- Version 4 additions -->
-    <request name="damage_buffer" since="4">
+    <request name="damage_buffer" since="4" hooked="true">
       <description summary="mark part of the surface damaged using buffer co-ordinates">
 	This request is used to describe the regions where the pending
 	buffer is different from the current surface contents, and where
diff --git a/src/network-client.c b/src/network-client.c
new file mode 100644
index 0000000..7c3f8c2
--- /dev/null
+++ b/src/network-client.c
@@ -0,0 +1,269 @@
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <protocol/wayland-client-protocol.h>
+
+struct pool_hook_data {
+	void *address;
+	size_t size;
+	int fd;
+	int refcount;
+};
+
+struct buffer_hook_data {
+	struct pool_hook_data *pdata;
+	int32_t offset;
+	int32_t width;
+	int32_t height;
+	int32_t stride;
+};
+
+struct surface_hook_data {
+	struct wl_buffer *buffer;
+	int x, y, width, height;
+};
+
+static void
+pool_unref(struct pool_hook_data *pool)
+{
+	pool->refcount--;
+	if (pool->refcount)
+		return;
+
+	munmap(pool->address, pool->size);
+	close(pool->fd);
+	free(pool);
+}
+
+static void
+pool_ref(struct pool_hook_data *pool)
+{
+	pool->refcount++;
+}
+
+WL_EXPORT void *
+wl_compositor_create_surface_pre_hook(struct wl_compositor *compositor)
+{
+	struct surface_hook_data *data;
+
+	if (!wl_proxy_get_remote((void *)compositor))
+		return NULL;
+
+	data = malloc(sizeof(struct surface_hook_data));
+	if (!data)
+		return NULL;
+
+	data->x = 0;
+	data->y = 0;
+	data->width = INT32_MAX;
+	data->height = INT32_MAX;
+
+	return data;
+}
+
+WL_EXPORT void *
+wl_shm_create_pool_pre_hook(struct wl_shm *wl_shm, int32_t fd, int32_t size)
+{
+	struct pool_hook_data *pdata;
+
+	if (!wl_proxy_get_remote((void *)wl_shm))
+		return NULL;
+
+	pdata = malloc(sizeof(struct pool_hook_data));
+	pdata->fd = fd;
+	pdata->address = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+			      fd, 0);
+	pdata->size = size;
+	pdata->refcount = 1;
+	return pdata;
+}
+
+WL_EXPORT void
+wl_shm_pool_destroy_pre_hook(struct wl_shm_pool *pool)
+{
+	struct pool_hook_data *pdata;
+
+	if (!wl_proxy_get_remote((void *)pool))
+		return;
+
+	pdata = wl_proxy_get_hook_data((void *) pool);
+	pool_unref(pdata);
+}
+
+WL_EXPORT void *
+wl_shm_pool_create_buffer_pre_hook(struct wl_shm_pool *pool,  int32_t offset,
+				   int32_t width, int32_t height,
+				   int32_t stride, uint32_t format)
+{
+	struct buffer_hook_data *data;
+	struct pool_hook_data *pdata;
+
+	if (!wl_proxy_get_remote((void *)pool))
+		return NULL;
+
+	data = malloc(sizeof(struct buffer_hook_data));
+	pdata = wl_proxy_get_hook_data((void *) pool);
+	data->pdata = pdata;
+	pool_ref(pdata);
+	data->offset = offset;
+	data->stride = stride;
+	data->width = width;
+	data->height = height;
+	return data;
+}
+
+WL_EXPORT void
+wl_shm_pool_resize_pre_hook(struct wl_shm_pool *pool, int32_t size)
+{
+	struct pool_hook_data *pdata;
+
+	if (!wl_proxy_get_remote((void *)pool))
+		return;
+
+	pdata = wl_proxy_get_hook_data((void *)pool);
+	munmap(pdata->address, pdata->size);
+	pdata->address = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED,
+			      pdata->fd, 0);
+	pdata->size = size;
+}
+
+WL_EXPORT void
+wl_surface_attach_pre_hook(struct wl_surface *wl_surface,
+			   struct wl_buffer *buffer,
+			   int32_t x,
+			   int32_t y)
+{
+	struct surface_hook_data *data;
+
+	if (!wl_proxy_get_remote((void *)wl_surface))
+		return;
+
+	data = wl_proxy_get_hook_data((void *)wl_surface);
+	data->buffer = buffer;
+}
+
+WL_EXPORT void
+wl_surface_damage_pre_hook(struct wl_surface *wl_surface, int32_t x,
+			   int32_t y, int32_t width, int32_t height)
+{
+	struct surface_hook_data *data;
+
+	if (!wl_proxy_get_remote((void *)wl_surface))
+		return;
+
+	data = wl_proxy_get_hook_data((void *)wl_surface);
+	data->x = 0;
+	data->y = 0;
+	data->width = INT32_MAX;
+	data->height = INT32_MAX;
+}
+
+WL_EXPORT void
+wl_surface_damage_buffer_pre_hook(struct wl_surface *wl_surface, int32_t x,
+				  int32_t y, int32_t width, int32_t height)
+{
+	struct surface_hook_data *data;
+
+	if (!wl_proxy_get_remote((void *)wl_surface))
+		return;
+
+	data = wl_proxy_get_hook_data((void *)wl_surface);
+
+	if (data->width == 0 || data->height == 0) {
+		data->x = x;
+		data->y = y;
+		data->width = width;
+		data->height = height;
+	} else {
+		if (x < data->x) {
+			data->width += data->x - x;
+			data->x = x;
+			if (width > data->width)
+				data->width = width;
+		}
+		if (x > data->x) {
+			if (width + x > data->x + data->width)
+				data->width = width + x - data->x;
+		}
+
+		if (y < data->y) {
+			data->height += data->y - y;
+			data->y = y;
+			if (height > data->height)
+				data->height = height;
+		}
+		if (y > data->y) {
+			if (height + y > data->y + data->height)
+				data->height = height + y - data->y;
+		}
+	}
+}
+
+WL_EXPORT void
+wl_surface_commit_pre_hook(struct wl_surface *wl_surface)
+{
+	struct surface_hook_data *data;
+	struct buffer_hook_data *bdata;
+	struct wl_array content;
+	char *ugh, *cptr;
+	int i, j, count = 0, offset = 0;
+
+	if (!wl_proxy_get_remote((void *)wl_surface))
+		return;
+
+	data = wl_proxy_get_hook_data((void *)wl_surface);
+	bdata = wl_proxy_get_hook_data((void *)data->buffer);
+	if (data->width + data->x > bdata->width)
+		data->width = bdata->width - data->x;
+	if (data->height + data->y > bdata->height)
+		data->height = bdata->height - data->y;
+
+	wl_array_init(&content);
+	cptr = bdata->pdata->address + bdata->offset;
+	for (i = data->y; i < data->y + data->height; i++)
+		for (j = data->x; j < data->x + data->width; j++) {
+			if (count > 1000) {
+				wl_buffer_transmit(data->buffer, data->x,
+						   data->y, data->width,
+						   data->height, offset,
+						   &content);
+				wl_array_release(&content);
+				wl_array_init(&content);
+				offset += count;
+				count = 0;
+			}
+			count++;
+			ugh = wl_array_add(&content, 4);
+			*ugh = *(cptr + i * bdata->stride + j * 4);
+			*(ugh + 1) = *(cptr + i * bdata->stride + j * 4 + 1);
+			*(ugh + 2) = *(cptr + i * bdata->stride + j * 4 + 2);
+			*(ugh + 3) = *(cptr + i * bdata->stride + j * 4 + 3);
+	}
+	wl_buffer_transmit(data->buffer, data->x, data->y, data->width,
+			   data->height, offset, &content);
+	wl_array_release(&content);
+	data->x = 0;
+	data->y = 0;
+	data->width = 0;
+	data->height = 0;
+}
+
+WL_EXPORT void
+wl_buffer_destroy_pre_hook(struct wl_buffer *wl_buffer)
+{
+	struct buffer_hook_data *bdata;
+
+	if (!wl_proxy_get_remote((void *)wl_buffer))
+		return;
+
+	bdata = wl_proxy_get_hook_data((void *)wl_buffer);
+	if (bdata) {
+		pool_unref(bdata->pdata);
+		free(bdata);
+	}
+}
-- 
2.7.0



More information about the wayland-devel mailing list