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 <[email protected]> --- 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 _______________________________________________ wayland-devel mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/wayland-devel
