}
static void
-sync_callback(void *data)
-{
- int *done = data;
-
- *done = 1;
-}
-
-static void
create_surface(struct window *window)
{
struct display *display = window->display;
EGLBoolean ret;
int done = 0;
+ if (!display->premultiplied_argb_visual)
+ wl_display_roundtrip(display->display);
if (!display->premultiplied_argb_visual) {
- wl_display_sync_callback(display->display, sync_callback, &done);
- while (!done)
- wl_display_iterate(display->display, display->mask);
- if (!display->premultiplied_argb_visual) {
- fprintf(stderr, "premultiplied argb visual missing\n");
- exit(1);
- }
+ fprintf(stderr, "premultiplied argb visual missing\n");
+ exit(1);
}
window->surface = wl_compositor_create_surface(display->compositor);
assert(ret == EGL_TRUE);
}
+static const struct wl_callback_listener frame_listener;
+
static void
-redraw(struct wl_surface *surface, void *data, uint32_t time)
+redraw(void *data, struct wl_callback *callback, uint32_t time)
{
struct window *window = data;
static const GLfloat verts[3][2] = {
glFlush();
eglSwapBuffers(window->display->egl.dpy, window->egl_surface);
- wl_display_frame_callback(window->display->display,
- window->surface,
- redraw, window);
+ if (callback)
+ wl_callback_destroy(callback);
+
+ callback = wl_surface_frame(window->surface);
+ wl_callback_add_listener(callback, &frame_listener, window);
}
+static const struct wl_callback_listener frame_listener = {
+ redraw
+};
+
static void
compositor_handle_visual(void *data,
struct wl_compositor *compositor,
display_handle_global, &display);
wl_display_get_fd(display.display, event_mask_update, &display);
+ wl_display_iterate(display.display, WL_DISPLAY_READABLE);
init_egl(&display);
create_surface(&window);
init_gl(&window);
- redraw(window.surface, &window, 0);
+ redraw(&window, NULL, 0);
while (true)
wl_display_iterate(display.display, display.mask);
return window;
}
+static const struct wl_callback_listener frame_listener;
+
static void
-redraw(struct wl_surface *surface, void *data, uint32_t time)
+redraw(void *data, struct wl_callback *callback, uint32_t time)
{
struct window *window = data;
uint32_t *p;
wl_surface_damage(window->surface,
0, 0, window->width, window->height);
- wl_display_frame_callback(window->display->display,
- window->surface,
- redraw, window);
+ if (callback)
+ wl_callback_destroy(callback);
+
+ callback = wl_surface_frame(window->surface);
+ wl_callback_add_listener(callback, &frame_listener, window);
}
+static const struct wl_callback_listener frame_listener = {
+ redraw
+};
+
static void
compositor_handle_visual(void *data,
struct wl_compositor *compositor,
return 0;
}
-static void
-sync_callback(void *data)
-{
- int *done = data;
-
- *done = 1;
-}
-
static struct display *
create_display(void)
{
struct display *display;
- int done;
display = malloc(sizeof *display);
display->display = wl_display_connect(NULL);
wl_display_get_fd(display->display, event_mask_update, display);
- wl_display_sync_callback(display->display, sync_callback, &done);
while (!display->xrgb_visual)
- wl_display_iterate(display->display, display->mask);
+ wl_display_roundtrip(display->display);
return display;
}
display = create_display();
window = create_window(display, 250, 250);
- redraw(window->surface, window, 0);
+ redraw(window, NULL, 0);
while (true)
wl_display_iterate(display->display, display->mask);
return 0;
}
-static void
-sync_callback(void *data)
-{
- int *done = data;
-
- *done = 1;
-}
-
-static void
-force_roundtrip(struct display *d)
-{
- int done = 0;
-
- wl_display_sync_callback(d->display, sync_callback, &done);
- wl_display_iterate(d->display, WL_DISPLAY_WRITABLE);
- while (!done)
- wl_display_iterate(d->display, WL_DISPLAY_READABLE);
-}
-
struct display *
display_create(int *argc, char **argv[], const GOptionEntry *option_entries,
display_global_handler_t handler)
d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR");
if (!d->premultiplied_argb_visual || !d->rgb_visual) {
- force_roundtrip(d);
+ wl_display_roundtrip(d->display);
if (!d->premultiplied_argb_visual || !d->rgb_visual) {
fprintf(stderr, "failed to retreive visuals\n");
return NULL;
return 0;
}
-static void
-frame_callback(struct wl_surface *surface, void *data, uint32_t time)
-{
- struct wlsc_output *output = data;
-
- wlsc_output_finish_frame(output, time);
-}
-
static int
wayland_output_prepare_render(struct wlsc_output *output_base)
{
return 0;
}
+static void
+frame_done(void *data, struct wl_callback *wl_callback, uint32_t time)
+{
+ struct wlsc_output *output = data;
+
+ wlsc_output_finish_frame(output, time);
+}
+
+static const struct wl_callback_listener frame_listener = {
+ frame_done
+};
+
static int
wayland_output_present(struct wlsc_output *output_base)
{
struct wayland_output *output = (struct wayland_output *) output_base;
struct wayland_compositor *c =
(struct wayland_compositor *) output->base.compositor;
+ struct wl_callback *callback;
if (wayland_output_prepare_render(&output->base))
return -1;
eglSwapBuffers(c->base.display, output->egl_surface);
- wl_display_frame_callback(c->parent.display,
- output->parent.surface,
- frame_callback, &output->base);
+ callback = wl_surface_frame(output->parent.surface);
+ wl_callback_add_listener(callback, &frame_listener, output);
return 0;
}
fade_output(output, ec->fade.spring.current, &total_damage);
}
+struct wlsc_frame_callback {
+ struct wl_resource resource;
+ struct wl_client *client;
+ struct wl_list link;
+};
+
static void
repaint(void *data, int msecs)
{
struct wlsc_output *output = data;
struct wlsc_compositor *compositor = output->compositor;
- struct wlsc_surface *es;
struct wlsc_animation *animation, *next;
+ struct wlsc_frame_callback *cb, *cnext;
wlsc_output_repaint(output);
output->repaint_needed = 0;
output->repaint_scheduled = 1;
output->present(output);
- /* FIXME: Keep the surfaces in an per-output list. */
- wl_list_for_each(es, &compositor->surface_list, link) {
- if (es->output == output) {
- wl_display_post_frame(compositor->wl_display,
- &es->surface, msecs);
- }
+ wl_list_for_each_safe(cb, cnext, &output->frame_callback_list, link) {
+ wl_client_post_event(cb->client, &cb->resource.object,
+ WL_CALLBACK_DONE, msecs);
+ wl_resource_destroy(&cb->resource, cb->client, 0);
}
+ wl_list_init(&output->frame_callback_list);
wl_list_for_each_safe(animation, next,
&compositor->animation_list, link)
wlsc_surface_damage_rectangle(es, x, y, width, height);
}
+static void
+destroy_frame_callback(struct wl_resource *resource, struct wl_client *client)
+{
+ free(resource);
+}
+
+static void
+surface_frame(struct wl_client *client,
+ struct wl_surface *surface, uint32_t callback)
+{
+ struct wlsc_frame_callback *cb;
+ struct wlsc_surface *es = (struct wlsc_surface *) surface;
+
+ cb = malloc(sizeof *cb);
+ if (cb == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ cb->resource.object.interface = &wl_callback_interface;
+ cb->resource.object.id = callback;
+ cb->resource.destroy = destroy_frame_callback;
+ wl_list_insert(es->output->frame_callback_list.prev, &cb->link);
+ cb->client = client;
+
+ wl_client_add_resource(client, &cb->resource);
+}
+
const static struct wl_surface_interface surface_interface = {
surface_destroy,
surface_attach,
- surface_damage
+ surface_damage,
+ surface_frame
};
static void
output->scanout_buffer_destroy_listener.func =
output_handle_scanout_buffer_destroy;
wl_list_init(&output->scanout_buffer_destroy_listener.link);
+ wl_list_init(&output->frame_callback_list);
output->object.interface = &wl_output_interface;
wl_display_add_object(c->wl_display, &output->object);
struct wlsc_compositor *compositor;
struct wlsc_surface *background;
struct wlsc_matrix matrix;
+ struct wl_list frame_callback_list;
int32_t x, y, mm_width, mm_height;
pixman_region32_t region;
pixman_region32_t previous_damage;