From d72037cc78f6ebf00dad060b096e230e47e37e83 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Tue, 21 Jun 2011 16:33:27 +0200 Subject: [PATCH 1/2] compositor: Send frame event after redraw --- compositor/compositor.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/compositor/compositor.c b/compositor/compositor.c index bb4d56dd..0dcfc7ce 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -578,16 +578,8 @@ WL_EXPORT void wlsc_output_finish_frame(struct wlsc_output *output, int msecs) { struct wlsc_compositor *compositor = output->compositor; - struct wlsc_surface *es; struct wlsc_animation *animation, *next; - wl_list_for_each(es, &compositor->surface_list, link) { - if (es->output == output) { - wl_display_post_frame(compositor->wl_display, - &es->surface, msecs); - } - } - output->finished = 1; wl_event_source_timer_update(compositor->timer_source, 5); @@ -598,6 +590,20 @@ wlsc_output_finish_frame(struct wlsc_output *output, int msecs) animation->frame(animation, output, msecs); } +static void +wlsc_output_finish_redraw(struct wlsc_output *output, int msecs) +{ + struct wlsc_compositor *compositor = output->compositor; + struct wlsc_surface *es; + + wl_list_for_each(es, &compositor->surface_list, link) { + if (es->output == output) { + wl_display_post_frame(compositor->wl_display, + &es->surface, msecs); + } + } +} + WL_EXPORT void wlsc_output_damage(struct wlsc_output *output) { @@ -709,6 +715,9 @@ wlsc_output_repaint(struct wlsc_output *output) pixman_region32_union(&ec->damage_region, &ec->damage_region, &total_damage); + + wlsc_output_finish_redraw(output, + wlsc_compositor_get_time()); return; } } @@ -747,6 +756,8 @@ wlsc_output_repaint(struct wlsc_output *output) if (ec->fade.spring.current > 0.001) fade_output(output, ec->fade.spring.current, &total_damage); + + wlsc_output_finish_redraw(output, wlsc_compositor_get_time()); } static int From 0628626d5546d0ad684667a1250778fbadab21b1 Mon Sep 17 00:00:00 2001 From: Benjamin Franzke Date: Fri, 6 May 2011 19:12:33 +0200 Subject: [PATCH 2/2] Implement buffer.release event --- compositor/compositor.c | 79 +++++++++++++++++++++++++++++++++++++++++ compositor/compositor.h | 6 ++++ 2 files changed, 85 insertions(+) diff --git a/compositor/compositor.c b/compositor/compositor.c index 0dcfc7ce..4eb2b35d 100644 --- a/compositor/compositor.c +++ b/compositor/compositor.c @@ -162,6 +162,32 @@ wlsc_spring_done(struct wlsc_spring *spring) fabs(spring->current - spring->target) < 0.0002; } +static void +surface_handle_buffer_destroy(struct wl_listener *listener, + struct wl_resource *resource, uint32_t time) +{ + struct wlsc_surface *es = container_of(listener, struct wlsc_surface, + buffer_destroy_listener); + struct wl_buffer *buffer = (struct wl_buffer *) resource; + + if (es->buffer == buffer) + es->buffer = NULL; +} + +static void +output_handle_scanout_buffer_destroy(struct wl_listener *listener, + struct wl_resource *resource, + uint32_t time) +{ + struct wlsc_output *output = + container_of(listener, struct wlsc_output, + scanout_buffer_destroy_listener); + struct wl_buffer *buffer = (struct wl_buffer *) resource; + + if (output->scanout_buffer == buffer) + output->scanout_buffer = NULL; +} + WL_EXPORT struct wlsc_surface * wlsc_surface_create(struct wlsc_compositor *compositor, int32_t x, int32_t y, int32_t width, int32_t height) @@ -192,6 +218,11 @@ wlsc_surface_create(struct wlsc_compositor *compositor, surface->width = width; surface->height = height; + surface->buffer = NULL; + + surface->buffer_destroy_listener.func = surface_handle_buffer_destroy; + wl_list_init(&surface->buffer_destroy_listener.link); + surface->transform = NULL; return surface; @@ -243,6 +274,8 @@ destroy_surface(struct wl_resource *resource, struct wl_client *client) else glDeleteTextures(1, &surface->saved_texture); + if (surface->buffer) + wl_list_remove(&surface->buffer_destroy_listener.link); if (surface->image != EGL_NO_IMAGE_KHR) compositor->destroy_image(compositor->display, @@ -312,6 +345,9 @@ wlsc_sprite_attach(struct wlsc_sprite *sprite, struct wl_surface *surface) } es->visual = sprite->visual; + + if (es->buffer) + es->buffer = NULL; } enum sprite_usage { @@ -574,12 +610,33 @@ wlsc_compositor_damage_all(struct wlsc_compositor *compositor) wlsc_output_damage(output); } +static inline void +wlsc_buffer_post_release(struct wl_buffer *buffer) +{ + if (buffer->client == NULL) { + fprintf(stderr, "buffer.release warning: buffer.client: %p\n", + buffer->client); + return; + } + + wl_client_post_event(buffer->client, + &buffer->resource.object, + WL_BUFFER_RELEASE); +} + WL_EXPORT void wlsc_output_finish_frame(struct wlsc_output *output, int msecs) { struct wlsc_compositor *compositor = output->compositor; struct wlsc_animation *animation, *next; + if (output->scanout_buffer) { + if (--output->scanout_buffer->busy_count == 0) + wlsc_buffer_post_release(output->scanout_buffer); + + output->scanout_buffer = NULL; + } + output->finished = 1; wl_event_source_timer_update(compositor->timer_source, 5); @@ -716,6 +773,13 @@ wlsc_output_repaint(struct wlsc_output *output) &ec->damage_region, &total_damage); + output->scanout_buffer = es->buffer; + output->scanout_buffer->busy_count++; + + wl_list_remove(&output->scanout_buffer_destroy_listener.link); + wl_list_insert(output->scanout_buffer->resource.destroy_listener_list.prev, + &output->scanout_buffer_destroy_listener.link); + wlsc_output_finish_redraw(output, wlsc_compositor_get_time()); return; @@ -869,6 +933,17 @@ surface_attach(struct wl_client *client, { struct wlsc_surface *es = (struct wlsc_surface *) surface; + buffer->busy_count++; + + if (es->buffer && es->buffer->busy_count > 0) + if (--es->buffer->busy_count == 0) + wlsc_buffer_post_release(es->buffer); + + es->buffer = buffer; + wl_list_remove(&es->buffer_destroy_listener.link); + wl_list_insert(es->buffer->resource.destroy_listener_list.prev, + &es->buffer_destroy_listener.link); + es->x += x; es->y += y; es->width = buffer->width; @@ -1641,6 +1716,10 @@ wlsc_output_init(struct wlsc_output *output, struct wlsc_compositor *c, output->finished = 1; wlsc_output_move(output, x, y); + output->scanout_buffer_destroy_listener.func = + output_handle_scanout_buffer_destroy; + wl_list_init(&output->scanout_buffer_destroy_listener.link); + output->object.interface = &wl_output_interface; wl_display_add_object(c->wl_display, &output->object); wl_display_add_global(c->wl_display, &output->object, diff --git a/compositor/compositor.h b/compositor/compositor.h index 2546d58f..2b7c11d2 100644 --- a/compositor/compositor.h +++ b/compositor/compositor.h @@ -65,6 +65,9 @@ struct wlsc_output { int repaint_needed; int finished; + struct wl_buffer *scanout_buffer; + struct wl_listener scanout_buffer_destroy_listener; + int (*prepare_render)(struct wlsc_output *output); int (*present)(struct wlsc_output *output); int (*prepare_scanout_surface)(struct wlsc_output *output, @@ -235,6 +238,9 @@ struct wlsc_surface { struct wlsc_output *fullscreen_output; EGLImageKHR image; + + struct wl_buffer *buffer; + struct wl_listener buffer_destroy_listener; }; void