From 555914a13bec2d6f9ea5c48dc9a955bd397e4ea1 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 3 Aug 2017 09:50:45 -0400 Subject: Add surface interface stubs in compositor example Add the wayland surface interface to the example compositor. Implement the create_surface method to create a new wlr surface from the wayland surface and add the interface. --- examples/compositor/wl_compositor.c | 91 +++++++++++++++++++++++++++++++++++-- 1 file changed, 87 insertions(+), 4 deletions(-) (limited to 'examples/compositor/wl_compositor.c') diff --git a/examples/compositor/wl_compositor.c b/examples/compositor/wl_compositor.c index 0cd73afb..4c49861c 100644 --- a/examples/compositor/wl_compositor.c +++ b/examples/compositor/wl_compositor.c @@ -3,13 +3,95 @@ #include #include "compositor.h" +static void surface_destroy(struct wl_client *client, struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static void surface_attach(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *buffer_resource, int32_t sx, int32_t sy) { + wlr_log(L_DEBUG, "TODO: surface attach"); +} + +static void surface_damage(struct wl_client *client, + struct wl_resource *resource, + int32_t x, int32_t y, int32_t width, int32_t height) { + wlr_log(L_DEBUG, "TODO: surface damage"); +} + +static void surface_frame(struct wl_client *client, + struct wl_resource *resource, uint32_t callback) { + wlr_log(L_DEBUG, "TODO: surface frame"); +} + +static void surface_set_opaque_region(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *region_resource) { + wlr_log(L_DEBUG, "TODO: surface opaque region"); +} + +static void surface_set_input_region(struct wl_client *client, + struct wl_resource *resource, + struct wl_resource *region_resource) { + + wlr_log(L_DEBUG, "TODO: surface input region"); +} + +static void surface_commit(struct wl_client *client, + struct wl_resource *resource) { + wlr_log(L_DEBUG, "TODO: surface surface commit"); +} + +static void surface_set_buffer_transform(struct wl_client *client, + struct wl_resource *resource, int transform) { + wlr_log(L_DEBUG, "TODO: surface surface buffer transform"); +} + +static void surface_set_buffer_scale(struct wl_client *client, + struct wl_resource *resource, + int32_t scale) { + wlr_log(L_DEBUG, "TODO: surface set buffer scale"); +} + + +static void surface_damage_buffer(struct wl_client *client, + struct wl_resource *resource, + int32_t x, int32_t y, int32_t width, + int32_t height) { + wlr_log(L_DEBUG, "TODO: surface damage buffer"); +} + +struct wl_surface_interface surface_interface = { + surface_destroy, + surface_attach, + surface_damage, + surface_frame, + surface_set_opaque_region, + surface_set_input_region, + surface_commit, + surface_set_buffer_transform, + surface_set_buffer_scale, + surface_damage_buffer +}; + +static void destroy_surface(struct wl_resource *resource) { + wlr_log(L_DEBUG, "TODO: destroy surface"); +} + static void wl_compositor_create_surface(struct wl_client *client, - struct wl_resource *resource, uint32_t id) { - wlr_log(L_DEBUG, "TODO: implement create_surface"); + struct wl_resource *resource, uint32_t id) { + struct wl_compositor_state *state = wl_resource_get_user_data(resource); + struct wl_resource *surface_resource = wl_resource_create(client, + &wl_surface_interface, wl_resource_get_version(resource), id); + struct wlr_surface *surface = wlr_render_surface_init(state->renderer); + wl_resource_set_implementation(surface_resource, &surface_interface, + surface, destroy_surface); + wl_resource_set_user_data(surface_resource, surface); + } static void wl_compositor_create_region(struct wl_client *client, - struct wl_resource *resource, uint32_t id) { + struct wl_resource *resource, uint32_t id) { wlr_log(L_DEBUG, "TODO: implement create_region"); } @@ -47,9 +129,10 @@ static void wl_compositor_bind(struct wl_client *wl_client, void *_state, } void wl_compositor_init(struct wl_display *display, - struct wl_compositor_state *state) { + struct wl_compositor_state *state, struct wlr_renderer *renderer) { struct wl_global *wl_global = wl_global_create(display, &wl_compositor_interface, 4, state, wl_compositor_bind); state->wl_global = wl_global; + state->renderer = renderer; wl_list_init(&state->wl_resources); } -- cgit v1.2.3 From 6610aa7ca7d170c43705c86db65f7a1f8fc8681a Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Thu, 3 Aug 2017 14:20:51 -0400 Subject: Implement shm buffer surface attach interface Implement surface_attach method. This is called when a client attaches an shm buffer with wl_surface_attach(). Implement the GLES2 interface for attaching shm buffers. This creates an opengl texture with the shm buffer contents for the surface. This commit also includes some working code to render the surfaces onto the screen for demonstration purposes. --- examples/compositor.h | 1 + examples/compositor/main.c | 13 ++++++++++++- examples/compositor/wl_compositor.c | 8 ++++++-- render/gles2/surface.c | 31 ++++++++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 4 deletions(-) (limited to 'examples/compositor/wl_compositor.c') diff --git a/examples/compositor.h b/examples/compositor.h index 0f2716fe..b04093ca 100644 --- a/examples/compositor.h +++ b/examples/compositor.h @@ -7,6 +7,7 @@ struct wl_compositor_state { struct wl_global *wl_global; struct wl_list wl_resources; struct wlr_renderer *renderer; + struct wl_list surfaces; }; void wl_compositor_init(struct wl_display *display, diff --git a/examples/compositor/main.c b/examples/compositor/main.c index 689269d0..e13fda24 100644 --- a/examples/compositor/main.c +++ b/examples/compositor/main.c @@ -28,7 +28,18 @@ void handle_output_frame(struct output_state *output, struct timespec *ts) { wlr_output_make_current(wlr_output); wlr_renderer_begin(sample->renderer, wlr_output); - // TODO: render surfaces + + struct wl_resource *_res; + float matrix[16]; + wl_list_for_each(_res, &sample->compositor.surfaces, link) { + struct wlr_surface *surface = wl_resource_get_user_data(_res); + if (surface->valid) { + wlr_surface_get_matrix(surface, &matrix, + &wlr_output->transform_matrix, 200, 200); + wlr_render_with_matrix(sample->renderer, surface, &matrix); + } + } + wlr_renderer_end(sample->renderer); wlr_output_swap_buffers(wlr_output); } diff --git a/examples/compositor/wl_compositor.c b/examples/compositor/wl_compositor.c index 4c49861c..8fbf4a93 100644 --- a/examples/compositor/wl_compositor.c +++ b/examples/compositor/wl_compositor.c @@ -10,7 +10,10 @@ static void surface_destroy(struct wl_client *client, struct wl_resource *resour static void surface_attach(struct wl_client *client, struct wl_resource *resource, struct wl_resource *buffer_resource, int32_t sx, int32_t sy) { - wlr_log(L_DEBUG, "TODO: surface attach"); + struct wlr_surface *surface = wl_resource_get_user_data(resource); + struct wl_shm_buffer *buffer = wl_shm_buffer_get(buffer_resource); + uint32_t format = wl_shm_buffer_get_format(buffer); + wlr_surface_attach_shm(surface, format, buffer); } static void surface_damage(struct wl_client *client, @@ -87,7 +90,7 @@ static void wl_compositor_create_surface(struct wl_client *client, wl_resource_set_implementation(surface_resource, &surface_interface, surface, destroy_surface); wl_resource_set_user_data(surface_resource, surface); - + wl_list_insert(&state->surfaces, wl_resource_get_link(surface_resource)); } static void wl_compositor_create_region(struct wl_client *client, @@ -135,4 +138,5 @@ void wl_compositor_init(struct wl_display *display, state->wl_global = wl_global; state->renderer = renderer; wl_list_init(&state->wl_resources); + wl_list_init(&state->surfaces); } diff --git a/render/gles2/surface.c b/render/gles2/surface.c index f730a499..300e1e46 100644 --- a/render/gles2/surface.c +++ b/render/gles2/surface.c @@ -34,6 +34,35 @@ static bool gles2_surface_attach_pixels(struct wlr_surface_state *surface, return true; } +static bool gles2_surface_attach_shm(struct wlr_surface_state *surface, + uint32_t format, struct wl_shm_buffer *buffer) { + const struct pixel_format *fmt = gl_format_for_wl_format(format); + if (!fmt || !fmt->gl_format) { + wlr_log(L_ERROR, "No supported pixel format for this surface"); + return false; + } + wl_shm_buffer_begin_access(buffer); + uint8_t *pixels = wl_shm_buffer_get_data(buffer); + int width = wl_shm_buffer_get_width(buffer); + int height = wl_shm_buffer_get_height(buffer); + int pitch = wl_shm_buffer_get_stride(buffer) / (fmt->bpp / 8); + surface->wlr_surface->width = width; + surface->wlr_surface->height = height; + surface->wlr_surface->format = format; + surface->pixel_format = fmt; + + GL_CALL(glActiveTexture(GL_TEXTURE0)); + GL_CALL(glGenTextures(1, &surface->tex_id)); + GL_CALL(glBindTexture(GL_TEXTURE_2D, surface->tex_id)); + GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch)); + GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0, + fmt->gl_format, fmt->gl_type, pixels)); + + surface->wlr_surface->valid = true; + wl_shm_buffer_end_access(buffer); + return true; +} + static void gles2_surface_get_matrix(struct wlr_surface_state *surface, float (*matrix)[16], const float (*projection)[16], int x, int y) { struct wlr_surface *_surface = surface->wlr_surface; @@ -61,7 +90,7 @@ static void gles2_surface_destroy(struct wlr_surface_state *surface) { static struct wlr_surface_impl wlr_surface_impl = { .attach_pixels = gles2_surface_attach_pixels, - // .attach_shm = TODO + .attach_shm = gles2_surface_attach_shm, .get_matrix = gles2_surface_get_matrix, .bind = gles2_surface_bind, .destroy = gles2_surface_destroy, -- cgit v1.2.3 From effea557bbd7ea4d4dda76eaf050cddf54a90346 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Fri, 4 Aug 2017 11:53:55 -0400 Subject: Implement destroying surfaces Add a signal for wlr_surface destruction on the wlr_surface that compositors can listen to to remove the surface from their state. Implement a listener for this in the example wl_compositor to remove the surface from its internal list of surfaces. Destroy the surface in the compositor destroy_surface callback given when the surface resource was created. Add a reference to the surface resource to the wlr_surface so a compositor can find it in its list of resources upon wlr_resource destruction. --- examples/compositor.h | 1 + examples/compositor/wl_compositor.c | 26 +++++++++++++++++++++++++- include/wlr/render.h | 2 ++ render/gles2/surface.c | 2 ++ 4 files changed, 30 insertions(+), 1 deletion(-) (limited to 'examples/compositor/wl_compositor.c') diff --git a/examples/compositor.h b/examples/compositor.h index b04093ca..abe1a743 100644 --- a/examples/compositor.h +++ b/examples/compositor.h @@ -8,6 +8,7 @@ struct wl_compositor_state { struct wl_list wl_resources; struct wlr_renderer *renderer; struct wl_list surfaces; + struct wl_listener destroy_surface_listener; }; void wl_compositor_init(struct wl_display *display, diff --git a/examples/compositor/wl_compositor.c b/examples/compositor/wl_compositor.c index 8fbf4a93..c9dfda56 100644 --- a/examples/compositor/wl_compositor.c +++ b/examples/compositor/wl_compositor.c @@ -78,7 +78,28 @@ struct wl_surface_interface surface_interface = { }; static void destroy_surface(struct wl_resource *resource) { - wlr_log(L_DEBUG, "TODO: destroy surface"); + struct wlr_surface *surface = wl_resource_get_user_data(resource); + wlr_surface_destroy(surface); +} + +static void destroy_surface_listener(struct wl_listener *listener, void *data) { + struct wl_compositor_state *state; + struct wlr_surface *surface = data; + state = wl_container_of(listener, state, destroy_surface_listener); + + struct wl_resource *res = NULL, *_res; + wl_list_for_each(_res, &state->surfaces, link) { + if (_res == surface->resource) { + res = _res; + break; + } + } + + if (!res) { + return; + } + + wl_list_remove(&res->link); } static void wl_compositor_create_surface(struct wl_client *client, @@ -87,10 +108,12 @@ static void wl_compositor_create_surface(struct wl_client *client, struct wl_resource *surface_resource = wl_resource_create(client, &wl_surface_interface, wl_resource_get_version(resource), id); struct wlr_surface *surface = wlr_render_surface_init(state->renderer); + surface->resource = surface_resource; wl_resource_set_implementation(surface_resource, &surface_interface, surface, destroy_surface); wl_resource_set_user_data(surface_resource, surface); wl_list_insert(&state->surfaces, wl_resource_get_link(surface_resource)); + wl_signal_add(&surface->destroy_signal, &state->destroy_surface_listener); } static void wl_compositor_create_region(struct wl_client *client, @@ -137,6 +160,7 @@ void wl_compositor_init(struct wl_display *display, &wl_compositor_interface, 4, state, wl_compositor_bind); state->wl_global = wl_global; state->renderer = renderer; + state->destroy_surface_listener.notify = destroy_surface_listener; wl_list_init(&state->wl_resources); wl_list_init(&state->surfaces); } diff --git a/include/wlr/render.h b/include/wlr/render.h index 30648a20..4de2432d 100644 --- a/include/wlr/render.h +++ b/include/wlr/render.h @@ -57,6 +57,8 @@ struct wlr_surface { bool valid; uint32_t format; int width, height; + struct wl_signal destroy_signal; + struct wl_resource *resource; }; /** diff --git a/render/gles2/surface.c b/render/gles2/surface.c index 300e1e46..33d8b0dc 100644 --- a/render/gles2/surface.c +++ b/render/gles2/surface.c @@ -84,6 +84,7 @@ static void gles2_surface_bind(struct wlr_surface_state *surface) { } static void gles2_surface_destroy(struct wlr_surface_state *surface) { + wl_signal_emit(&surface->wlr_surface->destroy_signal, surface->wlr_surface); GL_CALL(glDeleteTextures(1, &surface->tex_id)); free(surface); } @@ -100,5 +101,6 @@ struct wlr_surface *gles2_surface_init() { struct wlr_surface_state *state = calloc(sizeof(struct wlr_surface_state), 1); struct wlr_surface *surface = wlr_surface_init(state, &wlr_surface_impl); state->wlr_surface = surface; + wl_signal_init(&surface->destroy_signal); return surface; } -- cgit v1.2.3