summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Franzke <benjaminfranzke@googlemail.com>2011-05-06 19:12:33 +0200
committerBenjamin Franzke <benjaminfranzke@googlemail.com>2011-06-21 19:03:59 +0200
commit73e01aba6582b2e2371083f8115e6eaea42e03b2 (patch)
treeb61480832e2d7d449b3df7582b30efa80bbe6e56
parentd72037cc78f6ebf00dad060b096e230e47e37e83 (diff)
Implement buffer.release eventbuffer.release-2
-rw-r--r--compositor/compositor.c71
-rw-r--r--compositor/compositor.h6
2 files changed, 77 insertions, 0 deletions
diff --git a/compositor/compositor.c b/compositor/compositor.c
index 0dcfc7c..821718e 100644
--- a/compositor/compositor.c
+++ b/compositor/compositor.c
@@ -26,6 +26,7 @@
#include <stdint.h>
#include <limits.h>
#include <stdarg.h>
+#include <assert.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <unistd.h>
@@ -162,6 +163,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 +219,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 +275,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 +346,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 +611,27 @@ 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 == NULL || --buffer->busy_count > 0)
+ return;
+
+ assert(buffer->client != NULL);
+ 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;
+ 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 +768,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 +928,14 @@ surface_attach(struct wl_client *client,
{
struct wlsc_surface *es = (struct wlsc_surface *) surface;
+ buffer->busy_count++;
+ 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 +1708,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 2546d58..2b7c11d 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