[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