diff --git a/src/compositor-drm.c b/src/compositor-drm.c index e1a70e42f..baf2fb531 100644 --- a/src/compositor-drm.c +++ b/src/compositor-drm.c @@ -567,7 +567,7 @@ drm_output_set_gamma(struct weston_output *output_base, weston_log("set gamma failed: %m\n"); } -static void +static int drm_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) { @@ -579,12 +579,12 @@ drm_output_repaint(struct weston_output *output_base, int ret = 0; if (output->destroy_pending) - return; + return -1; if (!output->next) drm_output_render(output, damage); if (!output->next) - return; + return -1; mode = container_of(output->base.current_mode, struct drm_mode, base); if (!output->current) { @@ -594,7 +594,7 @@ drm_output_repaint(struct weston_output *output_base, &mode->mode_info); if (ret) { weston_log("set mode failed: %m\n"); - return; + goto err_pageflip; } output_base->set_dpms(output_base, WESTON_DPMS_ON); } @@ -603,7 +603,7 @@ drm_output_repaint(struct weston_output *output_base, output->next->fb_id, DRM_MODE_PAGE_FLIP_EVENT, output) < 0) { weston_log("queueing pageflip failed: %m\n"); - return; + goto err_pageflip; } output->page_flip_pending = 1; @@ -655,7 +655,15 @@ drm_output_repaint(struct weston_output *output_base, output->vblank_pending = 1; } - return; + return 0; + +err_pageflip: + if (output->next) { + drm_output_release_fb(output, output->next); + output->next = NULL; + } + + return -1; } static void diff --git a/src/compositor-fbdev.c b/src/compositor-fbdev.c index 26433da6c..24140eff3 100644 --- a/src/compositor-fbdev.c +++ b/src/compositor-fbdev.c @@ -194,7 +194,7 @@ fbdev_output_repaint_pixman(struct weston_output *base, pixman_region32_t *damag 1000000 / output->mode.refresh); } -static void +static int fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage) { struct fbdev_output *output = to_fbdev_output(base); @@ -212,6 +212,8 @@ fbdev_output_repaint(struct weston_output *base, pixman_region32_t *damage) wl_event_source_timer_update(output->finish_frame_timer, 1000000 / output->mode.refresh); } + + return 0; } static int diff --git a/src/compositor-headless.c b/src/compositor-headless.c index 2a0b0c3ec..9d9f6dd3f 100644 --- a/src/compositor-headless.c +++ b/src/compositor-headless.c @@ -60,7 +60,7 @@ finish_frame_handler(void *data) return 1; } -static void +static int headless_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) { @@ -74,7 +74,7 @@ headless_output_repaint(struct weston_output *output_base, wl_event_source_timer_update(output->finish_frame_timer, 16); - return; + return 0; } static void diff --git a/src/compositor-rdp.c b/src/compositor-rdp.c index 69f1d0445..8a302f85d 100644 --- a/src/compositor-rdp.c +++ b/src/compositor-rdp.c @@ -302,7 +302,7 @@ rdp_output_start_repaint_loop(struct weston_output *output) weston_output_finish_frame(output, msec); } -static void +static int rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) { struct rdp_output *output = container_of(output_base, struct rdp_output, base); @@ -324,6 +324,7 @@ rdp_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) &ec->primary_plane.damage, damage); wl_event_source_timer_update(output->finish_frame_timer, 16); + return 0; } static void diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c index 05667fb4c..60926325b 100644 --- a/src/compositor-rpi.c +++ b/src/compositor-rpi.c @@ -223,7 +223,7 @@ rpi_output_start_repaint_loop(struct weston_output *output) weston_output_finish_frame(output, time); } -static void +static int rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage) { struct rpi_output *output = to_rpi_output(base); @@ -247,6 +247,7 @@ rpi_output_repaint(struct weston_output *base, pixman_region32_t *damage) /* schedule callback to rpi_output_update_complete() */ rpi_dispmanx_update_submit(update, output); DBG("frame update submitted\n"); + return 0; } static void diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c index 77b2a2cc4..f3b03619b 100644 --- a/src/compositor-wayland.c +++ b/src/compositor-wayland.c @@ -210,7 +210,7 @@ wayland_output_start_repaint_loop(struct weston_output *output_base) wl_surface_commit(output->parent.surface); } -static void +static int wayland_output_repaint(struct weston_output *output_base, pixman_region32_t *damage) { @@ -225,7 +225,7 @@ wayland_output_repaint(struct weston_output *output_base, pixman_region32_subtract(&ec->primary_plane.damage, &ec->primary_plane.damage, damage); - + return 0; } static void diff --git a/src/compositor-x11.c b/src/compositor-x11.c index 704e751ec..7cda30a4e 100644 --- a/src/compositor-x11.c +++ b/src/compositor-x11.c @@ -324,7 +324,7 @@ x11_output_start_repaint_loop(struct weston_output *output) weston_output_finish_frame(output, msec); } -static void +static int x11_output_repaint_gl(struct weston_output *output_base, pixman_region32_t *damage) { @@ -337,6 +337,7 @@ x11_output_repaint_gl(struct weston_output *output_base, &ec->primary_plane.damage, damage); wl_event_source_timer_update(output->finish_frame_timer, 10); + return 0; } static void @@ -444,7 +445,7 @@ set_clip_for_output(struct weston_output *output_base, pixman_region32_t *region } -static void +static int x11_output_repaint_shm(struct weston_output *output_base, pixman_region32_t *damage) { @@ -475,6 +476,7 @@ x11_output_repaint_shm(struct weston_output *output_base, } wl_event_source_timer_update(output->finish_frame_timer, 10); + return 0; } static int diff --git a/src/compositor.c b/src/compositor.c index 566586332..bfad05d4e 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -1365,7 +1365,7 @@ weston_compositor_build_surface_list(struct weston_compositor *compositor) } } -static void +static int weston_output_repaint(struct weston_output *output, uint32_t msecs) { struct weston_compositor *ec = output->compositor; @@ -1374,6 +1374,7 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs) struct weston_frame_callback *cb, *cnext; struct wl_list frame_callback_list; pixman_region32_t output_damage; + int r; /* Rebuild the surface list and update surface transforms up front. */ weston_compositor_build_surface_list(ec); @@ -1404,7 +1405,7 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs) if (output->dirty) weston_output_update_matrix(output); - output->repaint(output, &output_damage); + r = output->repaint(output, &output_damage); pixman_region32_fini(&output_damage); @@ -1422,6 +1423,8 @@ weston_output_repaint(struct weston_output *output, uint32_t msecs) animation->frame_counter++; animation->frame(animation, output, msecs); } + + return r; } static int @@ -1440,15 +1443,16 @@ weston_output_finish_frame(struct weston_output *output, uint32_t msecs) struct weston_compositor *compositor = output->compositor; struct wl_event_loop *loop = wl_display_get_event_loop(compositor->wl_display); - int fd; + int fd, r; output->frame_time = msecs; if (output->repaint_needed && compositor->state != WESTON_COMPOSITOR_SLEEPING && compositor->state != WESTON_COMPOSITOR_OFFSCREEN) { - weston_output_repaint(output, msecs); - return; + r = weston_output_repaint(output, msecs); + if (!r) + return; } output->repaint_scheduled = 0; diff --git a/src/compositor.h b/src/compositor.h index 09c386479..b8d173a27 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -219,7 +219,7 @@ struct weston_output { struct wl_list mode_list; void (*start_repaint_loop)(struct weston_output *output); - void (*repaint)(struct weston_output *output, + int (*repaint)(struct weston_output *output, pixman_region32_t *damage); void (*destroy)(struct weston_output *output); void (*assign_planes)(struct weston_output *output);