This fixes tearing with multi head.
}
static void
-frame_callback(void *data, uint32_t time)
+frame_callback(struct wl_surface *surface, void *data, uint32_t time)
{
struct gears *gears = data;
window_schedule_redraw(gears->window);
wl_display_frame_callback(display_get_display(gears->d),
+ window_get_wl_surface(gears->window),
frame_callback, gears);
}
draw_gears(gears);
wl_display_frame_callback(display_get_display(gears->d),
+ window_get_wl_surface(gears->window),
frame_callback, gears);
return gears;
};
static void
-frame_callback(void *data, uint32_t time)
+frame_callback(struct wl_surface *surface, void *data, uint32_t time)
{
struct resizor *resizor = data;
double force, height;
if (fabs(resizor->height.previous - resizor->height.target) > 0.1) {
wl_display_frame_callback(display_get_display(resizor->display),
+ window_get_wl_surface(resizor->window),
frame_callback, resizor);
}
}
switch (sym) {
case XK_Down:
resizor->height.target = 400;
- frame_callback(resizor, 0);
+ frame_callback(window_get_wl_surface(window), resizor, 0);
break;
case XK_Up:
resizor->height.target = 200;
- frame_callback(resizor, 0);
+ frame_callback(window_get_wl_surface(window), resizor, 0);
break;
}
}
}
static void
-redraw(void *data, uint32_t time)
+redraw(struct wl_surface *surface, void *data, 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, redraw, window);
+ wl_display_frame_callback(window->display->display,
+ window->surface,
+ redraw, window);
}
static void
create_surface(&window);
init_gl(&window);
- wl_display_frame_callback(display.display, redraw, &window);
+ wl_display_frame_callback(display.display, window.surface,
+ redraw, &window);
wl_display_get_fd(display.display, event_mask_update, &display);
while (true)
}
static void
-frame_callback(void *data, uint32_t time)
+frame_callback(struct wl_surface *surface, void *data, uint32_t time)
{
struct smoke *smoke = data;
window_damage(smoke->window, 0, 0, smoke->width, smoke->height);
wl_display_frame_callback(display_get_display(smoke->display),
+ window_get_wl_surface(smoke->window),
frame_callback, smoke);
}
window_set_user_data(smoke.window, &smoke);
wl_display_frame_callback(display_get_display(d),
+ window_get_wl_surface(smoke.window),
frame_callback, &smoke);
display_run(d);
return cairo_surface_reference(window->cairo_surface);
}
+struct wl_surface *
+window_get_wl_surface(struct window *window)
+{
+ return window->surface;
+}
+
static int
get_pointer_location(struct window *window, int32_t x, int32_t y)
{
cairo_surface_t *
window_get_surface(struct window *window);
+struct wl_surface *
+window_get_wl_surface(struct window *window);
+
void
window_flush(struct window *window);
return 0;
}
-static void
-drm_compositor_present(struct wlsc_compositor *ec)
+static int
+drm_output_present(struct wlsc_output *output_base)
{
- struct drm_compositor *c = (struct drm_compositor *) ec;
- struct drm_output *output;
+ struct drm_output *output = (struct drm_output *) output_base;
+ struct drm_compositor *c =
+ (struct drm_compositor *) output->base.compositor;
- wl_list_for_each(output, &ec->output_list, base.link) {
- if (drm_output_prepare_render(&output->base))
- continue;
- glFlush();
+ if (drm_output_prepare_render(&output->base))
+ return -1;
+ glFlush();
+
+ output->current ^= 1;
- output->current ^= 1;
+ drmModePageFlip(c->drm.fd, output->crtc_id,
+ output->fb_id[output->current ^ 1],
+ DRM_MODE_PAGE_FLIP_EVENT, output);
- drmModePageFlip(c->drm.fd, output->crtc_id,
- output->fb_id[output->current ^ 1],
- DRM_MODE_PAGE_FLIP_EVENT, output);
- }
+ return 0;
}
static void
unsigned int sec, unsigned int usec, void *data)
{
struct wlsc_output *output = data;
- struct wlsc_compositor *compositor = output->compositor;
uint32_t msecs;
- /* run synchronized to first output, ignore other pflip events.
- * FIXME: support per output/surface frame callbacks */
- if (output == container_of(compositor->output_list.prev,
- struct wlsc_output, link)) {
- msecs = sec * 1000 + usec / 1000;
- wlsc_compositor_finish_frame(compositor, msecs);
- }
+ msecs = sec * 1000 + usec / 1000;
+ wlsc_output_finish_frame(output, msecs);
}
static void
}
output->base.prepare_render = drm_output_prepare_render;
+ output->base.present = drm_output_present;
wl_list_insert(ec->base.output_list.prev, &output->base.link);
}
ec->base.destroy = drm_destroy;
- ec->base.present = drm_compositor_present;
ec->base.create_buffer = wlsc_shm_buffer_create;
ec->base.focus = 1;
}
static void
-frame_callback(void *data, uint32_t time)
+frame_callback(struct wl_surface *surface, void *data, uint32_t time)
{
- struct wayland_compositor *c = (struct wayland_compositor *) data;
+ struct wlsc_output *output = data;
- wlsc_compositor_finish_frame(&c->base, time);
+ wlsc_output_finish_frame(output, time);
}
static int
return 0;
}
-static void
-wayland_compositor_present(struct wlsc_compositor *base)
+static int
+wayland_output_present(struct wlsc_output *output_base)
{
- struct wayland_compositor *c = (struct wayland_compositor *) base;
- struct wayland_output *output;
+ struct wayland_output *output = (struct wayland_output *) output_base;
+ struct wayland_compositor *c =
+ (struct wayland_compositor *) output->base.compositor;
- wl_list_for_each(output, &base->output_list, base.link) {
- if (wayland_output_prepare_render(&output->base))
- continue;
+ if (wayland_output_prepare_render(&output->base))
+ return -1;
- eglSwapBuffers(c->base.display, output->egl_surface);
- }
+ eglSwapBuffers(c->base.display, output->egl_surface);
+ wl_display_frame_callback(c->parent.display,
+ output->parent.surface,
+ frame_callback, &output->base);
- wl_display_frame_callback(c->parent.display, frame_callback, c);
+ return 0;
}
static int
glClearColor(0, 0, 0, 0.5);
output->base.prepare_render = wayland_output_prepare_render;
+ output->base.present = wayland_output_present;
wl_list_insert(c->base.output_list.prev, &output->base.link);
return NULL;
c->base.destroy = wayland_destroy;
- c->base.present = wayland_compositor_present;
c->base.create_buffer = wlsc_shm_buffer_create;
/* Can't init base class until we have a current egl context */
return 0;
}
-static void
-x11_compositor_present(struct wlsc_compositor *base)
+static int
+x11_output_present(struct wlsc_output *output_base)
{
- struct x11_compositor *c = (struct x11_compositor *) base;
- struct x11_output *output;
+ struct x11_output *output = (struct x11_output *) output_base;
+ struct wlsc_compositor *ec = output->base.compositor;
struct timeval tv;
uint32_t msec;
- wl_list_for_each(output, &c->base.output_list, base.link) {
- if (x11_output_prepare_render(&output->base))
- continue;
+ if (x11_output_prepare_render(&output->base))
+ return -1;
- eglSwapBuffers(c->base.display, output->egl_surface);
- }
+ eglSwapBuffers(ec->display, output->egl_surface);
gettimeofday(&tv, NULL);
msec = tv.tv_sec * 1000 + tv.tv_usec / 1000;
- wlsc_compositor_finish_frame(&c->base, msec);
+ wlsc_output_finish_frame(&output->base, msec);
+
+ return 0;
}
static void
}
output->base.prepare_render = x11_output_prepare_render;
+ output->base.present = x11_output_present;
wl_list_insert(c->base.output_list.prev, &output->base.link);
return NULL;
c->base.destroy = x11_destroy;
- c->base.present = x11_compositor_present;
c->base.create_buffer = wlsc_shm_buffer_create;
/* Can't init base class until we have a current egl context */
}
void
-wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs)
+wlsc_output_finish_frame(struct wlsc_output *output, int msecs)
{
- wl_display_post_frame(compositor->wl_display, 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);
+ }
+ }
+
+ output->finished = 1;
+
wl_event_source_timer_update(compositor->timer_source, 5);
compositor->repaint_on_timeout = 1;
}
{
struct wlsc_compositor *ec = data;
struct wlsc_output *output;
+ int repainted_all_outputs = 1;
- if (!ec->repaint_needed) {
- ec->repaint_on_timeout = 0;
- return;
- }
+ wl_list_for_each(output, &ec->output_list, link) {
+ if (!output->repaint_needed)
+ continue;
+
+ if (!output->finished) {
+ repainted_all_outputs = 0;
+ continue;
+ }
- wl_list_for_each(output, &ec->output_list, link)
wlsc_output_repaint(output);
+ output->finished = 0;
+ output->present(output);
- ec->present(ec);
+ output->repaint_needed = 0;
+ }
- ec->repaint_needed = 0;
+ if (repainted_all_outputs)
+ ec->repaint_on_timeout = 0;
+ else
+ wl_event_source_timer_update(ec->timer_source, 1);
}
void
wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor)
{
- compositor->repaint_needed = 1;
+ struct wlsc_output *output;
+
+ wl_list_for_each(output, &compositor->output_list, link)
+ output->repaint_needed = 1;
+
if (compositor->repaint_on_timeout)
return;
wl_resource_destroy(&surface->resource, client);
}
+void
+wlsc_surface_assign_output(struct wlsc_surface *es)
+{
+ struct wlsc_compositor *ec = es->compositor;
+ struct wlsc_output *output;
+
+ struct wlsc_output *tmp = es->output;
+ es->output = NULL;
+
+ wl_list_for_each(output, &ec->output_list, link) {
+ if (output->x < es->x && es->x < output->x + output->width &&
+ output->y < es->y && es->y < output->y + output->height) {
+ if (output != tmp)
+ printf("assiging surface %p to output %p\n",
+ es, output);
+ es->output = output;
+ }
+ }
+
+ if (es->output == NULL) {
+ printf("no output found\n");
+ es->output = container_of(ec->output_list.next,
+ struct wlsc_output, link);
+ }
+}
+
static void
surface_attach(struct wl_client *client,
struct wl_surface *surface, struct wl_buffer *buffer,
es->y += y;
es->width = buffer->width;
es->height = buffer->height;
+ if (x != 0 || y != 0)
+ wlsc_surface_assign_output(es);
wlsc_surface_update_matrix(es);
}
struct wl_surface *surface)
{
struct wlsc_surface *es = (struct wlsc_surface *) surface;
+ struct wlsc_compositor *ec = es->compositor;
switch (es->map_type) {
case WLSC_SURFACE_MAP_UNMAPPED:
es->x = 10 + random() % 400;
es->y = 10 + random() % 400;
wlsc_surface_update_matrix(es);
+ /* assign to first output */
+ es->output = container_of(ec->output_list.next,
+ struct wlsc_output, link);
wl_list_insert(&es->compositor->surface_list, &es->link);
break;
case WLSC_SURFACE_MAP_TOPLEVEL:
switch (es->map_type) {
case WLSC_SURFACE_MAP_UNMAPPED:
wl_list_insert(&es->compositor->surface_list, &es->link);
+ /* assign to parents output */
+ es->output = pes->output;
break;
case WLSC_SURFACE_MAP_FULLSCREEN:
es->fullscreen_output = NULL;
struct wlsc_surface *es = (struct wlsc_surface *) surface;
struct wlsc_output *output;
+ /* FIXME: Fullscreen on first output */
+ /* FIXME: Handle output going away */
+ output = container_of(es->compositor->output_list.next,
+ struct wlsc_output, link);
+
switch (es->map_type) {
case WLSC_SURFACE_MAP_UNMAPPED:
es->x = 10 + random() % 400;
es->y = 10 + random() % 400;
+ /* assign to first output */
+ es->output = output;
wl_list_insert(&es->compositor->surface_list, &es->link);
break;
case WLSC_SURFACE_MAP_FULLSCREEN:
break;
}
- /* FIXME: Fullscreen on first output */
- /* FIXME: Handle output going away */
- output = container_of(es->compositor->output_list.next,
- struct wlsc_output, link);
-
es->saved_x = es->x;
es->saved_y = es->y;
es->x = (output->width - es->width) / 2;
background_create(output, option_background);
output->flags = flags;
+ output->finished = 1;
wlsc_output_move(output, x, y);
output->object.interface = &wl_output_interface;
int32_t x, y, width, height;
pixman_region32_t previous_damage_region;
uint32_t flags;
+ int repaint_needed;
+ int finished;
int (*prepare_render)(struct wlsc_output *output);
+ int (*present)(struct wlsc_output *output);
};
enum wlsc_pointer_type {
/* Repaint state. */
struct wl_event_source *timer_source;
- int repaint_needed;
int repaint_on_timeout;
struct timespec previous_swap;
pixman_region32_t damage_region;
void (*destroy)(struct wlsc_compositor *ec);
int (*authenticate)(struct wlsc_compositor *c, uint32_t id);
- void (*present)(struct wlsc_compositor *c);
struct wl_buffer *(*create_buffer)(struct wlsc_compositor *c,
int32_t width, int32_t height,
int32_t stride, struct wl_visual *visual,
struct wlsc_matrix matrix_inv;
struct wl_visual *visual;
struct wl_buffer *buffer;
+ struct wlsc_output *output;
enum wlsc_surface_map_type map_type;
struct wlsc_output *fullscreen_output;
};
struct wl_array *keys);
void
-wlsc_compositor_finish_frame(struct wlsc_compositor *compositor, int msecs);
+wlsc_output_finish_frame(struct wlsc_output *output, int msecs);
void
wlsc_compositor_schedule_repaint(struct wlsc_compositor *compositor);
void
+wlsc_surface_assign_output(struct wlsc_surface *surface);
+
+void
wlsc_surface_damage(struct wlsc_surface *surface);
void
wlsc_surface_damage(es);
es->x = x + move->dx;
es->y = y + move->dy;
+ wlsc_surface_assign_output(es);
wlsc_surface_update_matrix(es);
wlsc_surface_damage(es);
}